Reputation: 199
I created EBNF for expressions below
<expression> ::= <or_operand> [ "or" <or_operand> ]
<or_operand> ::= <and_operand> [ "and" <and_operand> ]
<and_operand> ::= <equality_operand> [ ( "=" | "!=" ) <equality_operand> ]
<equality_operand> ::= <simple_expression> [ <relational_operator> <simple_expression> ]
<relational_op> ::= "<" | ">" | "<=" | ">="
<simple_expression> ::= <term> [ ( "+" | "-" ) <term> ]
<term> ::= <factor> [ ( "*" | "/" ) <factor> ]
<factor> ::= <literal>
| "(" <expression> ")"
| "not" <factor>
| ( "+" | "-" ) <factor>
<literal> ::= <boolean_literal> | <number>
<boolean_literal> ::= "true" | "false"
<number> ::= <digit> [ <digit> ]
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
My problem lies within the factor section
<factor> ::= <literal>
| "(" <expression> ")"
| "not" <factor>
| ( "+" | "-" ) <factor>
You can see that I included three unary operators not
, -
, and +
. They work for specific types like not
only applies to boolean values only and +
/-
applies to numbers only.
I don't know how to handle cases when not
is mixed with +
/-
like not +7
, - not true
, etc. for example. Is there any way I can modify the grammar so not
can never be mixed with +
/-
?
Will it suffice?
<factor> ::= <literal>
| "(" <expression> ")"
| ( "not" | ( "+" | "-" ) ) <factor>
Or maybe it's parser's job to solve this issue?
Upvotes: 0
Views: 306
Reputation: 5893
This is quite easy to solve. You have two different styles of expressions each with their own syntax, so you just do not mix them, and keep their syntax rules separated.
A boolean expression can only occur in certain places, such as an assignment or some kind of choice statement. A numerical expression can only occur in a comparison or an assignment. This is not something that is handled at the semantic level, and if one looks at the grammar for many languages, this is how it is solved.
So you have for numeric expressions:
<simple_expression> ::= <term> [ ( "+" | "-" ) <term> ]
<term> ::= <factor> [ ( "*" | "/" ) <factor> ]
<factor> ::= <number>
| "(" <expression> ")"
| ( "+" | "-" ) <factor>
<number> ::= <digit> [ <digit> ]
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
This is now self contained. We can now build this into boolean expressions:
<boolean_expression> ::= "not" <boolean_expression>
| <logical_expression>
<logical_expression> ::= <or_operand> [ "or" <or_operand> ]
<or_operand> ::= <and_operand> [ "and" <and_operand> ]
<and_operand> ::= <equality_operand> [ ( "=" | "!=" ) <equality_operand> ]
<equality_operand> ::= <simple_expression> [ <relational_operator> <simple_expression> ]
| <boolean_literal>
<relational_op> ::= "<" | ">" | "<=" | ">="
<boolean_literal> ::= "true" | "false"
Notice that I permitted the equality comparison of boolean literals, however if you did not want to permit this you could change the rules to only permit them for an and operand.
Now we can use these in another rule, such as assignment:
<assignment> ::= <variable> ":=" ( <simple_expression> | <boolean_expression> )
All is done.
Upvotes: 1