跳轉到內容

Irony - 語言實現工具包/語法/非終結符

來自 Wikibooks,開放世界中的開放書籍

規則告訴解析器如何將掃描器饋送的標記組合成表示式和語句。

“+”和“|”已被過載,因此您可以將終結符和非終結符串在一起以定義這些規則。

來自 Irony 專案中找到的 ExpressionEvaluatorGrammar 示例

// 2. Non-terminals
var Term = new NonTerminal("Term");
var BinExpr = new NonTerminal("BinExpr", typeof(BinaryOperationNode));
var ParExpr = new NonTerminal("ParExpr");
var UnExpr = new NonTerminal("UnExpr", typeof(UnaryOperationNode));
var UnOp = new NonTerminal("UnOp");
var BinOp = new NonTerminal("BinOp", "operator");
var PrefixIncDec = new NonTerminal("PrefixIncDec", typeof(IncDecNode));
var PostfixIncDec = new NonTerminal("PostfixIncDec", typeof(IncDecNode));
var IncDecOp = new NonTerminal("IncDecOp");
var AssignmentStmt = new NonTerminal("AssignmentStmt", typeof(AssignmentNode));
var AssignmentOp = new NonTerminal("AssignmentOp", "assignment operator");
var Statement = new NonTerminal("Statement");
var Program = new NonTerminal("Program", typeof(StatementListNode));

// 3. BNF rules
Expr.Rule = Term | UnExpr | BinExpr | PrefixIncDec | PostfixIncDec;
Term.Rule = number | ParExpr | identifier | stringLit;
ParExpr.Rule = "(" + Expr + ")";
UnExpr.Rule = UnOp + Term;
UnOp.Rule = ToTerm("+") | "-"; 
BinExpr.Rule = Expr + BinOp + Expr;
BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**";
PrefixIncDec.Rule = IncDecOp + identifier;
PostfixIncDec.Rule = identifier + IncDecOp;
IncDecOp.Rule = ToTerm("++") | "--";
AssignmentStmt.Rule = identifier + AssignmentOp + Expr;
AssignmentOp.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/=";
Statement.Rule = AssignmentStmt | Expr | Empty;
Program.Rule = MakePlusRule(Program, NewLine, Statement);


Kleene 運算子

[編輯 | 編輯原始碼]

在傳統的 BNF 表示法中,“?”、“+”和“*”字元分別用於表示“0 次或 1 次”、“1 次或多次”和“0 次或多次”。在 Irony 中,它的實現方式略有不同。您可以使用來自基礎 Grammar 類的 MakePlusRuleMakeStarRule 方法分別表示“+”和“*”,或者您可以直接在規則中的項上使用 Q()、Plus() 和 Star() 方法。

許多語言都以一個名為“program”的非終結符開始,該非終結符包含一個或多個“statement”非終結符。以下是您指示該方法的方式

Root = program;

program = MakePlusRule(program, statement);

statement = ...

重要說明:當使用 MakePlusRuleMakeStarRule 時,規則中不能包含其他任何內容。

PreferShiftHere ReduceHere ResolveInCode ImplyPrecedenceHere


瞬態是非終結符,解析器使用它們將語句分解成更細粒度的表示式,但在其他情況下則不需要。例如,如果您有一個名為“expression”的非終結符,它可以分解成更細粒度的“binaryExpression”,那麼通常您只關心它最終被識別為“binaryExpression”。將“expression”放入解析樹只會建立一個實際上不需要存在的額外節點。

您可以使用來自基礎 Grammar 類的 MarkTransient 方法指示哪些非終結符是瞬態的。

MarkTransient(Term, Expr, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr);

您不能標記任何其 AST 節點型別為 StatementListNode 的非終結符為瞬態。因此,像“program”這樣的非終結符不能被標記為瞬態,因為它的定義是一系列語句。

華夏公益教科書