我必須為 C 程式生成一個涵蓋 IF、IF-ELSE、IF - ELSE IF - ELSE 條件的 LL1 語法。我正在執行以下操作,但無法解決遞回問題,因此我認為可能是我的語法錯誤或不滿足 LL1 條件。
你能告訴我語法是否正確嗎?
<MAIN> ::= int main () { <PROG> <AUX_PROG> }
<AUX_PROG> ::= <PROG> <AUX_PROG> | ε
<PROG> ::= <IF_STAT> | other | ε
<IF_STAT> ::= if ( other ) { <PROG> } <ELSE_STAT>
<ELSE_STAT> ::= else { <PROG> } | ε
follow(PROG) = { "}", if, other }
follow(AUX_PROG) = { "}" }
follow(IF_STAT) = follow(PROG) = { "}", if, other }
follow(ELSE_STAT) = follow(IF_STAT) = { "}", if, other }
follow(MAIN) = { $ }
first(MAIN) = { int }
first(AUX_PROG) = { if, other, ε }
first(PROG) = { if, other, ε }
first(IF_STAT) = { if }
first(ELSE_STAT) = { else, ε }
更新:我修改了語法,還包括了第一個和后續。大括號是必需的,這樣就不會出現懸空問題。
uj5u.com熱心網友回復:
該語法是模棱兩可的,因為<PROG> ::= ε它使<AUX_PROG> ::= <PROG> <AUX_PROG>左遞回。如果你消除了空產生式,<PROG>那么語法肯定是 LL(1)。
但是只是 LL(1) 并不能證明語法正確地識別了所需的語法,更不用說它正確地將每個輸入決議到所需的決議樹中。所以這絕對取決于你如何定義“正確”。由于您的問題并未真正指定您希望匹配的語法或您希望對其進行分析的形式,因此很難評論這些形式的正確性。
您絕對正確地注意到 C 的 dangling-else 問題的核心是 C 不需要分隔子句的主體if和子句。else所以以下是合法的C:
if (condition1) if (condition2) statement1; else statement2;
并且語言的規則導致else statement2系結到if (condition2),而不是第一個if。
這通常被稱為歧義,但實際上很容易消除歧義。您會在各處找到消歧技術,包括Wikipedia 關于 dangling else 的頗為蹂躪的條目,或最流行的編程語言教科書。然而,消歧技術不會產生 LL(1) 文法;您需要使用自下而上的決議器。(即使是運算子優先級決議器也可以處理它,但 LALR(1) 決議器可能更常見。)
正如 Wikipedia 指出的那樣,一個簡單的解決方案是更改語法以消除if (c1) if (c2) .... 一種簡單的方法是堅持if以某種方式對目標進行分隔,例如添加大括號(如果主體是多個陳述句,則無論如何都需要這樣做)。沒有必要對else條款的主體提出相同的要求,但這可能會讓語言用戶感到困惑。但是,允許if...else這樣的鏈式結構很方便:
if (c1) {
body1
}
else if (c2) {
body2
}
else if (c3) {
body3
}
...
這不是模棱兩可的,即使每個的主體都else沒有分隔。在某些語言中,該結構通過使用特殊elseif標記(可能拼寫為elifor elsif)來縮寫,以保留else子句必須是分隔塊的規則。else if但是,簡單地允許作為關于身體的一般規則的例外并不過分。
因此,如果您正在設計一種語言,您可以選擇。如果您正在實施其他人的語言(例如課程講師給出的語言),您需要確保您了解他們的要求。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/487589.html
