[英]Sprache: left recursion in grammar
我正在為類似於SQL的語言開發解析器,我遇到了創建一些語言規則的問題,例如: expression IS NULL
和expression IN (expression1, expression2, ...)
,邏輯和數學運算符之間具有優先級。
我上傳了一個GitHub測試項目https://github.com/anpv/SpracheTest/,但這個變種並不好。
我試圖使用以下規則:
private static readonly Parser<AstNode> InOperator =
from expr in Parse.Ref(() => Expression)
from inKeyword in Parse.IgnoreCase("in").Token()
from values in Parse
.Ref(() => Expression)
.DelimitedBy(Comma)
.Contained(OpenParenthesis, CloseParenthesis)
select new InOperator(expr, values);
private static readonly Parser<AstNode> IsNullOperator =
from expr in Parse.Ref(() => Expression)
from isNullKeyword in Parse
.IgnoreCase("is")
.Then(_ => Parse.WhiteSpace.AtLeastOnce())
.Then(_ => Parse.IgnoreCase("null"))
select new IsNullOperator(expr);
private static readonly Parser<AstNode> Equality =
Parse
.ChainOperator(Eq, IsNullOperator.Or(InOperator).Or(Additive), MakeBinary);
它在代碼中拋出ParseException
,如ScriptParser.ParseExpression("1 is null")
或ScriptParser.ParseExpression("1 in (1, 2, 3)"): "Parsing failure: Left recursion in the grammar."
。
我怎樣才能預測Expression,或者是否存在其他變體來解決這個問題?
答案是,不幸的是,Sprache無法解析左遞歸語法。 我偶然發現源代碼中的評論,討論了在研究這個問題時我是如何刪除對左遞歸語法的錯誤支持(這也是我如何找到你的問題) - 請參閱源代碼 。
為了解決這個問題,您需要重新組織解析方式。 例如,如果您正在編寫一個簡單的表達式解析器,那么這是您必須處理的常見問題。 在網上搜索有很多關於如何從語法中刪除左遞歸的討論,特別是對於表達式。
在你的情況下,我希望你需要做類似的事情:
term := everything simple in an expression (like "1", "2", "3", etc.)
expression := term [ IN ( expression*) | IS NULL | "+" expression | "-" expression | etc.]
或類似 - 基本上 - 你必須自己解除遞歸。 通過這樣做,我能夠解決表達式問題。 我懷疑任何基本的編譯器書可能都有關於如何“規范化”語法的部分。
它使你從解析器返回的任何對象構建更多的痛苦,但是在select語句中而不是“選擇新的表達式(arg1,arg2)”我將其更改為函數調用,並且函數決定根據參數的內容返回特定對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.