這是我撰寫決議器的腳本語言的 if 陳述句的代碼,這些陳述句可能有 else 或 elsif。實際上,我對我得到它的緊湊程度感到相當自豪:
@_( 'IF LPAREN expr_comp RPAREN THEN NEWLINE statement_set { elsif_statement } ENDIF',
'IF LPAREN expr_comp RPAREN THEN NEWLINE statement_set { elsif_statement } ELSE NEWLINE statement_set ENDIF',
)
def if_statement(self, p):
expressions = []
expressions.append((p.expr_comp, p[6]))
else_statement = None
if (p[8] == 'else'):
else_statement = p[10]
expressions.extend(p.elsif_statement)
return ('IF', expressions, else_statement)
@_('ELSIF LPAREN expr_comp RPAREN THEN NEWLINE statement_set')
def elsif_statement(self, p):
return (p.expr_comp, p.statement_set)
這會生成以下規則:
Rule 64 if_statement -> IF LPAREN expr_comp RPAREN THEN NEWLINE statement_set _3_elsif_statement_repeat ELSE NEWLINE statement_set ENDIF
Rule 65 _3_elsif_statement_repeat -> _3_elsif_statement_items
Rule 66 _3_elsif_statement_repeat ->
Rule 67 _3_elsif_statement_items -> _3_elsif_statement_items _3_elsif_statement_item
Rule 68 _3_elsif_statement_items -> _3_elsif_statement_item
Rule 69 _3_elsif_statement_item -> elsif_statement
Rule 70 if_statement -> IF LPAREN expr_comp RPAREN THEN NEWLINE statement_set _4_elsif_statement_repeat ENDIF
規則 71 _4_elsif_statement_repeat -> _4_elsif_statement_items
規則 72 _4_elsif_statement_repeat ->
規則 73 _4_elsif_statement_items -> _4_elsif_statement_items _4_elsif_statement_item
規則 74 _4_elsif_statement_items -> _4_elsif_statement_item
規則 75 _4_elsif_statement_item -> elsif_statement
規則 76 elsif_statement -> ELSIF LPAREN expr_comp RPAREN THEN NEWLINE 陳述句
不幸的是,它還會產生以下沖突:
Conflicts:
reduce/reduce conflict for ELSIF in state 111 resolved using rule _3_elsif_statement_item -> elsif_statement
rejected rule (_4_elsif_statement_item -> elsif_statement) in state 111
reduce using _3_elsif_statement_item -> elsif_statement with lookahead ELSIF
╭?
│ elsif_statement ? ELSIF LPAREN expr_comp RPAREN THEN NEWLINE statement_set
│ ╰_3_elsif_statement_item╯ ╰elsif_statement───────────────────────────────────────╯
│ ╰_3_elsif_statement_items╯ ╰_3_elsif_statement_item───────────────────────────────╯
│ ╰_3_elsif_statement_items─────────────────────────────────────────────────────────╯
╰?
reduce using _4_elsif_statement_item -> elsif_statement with lookahead ELSIF
╭?
│ elsif_statement ? ELSIF LPAREN expr_comp RPAREN THEN NEWLINE statement_set
│ ╰_4_elsif_statement_item╯ ╰elsif_statement───────────────────────────────────────╯
│ ╰_4_elsif_statement_items╯ ╰_4_elsif_statement_item───────────────────────────────╯
│ ╰_4_elsif_statement_items─────────────────────────────────────────────────────────╯
╰?
該代碼有效,但我試圖盡可能減少沖突,以免實際問題在噪音中消失。我懷疑部分問題是用于可選專案串列的自動化,但我的大腦并沒有準確地理解這是如何發生的。
uj5u.com熱心網友回復:
問題是您有兩個不同的產品,其中包括“{ elsif_statement }”。EBNF 擴展器創建了兩個不同的非終結符;它不會試圖注意到它們是相同的。這會產生沖突,因為決議器無法知道要使用兩個相同的非終結符中的哪一個,而無需提前查看elsif
or end
,這顯然是做不到的。
對此有許多修復。一個簡單的方法是將elsif_statement
識別單個elsif
子句的 更改為識別一系列elsif
子句。
uj5u.com熱心網友回復:
rici 的幫助對我找到一種進一步壓縮代碼的方法非常寶貴:
@_('IF LPAREN expr_comp RPAREN THEN NEWLINE statement_set elsif_statement_list optional_else ENDIF')
def if_statement(self, p):
expressions = []
expressions.append((p.expr_comp, p.statement_set))
else_statement = p.optional_else
expressions.extend(p.elsif_statement_list)
return ('IF', expressions, else_statement)
@_('[ ELSE NEWLINE statement_set ]')
def optional_else(self, p):
return p.statement_set
@_('{ elsif_statement }')
def elsif_statement_list(self, p):
return p.elsif_statement
@_('ELSIF LPAREN expr_comp RPAREN THEN NEWLINE statement_set')
def elsif_statement(self, p):
return (p.expr_comp, p.statement_set)
沒有減少沖突,我擺脫了一些索引檢查。順便說一句,將else
andelsif
結構放入它們自己的非終結符中對此有很大幫助。我最初的說法是,有多個規則導致函式,這意味著多個statement_set
專案意味著在一個規則下,會有一個p.statement_set
,在另一個規則下,會有p.statement_set0
and p.statement_set1
。由于可選和重復結構回傳 None 或如果專案不存在則回傳空串列,我可以檢查一下。并將它們粘貼在非終端中意味著我可以參考p.elsif_statement_list
而不是類似的東西_3_elsif_statement_repeat
或者在訪問值時必須使用索引(并且如果您將多個符號嵌入到花括號中而不是非終結符中,則使用多級參考來獲得您想要的實際欄位會變得更加混亂)。
希望這將幫助其他人實作類似的構造。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/508445.html