如果你打算寫規則明確地說,對於每個「優先級」級別使用不同的非終端,那麼根本不需要聲明優先級,而且您也不應該這樣做。
檸檬和所有yacc衍生物一樣,使用優先聲明來消除模糊語法中的歧義。特定的模糊語法是這樣的:
expression: expression '+' expression
| expression '*' expression
| '&' expression
| ... etc, etc.
在這種情況下,每一個替代方案都會導致轉換減少衝突。如果您的解析器發電機沒有優先規則,或者你想成爲精確,你必須寫,作爲一個明確的語法(這是你做了什麼):
term: ID | NUMBER | '(' expression ')' ;
postfix_expr: term | term '[' expression '] | ... ;
unary_expr: postfix_expr | '&' unary_expr | '*' unary_expr | ... ;
multiplicative_expr: unary_expr | multiplicative_expr '*' postfix_expr | ... ;
additive_expr: multiplicative_expr | additive_expr '+' multiplicative_expr | ... ;
...
assignment_expr: conditional_expr | unary_expr '=' assignment_expr | ...;
expression: assignment_expr ;
[1]
注意,明確語法甚至顯示了左結合(上面的乘法和加法)和右結合(賦值,儘管有點奇怪,見下文)。所以確實沒有含糊之處。
現在,優先聲明(%left
,%right
等)是只有用於消除歧義。如果沒有歧義,則聲明忽略。解析器生成器甚至不檢查它們是否反映語法。 (實際上,許多語法不能表示爲這種優先關係。)
因此,如果語法是明確的,那麼包含優先聲明是一個非常糟糕的主意。他們可能是完全錯誤的,並誤導任何讀過語法的人。改變它們不會影響語言解析的方式,這可能會誤導任何想編輯語法的人。
至少有一些問題,最好是使用具有優先規則的模糊語法,還是使用明確的語法。在類似於C
的語言中,其語法不能用簡單的優先級列表表示,因此使用明確的語法可能會更好。然而,明確的語法有更多的狀態,並且可能會使語法分析稍微慢一些,除非語法分析器生成器能夠優化單位減少量(上述語法中的所有第一個替代方法,其中每個表達式類型可能只是前一個表達式類型,但不影響AST;這些生產中的每一個都需要減少,儘管它大部分是空操作,並且許多解析器生成器會插入一些代碼。)
原因C
不能簡單地表示爲優先關係恰好是賦值運算符。試想一下:
a = 4 + b = c + 4;
這並不是因爲assignment-expression
分析,賦值運算符可以在左側僅適用於unary-expression
。這並不反映+
和=
之間可能的數字優先順序。 [2]
如果+
較高優先級的比=
,表達式將作爲解析:
a = ((4 + b) = (c + 4));
並且如果+
較低優先級,這將解析爲
(a = 4) + (b = (c + 4));
[1]我剛剛意識到我遺漏了cast_expression,但我不能投入重演;你明白了)
[2]描述固定。
+1爲了補償疼痛,因爲你必須親手寫這個。 – 2012-12-28 21:40:47
我不確定從哪裏開始。我應該嘗試在語法樹級別解析它,還是應該嘗試在解析器中檢測它(例如,通過窺視最近的令牌流)。 – doug65536
在解析器中。 AST必須是明確的。解析器是什麼數學和邏輯。 – 2012-12-28 21:57:09