[英]Removing indirect left recursion from this grammar
我試圖弄清楚如何從我的 Rust 端口的 Rust 解析器( https://github.com/kenaniah/ruby-parser/blob/master/ruby-parser/源代碼/解析器/表達式/邏輯.rs )。 語法看起來像:
E --> N | A | O | t
N --> n E
A --> E a E
O --> E o E
E = expression
A = keyword_and_expression
O = keyword_or_expression
N = keyword_not_expression
我 go 如何將其轉換為刪除A
和O
中的遞歸?
我認為這里的問題不是間接遞歸而是歧義。
如果它只是間接遞歸,您可以簡單地替換N
、 A
和O
的右側,從而消除間接遞歸:
E → n E
| E a E
| E o E
| t
為了擺脫直接左遞歸,你可以左因子:
E → n E
| E A'
| t
A'→ a E
| o E
然后刪除剩余的左遞歸:
E → n E E'
| t E'
E'→ ε
| A' E'
A'→ a E
| o E
它沒有左遞歸、直接或間接,並且每條規則都以唯一的終端開始。 但是,它不是 LL(1),因為存在 first/follow 沖突。
這真的不足為奇,因為原始語法是高度歧義的,而左遞歸消除並不能消除歧義。 只有伴隨着運算符優先級表,原始語法才真正有意義。
該表表明AND
和OR
是具有相同優先級的左結合運算符(一個稍微不尋常的決定),而NOT
是具有更高優先級的一元運算符。 反過來,這意味着 BNF 應該這樣寫:
N → n N
| t
E → A
| O
| N
A → E a N
O → E o N
N → n N
| t
與 OP 中語法的唯一區別是消除了歧義,如優先級表所示。
同樣,第一步是替換非終結符A
和O
以使左遞歸直接:
E → E a N
| E o N
| N
N → n N
| t
這與算術表達式的語法本質上是相同的(忽略乘法,因為只有一個優先級),左遞歸可以直接消除:
E → N E'
E' → a E
| o E
| ε
N → n N
| t
根據這個factorization tool ,生成的語法將是:
E -> N
| A
| O
| t
N -> n E
A -> n E a E A'
| O a E A'
| t a E A'
O -> n E o E O'
| n E a E A' o E O'
| t a E A' o E O'
| t o E O'
A' -> a E A'
| ϵ
O' -> a E A' o E O'
| o E O'
| ϵ
由於E
的多次產生,看起來A
和O
的因式分解最終變得相當復雜。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.