Why operator cannot be in parentheses? - c++

The question comes when I tried to make a macro like this:
#define OP1(a,b,op) (a) op (b)
then I was wondering why not also put op into parentheses, as it is also a macro parameter.
I then find I cannot even have this:
1 (+) 1;
otherwise there will be error:
error: expected primary-expression before ')' token
Can anyone tell me where is the rule saying operator cannot be in parentheses? I really cannot find it. Thank you.

ยง 7.6.6 (expr.add) defines "additive expressions" as:
additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression
No parens around the operator allowed.

There actually isn't any rule that says an operator should not be in parenthesis. But there is a rule that states that, "for a binary operator like +, the value on either sides of the operator must be valid operands like 5, 5.2".
So the expression (+) to the compiler means you are adding two parentheses (left paren, plus, right paren) together which is not supported by the language.
Putting macro parameters in parenthesis is good practice of course, but there is actually no need for putting the operator in this case inside parenthesis as there is no way of passing a complicated operator expression so you can rest assured that your macro will always work.

In programming, as in mathematics, the parentheses are used to override the operators precedence.
Without parentheses, 2 + 3 * 4 is evaluated as 2 + (3 * 4) because the multiplication (*) has a higher precedence than the addition (+). One can use parentheses to force the addition of 2 and 3 happen before the multiplication (of the result) by 4 by placing them around the addition operator and its operands as (2 + 3) * 4.
Both 3 * 4 and 2 + 3 in the expressions above are valid expressions.
+ in the expression 1 (+) 2 is not a valid expression. More, assuming the parentheses contain a valid sub-expression, the entire expression is invalid because it is just a list of values without operators to connect them into an expression.
Even more, this is also not the way you learned in school to write mathematical expressions.
Back to your #define, to avoid hidden errors and headache (due to the operators precedence) you should always enclose the expanded value of such a macro into parentheses like this:
#define OP1(a,b,op) ((a) op (b))

Related

Can parentheses override an expression's order of evaluation? [duplicate]

This question already has answers here:
Operator Precedence vs Order of Evaluation
(6 answers)
Closed 5 years ago.
Grouping operators and operands and Order of Evaluation are two important concepts of expression in C++.
Grouping
For expression with multiple operators, how the operands grouped with the specific operators is decided by the precedence and associativity of the operators and may depend on the order of evaluation.
Order
In C++, only 4 operators have the specified order of evaluations (logical AND, logical OR, conditional and comma operator). For the other operators, the evaluation order is unspecified.
Parentheses
Parentheses can override the precedence and associativity, and therefore specify the grouping of a compound expression.
However, the book by Peter Gottschling claims the parentheses can change the order of the evaluation. I personally doubt it; I think it's an error! In the example from the quotation below, the parentheses do not tell which expression of x, y and z is evaluated first, which one is later and which one is the last. It only groups the expression y + z as the left operand of the * operator.
An expression surrounded by parentheses is an expression as well,
e.g., (x + y). As this grouping by parentheses precedes all operators,
we can change the order of evaluation to suit our needs: x * (y + z)
computes the addition first. Discovering Modern C++, Chapter 1.4.1
Question
Can parentheses override expressions' order of evaluation?
The quoted sentence is poorly worded. The author didn't mean that the order of evaluation is changed, or even specified; I think the word "order" was meant in terms of how a human might read the expression (i.e. precedence).
Of course, if the three variables are independent and reading them has no side-effects, the "as if" rule makes the unspecified order irrelevant, as it wouldn't change the value of the expression.

Type conversion with float_of_int

I am starting with ocaml and tried:
float_of_int 8/2;;
I was expecting that it returns 4.0 because 8/2 is 4 but I get an error saying that:
Error: This expression has type float but an expression was expected of type
int
What am I missing here?
Your expression is parsed like this:
(float_of_int 8) / 2
So you're asking to divide a float using /, which applies to ints.
Function application (indicated in OCaml by putting two expressions side by side) has very high precedence, higher than all the binary infix operators. So you need to use parentheses.
It will work if you write:
float_of_int (8/2)
After reading Jeffrey's answer, I found another way to work with the expression though a little longer statement:
float_of_int 8/. float_of_int 2;;

What's the difference between the comma operator and the comma separator? [duplicate]

This question already has answers here:
How does the compiler know that the comma in a function call is not a comma operator?
(6 answers)
Closed 8 years ago.
In C++, the comma token (i.e., ,) is either interpreted as a comma operator or as a comma separator.
However, while searching in the web I realized that it's not quite clear in which cases the , token is interpreted as the binary comma operator and where is interpreted as a separator between statements.
Moreover, considering multiple statements/expressions in one line separated by , (e.g., a = 1, b = 2, c = 3;), there's a turbidness on the order in which they are evaluated.
Questions:
In which cases a comma , token is interpreted as an operator and in which as a separator?
When we have one line multiple statements/expressions separated by comma what's the order of evaluation for either the case of the comma operator and the case of the comma separator?
When a separator is appropriate -- in arguments to a function call or macro, or separating values in an initializer list (thanks for the reminder, #haccks) -- comma will be taken as a separator. In other expressions, it is taken as an operator. For example,
my_function(a,b,c,d);
is a call passing four arguments to a function, whereas
result=(a,b,c,d);
will be understood as the comma operator. It is possible, through ugly, to intermix the two by writing something like
my_function(a,(b,c),d);
The comma operator is normally evaluated left-to-right.
The original use of this operation in C was to allow a macro to perform several operations before returning a value. Since a macro instantiation looks like a function call, users generally expect it to be usable anywhere a function call could be; having the macro expand to multiple statements would defeat that. Hence, C introduced the , operator to permit chaining several expressions together into a single expression while discarding the results of all but the last.
As #haccks pointed out, the exact rules for how the compiler determines which meaning of , was intended come out of the language grammar, and have previously been discussed at How does the compiler know that the comma in a function call is not a comma operator?
You cannot use comma to separate statements. The , in a = 1, b = 2; is the comma operator, whose arguments are two assignment expressions. The order of evaluation of the arguments of the comma operator is left-to-right, so it's clear what the evaluation order is in that case.
In the context of the arguments to a function-call, those arguments cannot be comma-expressions, so the top-level commas must be syntactic (i.e. separating arguments). In that case, the evaluation order is not specified. (Of course, the arguments might be parenthesized expressions, and the parenthesized expression might be a comma expression.)
This is expressed clearly in the grammar in the C++ standard. The relevant productions are expression, which can be:
assignment-expression
or
expression , assignment-expression
and expression-list, which is the same as an initializer-list, which is a ,-separated list of initializer-clause, where an initializer-clause is either:
assignment-expression
or
braced-init-list
The , in the second expression production is the comma-operator.

Shunting-yard: missing argument to operator

I'm implementing the shunting-yard algorithm. I'm having trouble detecting when there are missing arguments to operators. The wikipedia entry is very bad on this topic, and their code also crashes for the example below.
For instance 3 - (5 + ) is incorrect because the + is missing an argument.
Just before the algorithm reaches the ), the operator stack contains - ( + and the operand stack contains 3 5. Then it goes like this:
it pops + from the operator stack
discovers that + is a binary operator
pops two operands, apply operator and push result (8) to operand stack
then it pops the matching ( from the stack, and continues
So how can I detect that the + is missing an argument? extra kudos if you also update wikipedia :-)
For binary operator only expressions, the postfix expression has the invariant that in any prefix of the expression, numbers of operands > numbers of operators and in the end, that difference is exactly one.
So you can verify the RPN expression for validity at each stage of the shunting yard by maintaining a running count of number of operands - number of operators. If that drops below one, or becomes more than one at the end, you have an error.
It does not pinpoint the error, but at least lets you know there is one.
(Note: I haven't tried proving the above fact, but seems like it will work)
You can build a state machine. It can spot the tokens where something is wrong.
When you start reading the expression expect a prefix operator or an operand.
If you read a prefix operator expect a prefix operator, operand or opening parenthesis.
If you read an operand expect a postfix or and infix operator or a closing parenthesis.
If you read a postfix operator expect and infix operator or a closing parenthesis.
If you read an infix operator expect a prefix operator, operand or opening parenthesis.
If you read an opening parenthesis expect a prefix operator, operand or opening parenthesis.
if you read a closing parenthesis expect a postfix or and infix operator or a closing parenthesis.
You can turn these ifs to a switch easily. :)

What's the formal name for this Syntax?

Sometimes in Scheme, I have functions that take arguments like this
add 3 4
What do you call this kind of "list" where it's elements are like a1 a2 a3 ? I don't think you can call it a list because lists are contained in parenthesis and elements are comma-seperated.
The (add 3 4) statement is "function application" from the lambda calculus. The 3 4 from the expression are bindings for the parameters; alternatively, it is the parameter list for the function.
s-expression?
Lisp uses prefix or Polish notation syntax.
Polish notation, also known as prefix
notation, is a form of notation for
logic, arithmetic, and algebra. Its
distinguishing feature is that it
places operators to the left of their
operands. If the arity of the
operators is fixed, the result is a
syntax lacking parentheses or other
brackets, that can still be parsed
without ambiguity.
add is the operator and the right part are the operands.
The arity of the operators isn't fixed so Lisp uses parens in it's syntax to group the expressions.