所以我一直在閱讀詞法分析器,解析器,解釋器甚至編譯。左遞歸,關聯性和AST評估
對於我試圖實現的語言,我在Recrusive Descent Parser上解決了問題。由於語言的原始語法具有左遞歸,我不得不稍微重寫它。
這裏是語法我有一個簡化版本(注意,這不是任何標準格式的語法,但有點假,我想,這就是我發現它在文檔中):
expr:
-----
expr + expr
expr - expr
expr * expr
expr/expr
(expr)
integer
identifier
爲了擺脫左遞歸的,我把它變成這樣(請注意添加NOT運算符的):
expr:
-----
expr_term {+ expr}
expr_term {- expr}
expr_term {* expr}
expr_term {/ expr}
expr_term:
----------
! expr_term
(expr)
integer
identifier
然後通過我的令牌使用以下子例程去(簡化的僞代碼-ISH):
public string Expression()
{
string term = ExpressionTerm();
if (term != null)
{
while (PeekToken() == OperatorToken)
{
term += ReadToken() + Expression();
}
}
return term;
}
public string ExpressionTerm()
{
//PeekToken and ReadToken accordingly, otherwise return null
}
This Works!調用Expression
後的結果總是等於它給出的輸入。
這使我想知道:如果我要在這些子程序中創建AST節點而不是字符串,並且使用中綴評估器(它也記住運算符的關聯性和優先級等)來評估AST,我不會得到相同的結果?
如果我這樣做,那麼爲什麼會有這麼多的話題涉及到「固定左遞歸,牢記關聯性和什麼不是」,當它實際上「簡單地」解決或者甚至是一個非問題時,它似乎就是這樣?或者,它真的是AST人們關心的結構(而不是它所評估的)?任何人都可以點亮一下,我可能會把它弄錯,哈哈!
解析器的目的是產生解釋(動作)或翻譯(相同或另一種語言中的等效文檔,如優化,註釋或編譯中)。重現原始輸入是無趣的。 – Apalala
我認爲這表明我得到了我的遞歸循環,因爲如果我將字符串更改爲節點樹,我最終還會得到一個語法正確的「句子」。這個假設是不正確的? –
重現輸入證明沒有關於識別結構。它可以通過回聲或運氣來完成。一個簡單而透明的翻譯將嘗試將輸入轉換爲前綴或後綴(波蘭語)符號。你甚至可以爲postfix建立一個評估器來知道你是否正確地解釋了輸入結構。就你而言,你會發現你不是,因爲所有的操作員都在同一個級別。您需要某種運算符優先權,請注意a + b * 3表示a +(b * 3)而不是(a + b)* 3。 – Apalala