簡體   English   中英

從此語法中刪除間接左遞歸

[英]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 如何將其轉換為刪除AO中的遞歸?

我認為這里的問題不是間接遞歸而是歧義。

如果它只是間接遞歸,您可以簡單地替換NAO的右側,從而消除間接遞歸:

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 沖突。

這真的不足為奇,因為原始語法是高度歧義的,而左遞歸消除並不能消除歧義。 只有伴隨着運算符優先級表,原始語法才真正有意義。

該表表明ANDOR是具有相同優先級的左結合運算符(一個稍微不尋常的決定),而NOT是具有更高優先級的一元運算符。 反過來,這意味着 BNF 應該這樣寫:

N → n N
  | t
E → A
  | O
  | N
A → E a N
O → E o N
N → n N
  | t

與 OP 中語法的唯一區別是消除了歧義,如優先級表所示。

同樣,第一步是替換非終結符AO以使左遞歸直接:

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的多次產生,看起來AO的因式分解最終變得相當復雜。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM