Language Change Specification for Precedence of Unary Operators
LCS Number: |
LCS-2016-13 |
Version: |
5 |
Date: |
v4 8-Feb-2017 v5 2-Mar-2017 |
Status: |
|
Author: |
Peter Flake |
Email: |
|
Source Doc: |
Unary Precedence |
Summary: |
Remove ambiguity of precedence of unary operators in formal syntax |
Voting Results: Cast your votes here
* Yes:
-
Peter Flake - 2016-12-20
-
Jim Lewis - 2017-02-07 ver 3
-
Brent Hayhoe - 2017-02-02
-
Lieven Lemiengre - 2017-02-02
-
Rob Gaddi - 2017-03-02 ver 5
-
Thomas Preusser - 2017-02-08 - ver 3
-
Patrick Lehmann - 2017-03-02 ver 5
* No:
-
* Abstain:
-
Details of Language Change:
Key:
- Existing LRM text is shown in BLACK font
- Additional LRM text is shown in RED
- Deleted LRM text is shown in
RED with strike-through
LRM 9 Expressions
page 117
9.1 General
An expression is a formula that defines the computation of a value.
expression ::=
condition_operator primary
| logical_expression
logical_expression ::=
relation { and relation }
| relation { or relation }
| relation { xor relation }
| relation [ nand relation ]
| relation [ nor relation ]
| relation { xnor relation }
relation ::=
shift_expression [ relational_operator shift_expression ]
shift_expression ::=
simple_expression [ shift_operator simple_expression ]
simple_expression ::=
[ sign ] term { adding_operator term }
term ::=
factor { multiplying_operator factor }
factor ::=
primary [ ** primary ]
| abs primary
| not primary
| logical_operator primary
factor ::=
unary_expression [ ** unary_expression ]
unary_expression ::=
primary
| abs primary
| not primary
| unary_logical_operator primary
primary ::=
name
| literal
| aggregate
| function_call
| qualified_expression
| type_conversion
| allocator
| ( expression )
Each primary has a value and a type. The only names allowed as primaries are attributes that yield values and names denoting objects or values. In the case of names denoting objects other than objects of file types or protected types, the value of the primary is the value of the object. In the case of names denoting either file objects or objects of protected types, the value of the primary is the entity denoted by the name. The type of an expression depends only upon the types of its operands and on the operators applied; for an overloaded operand or operator, the determination of the operand type, or the identification of the overloaded operator, depends on the context (see 12.5). For each predefined operator, the operand and result types are given in the following subclause.
NOTE 1—The syntax for an expression involving logical operators allows a sequence of binary and, or, xor, or xnor operators (whether predefined or user-defined), since the corresponding predefined operations are associative. For the binary operators nand and nor (whether predefined or user-defined), however, such a sequence is not allowed, since the corresponding predefined operations are not associative.
NOTE 2—The syntax for an expression involving a unary condition operator or unary logical operator in combination with any other operator requires that the unary operator and its operand be a parenthesized expression. For example, the expressions “(and A) and B” and “A and (and B)” are legal, whereas the expression “and A and B” and “A and and B” are not. Similarly, “and (and A)” is legal, whereas “and and A” is not. An expression consisting only of a unary condition oprator or unary logical operator and its operand need not be parenthesized.
NOTE 2 3—PSL extends the grammar of VHDL expressions to allow PSL expressions, PSL built-in function calls, and PSL union expressions as subexpressions. Such extended expressions can only appear in a VHDL description within PSL declarations and PSL directives, or in a verification unit.
9.2 Operators
9.2.1 General
The operators that may be used in expressions are defined as follows. Each operator belongs to a class of operators, all of which have the same precedence level; the classes of operators are listed in order of increasing precedence.
condition_operator ::= ??
logical_operator ::= and | or | nand | nor | xor | xnor
relational_operator ::= = | /= | < | <= | > | >= | ?= | ?/= | ?< | ?<= | ?> | ?>=
shift_operator ::= sll | srl | sla | sra | rol | ror
adding_operator ::= + | – | &
sign ::= + | –
multiplying_operator ::= * | / | mod | rem
binary _miscellaneous_operator ::= **
unary miscellaneous_operator ::= ** | abs | not | _unary _logical_operator
Operators of higher precedence are associated with their operands before operators of lower precedence. Where the language allows a sequence of operators, operators with the same precedence level are associated with their operands in textual order, from left to right. The precedence of an operator is fixed and cannot be changed by the user, but parentheses can be used to control the association of operators and operands. In general, operands in an expression are evaluated before being associated with operators. For certain operations, however, the right-hand operand is evaluated if and only if the left-hand operand has a certain value. These operations are called short-circuit operations. The binary logical operations and, or, nand, and nor defined for operands of types BIT and BOOLEAN are all short-circuit operations; furthermore, these are the only short-circuit operations.
Every predefined operator and every predefined MINIMUM and MAXIMUM operation is a pure function (see 4.2.1). No predefined operators have named formal parameters; therefore, named association (see 6.5.7.1) cannot be used when invoking a predefined operator.
NOTE 1—The predefined operators for the standard types are declared in package STANDARD as shown in 16.3.
NOTE 2—The operator not is classified as a miscellaneous operator for the purposes of defining precedence, but is otherwise classified as a logical operator.
9.2.2 General
[Delete note at end of section on page 120]
NOTE—All of the binary logical operators belong to the class of operators with the lowest precedence. The unary logical operators belong to the class of operators with the highest precedence.
LRM Annex C
page 486
factor ::=
primary [ ** primary ]
| abs primary
| not primary
| logical_operator primary
factor ::=
unary_expression [ ** unary_expression ]
page 500 (top)
unary_expression ::=
primary
| abs primary
| not primary
| unary_logical_operator primary
Comments
In section 9.2.2 - Logical operators is the following: NOTE—All of the binary logical operators belong to the class of operators with the lowest precedence. The unary logical operators belong to the class of operators with the highest precedence.
Perhaps this note needs to be copied (or possibly moved), to section 9.2.1 to define the precedence of unary operators rather than defining new 'unary_expression'. Would seem to me to be simpler way to accomplish the goal of defining unary operator precedence.
--
Kevin Jennings - 2016-12-08
The EBNF rule for "unary_expression" should refer to //unary_//logical_operator. The EBNF rule "miscellaneous_operator" should also use "logical_operator" with "unary_" in italic font.
--
Patrick Lehmann - 2016-12-31
It's not clear what the intent is for the proposed introduction of unary_expression in 9.1. Its effect is that expressions of the form abs x ** y become legal while in 1076-2008 this would have to be written as (abs x) ** y. In my perspective the parenthesized form is clear with regards to associativity while the form that becomes legal with the proposed change is not (I am referring to the expression text; of course it's clear when referring to the LRM). A rationale for the proposed change would be welcome.
Regarding the proposed change to 9.2.1, the prefix unary should be in tialics. The change works because there is no syntactic reference to the production miscellaneous_operators, otherwise the grammar would become ambiguous. However, I second Kevin in his proposal to add a NOTE 3 that repeats the NOTE from 9.2.2.
--
Ernst Christen - 2017-01-26
I agree: NOTE 2 should be removed because it is not true even in the current LRM:
- “and A and B” as well as “A and and B” are legal in VHDL 2008.
- “and (and A)” as well as “and and A” are not possible because after the first reduction, the result will not be an one-dimensional array of type bit or std_logic_vector any more.
EDIT: The BNF should not be changed. I concur with Ernst here. See Patrick's comment below.
--
Martin Zabel - 2017-02-03
By dividing the EBNF rules into two rules for factor
and unary_expression
, you are introducing, as intended, a new level of precedence. You also need to create a new rule/row in 9.2.1 because each line/rule represents one level of precedence. So you need to divide miscellaneous_operator
into two lines to reflect the new precedence levels.
--
Patrick Lehmann - 2017-02-03
I think the note in 9.2.2 needs to be deleted. The lowest precedence is now ??. Like Ernst I too like parentheses, however, only the ** operator requires them. All of the other binary operators do not. Hence, I think the change makes things more consistent. I agree on the usage of unary in itallics in the two places Patrick noted.
WRT precedence of miscellaneous operators (**, abs, not, unary logic operators) the precedence between operators did change, however, the precedence of the group of operators did not change. The precedence between operators was none (parentheses required) and is now left to right. This is still consistent with the LRM text as it allows left to right precedence where the EBNF allows it.
--
Jim Lewis - 2017-02-08
Updated to revision 3 to address comments above
--
Jim Lewis - 2017-02-08
@JimLewis
:
JL: WRT precedence of miscellaneous operators (**, abs, not, unary logic operators) the precedence between operators did change, however, the precedence of the group of operators did not change. The precedence between operators was none (parentheses required) and is now left to right. This is still consistent with the LRM text as it allows left to right precedence where the EBNF allows it.
MZ: I don't understand this. Within each group, all operators have the same precedence, as also stated in clause 9.2.1 paragraph 1. But within an expression, operators with the same precedence level are associated from left to right, as stated in clause 9.2.1 paragraph 3 (below BNF).
Example 1:
a AND b OR c
is the same as (a AND b) OR c
.
Example 2:
a OR b AND c
is the same as (a OR b) AND c
even if OR
is listed after AND
in the group logical_operator
.
Example 3:
abs a ** abs b
is not possible in VHDL-2008, but will be possible with this LCS. The expression equals to (abs a) ** (abs b)
. Thus ** has a higher precedence and must be listed in it's own group.
--
Martin Zabel - 2017-02-08
@MZ
. WRT Example 3: you state: abs a ** abs b
is equivalent to: (abs a) ** (abs b)
I agree.
One correct view of this is: "abs" has higher precedence than "**" because "abs" is done first.
Another correct view of this is: "abs" and "**" have equal precedence, and then left to right evaluation results in the same parenthesized expression.
Hence, the current table correctly expresses one of the two possible precedence rules.
For Examples 1 and 2, you have to read the "weasel words": "Where the language allows a sequence of operators". The EBNF does not allow mixing "and" with "or". Interestingly, the EBNF is the sole source of that information. If you try to mix "and" and "or" without parentheses you will get a syntax error.
Honestly, I like parentheses, however, it does not make sense to require parentheses for "**" and not for "and".
--
Jim Lewis - 2017-02-08
@Jim
: Now I understand the "weasel words." Of course, example 1 and 2 have syntax errors.
Regarding example 3: You cannot evaluate it from left to right, this would be ((abs a) **) abs b
which is non-sense. (Or I don't understand your view.)
The only problem with the BNF rule for miscellaneous_operator
was, that clause 9.2.8 refers to it. What about this change for clause 9.2.1 to split it into two groups:
binary_miscellaneous_operator ::= **
unary_miscellaneous_operator ::= abs | not | unary _logical_operator
--
Martin Zabel - 2017-02-10
In example 3, left to right it evaluates to: ((abs a) * abs b). The expression "abs b" is left operand to * and it is evaluated per the text "In general, operands in an expression are evaluated before being associated with operators".
Hence, both are indeed correct.
--
Jim Lewis - 2017-02-24