I'm guessing you're coming from a programming language where every expression must evaluate to a value, and if it didn't evaluate to something (like 5[Cos+Sin]), it's a syntax error. To me, Mathematica started to make a lot more sense, once I stopped thinking about functions and values, and started to think of every expression as evaluating to an "expression tree". (Note to long-time Mathematica users: I'm trying to explain this form the point of view of someone coming from a different programming language. I'm glossing over a lot of details like Set vs SetDelayed, Evaluate and Hold, but the "conceptual model" I'm trying to explain here was very useful for me when I started with MMA.)
So, e.g. a+b*c yields an expression tree. You can use TreeForm[a + b*c] to display the actual tree:

The same is true for a[b*c], or even (b*c)[a]. Think of these things as tree data structures, not as expressions as you might know them from C or Perl. For instance, you can access parts of that data structure using normal array-index syntax: (a + b*c) [[2, 1]] yields b. There are a few basic rules how operators can be combined, so e.g. a+*b or x=[b] are invalid, but other than that, you can build any tree you want.
The next step is that you can tell Mathematica tree manipulation rules that it should automatically apply to these trees. You could for example write:
a[x_ + c] := "Hello"
Now, any time Mathematica evaluates a tree that matches the pattern a[x_ + c], it will replace it with "Hello". Don't think of this as a function declaration. Think of it as a replacement rule. And you can define almost any kind of pattern matching and replacement rule. For example, you could write the replacement rule:
(x_ + b)[y_] := x*y
and Mathematica would from then on happily evaluate an expression like (5+b)[6] to 30.
(Note: Don't actually do this. It's a bad idea. In fact, it's such a bad idea that the people at Wolfram decided to protect the symbol Plus from being overwritten, to prevent you from doing this. But if you Unprotect[Plus], you could actually do this.)
All this is a bit confusing when you're coming from a "conventional" programming language. But it is extremely useful for manipulating symbolic expressions. For example, with the knowledge you have now, you could probably write a function that takes the derivative of a basic arithmetic expression in about 10 lines. Try that in a conventional programming language!