private LuaGrammar() : base(true) { #region Declare Terminals Here StringLiteral STRING = CreateLuaString(LuaTerminalNames.String); NumberLiteral NUMBER = CreateLuaNumber(LuaTerminalNames.Number); LuaLongStringTerminal LONGSTRING = new LuaLongStringTerminal(LuaTerminalNames.LongString); // This includes both single-line and block comments var Comment = new LuaCommentTerminal(LuaTerminalNames.Comment); //var TypeSymbol = new LuaTypeSymbolTerminal(LuaTerminalNames.TypeSymbol); // Regular Operators var DOT = ToTerm(LuaTerminalNames.Dot); var COLON = ToTerm(LuaTerminalNames.Colon); var SEMIC = ToTerm(LuaTerminalNames.Semic); var COMMA = ToTerm(LuaTerminalNames.Comma); // Standard Operators var EQ = Operator(LuaTerminalNames.Equal); var OpeAdd = Operator("+"); var OpeSub = Operator("-"); var OpeMul = Operator("*"); var OpeDiv = Operator("/"); var OpePow = Operator("^"); var OpeEQ = Operator("=="); var OpeNEQ = Operator("~="); var OpeBig = Operator(">"); var OpeBigEQ = Operator(">="); var OpeSm = Operator("<"); var OpeSmEQ = Operator("<="); var OpeLink = Operator(".."); var OpePre = Operator("%"); var OpeWell = Operator("#"); //NonGrammarTerminals.Add(TypeSymbol); //NonGrammarTerminals.Add(Comment); #region Keywords var LOCAL = Keyword("local"); var DO = Keyword("do"); var END = Keyword("end"); var WHILE = Keyword("while"); var REPEAT = Keyword("repeat"); var UNTIL = Keyword("until"); var IF = Keyword("if"); var THEN = Keyword("then"); var ELSEIF = Keyword("elseif"); var ELSE = Keyword("else"); var FOR = Keyword("for"); var IN = Keyword("in"); var FUNCTION = Keyword("function"); var RETURN = Keyword("return"); var BREAK = Keyword("break"); var NIL = Keyword("nil"); var FALSE = Keyword("false"); var TRUE = Keyword("true"); var NOT = Keyword("not"); var AND = Keyword("and"); var OR = Keyword("or"); var TypeSymbol = Keyword("--@"); //var CLASS = Keyword("class"); //var NEW = Keyword("new"); #endregion IdentifierTerminal Name = new IdentifierTerminal(LuaTerminalNames.Identifier); #endregion #region Declare NonTerminals Here NonTerminal Chunk = new NonTerminal(LuaTerminalNames.Chunk); NonTerminal Block = new NonTerminal(LuaTerminalNames.Block); NonTerminal Statement = new NonTerminal(LuaTerminalNames.Statement); NonTerminal LastStatement = new NonTerminal(LuaTerminalNames.LastStatement); NonTerminal FuncName = new NonTerminal(LuaTerminalNames.FunctionName); NonTerminal VarList = new NonTerminal(LuaTerminalNames.VarList); NonTerminal Var = new NonTerminal(LuaTerminalNames.Var); NonTerminal NameList = new NonTerminal(LuaTerminalNames.NameList); NonTerminal ExprList = new NonTerminal(LuaTerminalNames.ExprList); NonTerminal Expr = new NonTerminal(LuaTerminalNames.Expr); NonTerminal PrefixExpr = new NonTerminal(LuaTerminalNames.PrefixExpr); NonTerminal FunctionCall = new NonTerminal(LuaTerminalNames.FunctionCall); NonTerminal Args = new NonTerminal(LuaTerminalNames.Args); NonTerminal NamedFunction = new NonTerminal(LuaTerminalNames.NamedFunction); NonTerminal NamelessFunction = new NonTerminal(LuaTerminalNames.NamelessFunction); NonTerminal FuncBody = new NonTerminal(LuaTerminalNames.FunctionBody); NonTerminal ParList = new NonTerminal(LuaTerminalNames.ParList); NonTerminal TableConstructor = new NonTerminal(LuaTerminalNames.TableConstructor); NonTerminal FieldList = new NonTerminal(LuaTerminalNames.FieldList); NonTerminal Field = new NonTerminal(LuaTerminalNames.Field); NonTerminal FieldSep = new NonTerminal(LuaTerminalNames.FieldSeperator); NonTerminal BinOp = new NonTerminal(LuaTerminalNames.Binop); NonTerminal UnOp = new NonTerminal(LuaTerminalNames.Unop); NonTerminal LoopBlock = new NonTerminal(LuaTerminalNames.LoopBlock); NonTerminal BranchBlock = new NonTerminal(LuaTerminalNames.BranchBlock); NonTerminal Assign = new NonTerminal(LuaTerminalNames.Assign); NonTerminal LocalVar = new NonTerminal(LuaTerminalNames.LocalVar); //NonTerminal TypeSymbol = new NonTerminal(LuaTerminalNames.TypeSymbol); #endregion #region Place Rules Here //Using Lua 5.1 grammar as defined in //http://www.lua.org/manual/5.1/manual.html#8 this.Root = Chunk; //chunk ::= {stat [`;´]} [laststat [`;´]] Chunk.Rule = MakeStarRule(Chunk, Statement + SEMIC.Q()) + (LastStatement + SEMIC.Q()).Q(); //block ::= chunk Block = Chunk; //stat ::= varlist `=´ explist | // functioncall | // do block end | // while exp do block end | // repeat block until exp | // if exp then block {elseif exp then block} [else block] end | // for Name `=´ exp `,´ exp [`,´ exp] do block end | // for namelist in explist do block end | // function funcname funcbody | // local function Name funcbody | // local namelist [`=´ explist] //TypeSymbol.Rule = TypeSymbol; Statement.Rule = Assign | FunctionCall | DO + Block + END | LoopBlock | BranchBlock | NamedFunction | LocalVar ; Assign.Rule = VarList + EQ + ExprList; LoopBlock.Rule = WHILE + Expr + DO + Block + END | REPEAT + Block + UNTIL + Expr | FOR + Name + EQ + Expr + COMMA + Expr + (COMMA + Expr).Q() + DO + Block + END | FOR + NameList + IN + ExprList + DO + Block + END; BranchBlock.Rule = IF + Expr + THEN + Block + MakeStarRule(BranchBlock, ELSEIF + Expr + THEN + Block) + (ELSE + Block).Q() + END; LocalVar.Rule = LOCAL + NamedFunction | LOCAL + NameList + (EQ + ExprList).Q() | TypeSymbol + Name | TypeSymbol + NameList; ; //laststat ::= return [explist] | break LastStatement.Rule = RETURN + ExprList.Q() | BREAK; //funcname ::= Name {`.´ Name} [`:´ Name] FuncName.Rule = Name + MakeStarRule(DOT + Name) + (COLON + Name).Q(); //NamedFunction = 'function' + FuncName + FuncBody NamedFunction.Rule = FUNCTION + FuncName + FuncBody; //varlist ::= var {`,´ var} VarList.Rule = MakePlusRule(VarList, COMMA, Var); //namelist ::= Name {`,´ Name} NameList.Rule = MakePlusRule(NameList, COMMA, Name); //explist ::= {exp `,´} exp ExprList.Rule = MakePlusRule(ExprList, COMMA, Expr); //exp ::= nil | false | true | Number | String | `...´ | function | // prefixexp | tableconstructor | exp binop exp | unop exp Expr.Rule = NIL | FALSE | TRUE | NUMBER | STRING | LONGSTRING | "..." | NamelessFunction | PrefixExpr | TableConstructor | Expr + BinOp + Expr | UnOp + Expr; //var ::= Name | prefixexp `[´ exp `]´ | prefixexp `.´ Name Var.Rule = Name | PrefixExpr + "[" + Expr + "]" | PrefixExpr + DOT + Name; //prefixexp ::= var | functioncall | `(´ exp `)´ PrefixExpr.Rule = Var | FunctionCall | "(" + Expr + ")"; //functioncall ::= prefixexp args | prefixexp `:´ Name args FunctionCall.Rule = PrefixExpr + Args | PrefixExpr + COLON + Name + Args; //args ::= `(´ [explist] `)´ | tableconstructor | String Args.Rule = "(" + ExprList.Q() + ")" | TableConstructor | STRING | LONGSTRING; //function ::= function funcbody NamelessFunction.Rule = FUNCTION + FuncBody; //funcbody ::= `(´ [parlist] `)´ block end FuncBody.Rule = "(" + ParList.Q() + ")" + Block + END; //parlist ::= namelist [`,´ `...´] | `...´ ParList.Rule = NameList + (COMMA + "...").Q() | "..."; //tableconstructor ::= `{´ [fieldlist] `}´ TableConstructor.Rule = "{" + FieldList.Q() + "}"; //fieldlist ::= field {fieldsep field} [fieldsep] //FieldList.Rule = Field + MakeStarRule(FieldSep + Field) + FieldSep.Q(); FieldList.Rule = MakePlusRule(FieldList, Field + FieldSep.Q()); //field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp Field.Rule = "[" + Expr + "]" + EQ + Expr | Name + EQ + Expr | Expr; //fieldsep ::= `,´ | `;´ FieldSep.Rule = COMMA | SEMIC; //binop ::= `+´ | `-´ | `*´ | `/´ | `^´ | `%´ | `..´ | // `<´ | `<=´ | `>´ | `>=´ | `==´ | `~=´ | // and | or BinOp.Rule = OpeAdd | OpeSub | OpeMul | OpeDiv | OpePow | OpePre | OpeLink | OpeSm | OpeSmEQ | OpeBig | OpeBigEQ | OpeEQ | OpeNEQ | AND | OR; //unop ::= `-´ | not | `#´ UnOp.Rule = NOT | OpeSub | OpeWell; #endregion #region Define Keywords and Register Symbols this.RegisterBracePair("(", ")"); this.RegisterBracePair("{", "}"); this.RegisterBracePair("[", "]"); this.MarkPunctuation(",", ";"); this.RegisterOperators(1, OR); this.RegisterOperators(2, AND); this.RegisterOperators(3, OpeBigEQ, OpeBig, OpeSm, OpeSmEQ, OpeNEQ, OpeEQ); this.RegisterOperators(4, Associativity.Right, OpeLink); this.RegisterOperators(5, OpeAdd, OpeSub); this.RegisterOperators(6, OpeMul, OpeDiv, OpePre); this.RegisterOperators(7, NOT); this.RegisterOperators(8, Associativity.Right, OpePow); #endregion }
private LuaGrammar() : base(true) { #region Declare Terminals Here StringLiteral STRING = CreateLuaString(LuaTerminalNames.String); NumberLiteral NUMBER = CreateLuaNumber(LuaTerminalNames.Number); LuaLongStringTerminal LONGSTRING = new LuaLongStringTerminal(LuaTerminalNames.LongString); // This includes both single-line and block comments var Comment = new LuaCommentTerminal(LuaTerminalNames.Comment); // Regular Operators var DOT = ToTerm(LuaTerminalNames.Dot); var COLON = ToTerm(LuaTerminalNames.Colon); var SEMIC = ToTerm(LuaTerminalNames.Semic); var COMMA = ToTerm(LuaTerminalNames.Comma); // Standard Operators var EQ = Operator(LuaTerminalNames.Equal); var OpeAdd = Operator("+"); var OpeSub = Operator("-"); var OpeMul = Operator("*"); var OpeDiv = Operator("/"); var OpePow = Operator("^"); var OpeEQ = Operator("=="); var OpeNEQ = Operator("~="); var OpeBig = Operator(">"); var OpeBigEQ = Operator(">="); var OpeSm = Operator("<"); var OpeSmEQ = Operator("<="); var OpeLink = Operator(".."); var OpePre = Operator("%"); var OpeWell = Operator("#"); NonGrammarTerminals.Add(Comment); #region Keywords var LOCAL = Keyword("local"); var DO = Keyword("do"); var END = Keyword("end"); var WHILE = Keyword("while"); var REPEAT = Keyword("repeat"); var UNTIL = Keyword("until"); var IF = Keyword("if"); var THEN = Keyword("then"); var ELSEIF = Keyword("elseif"); var ELSE = Keyword("else"); var FOR = Keyword("for"); var IN = Keyword("in"); var FUNCTION = Keyword("function"); var RETURN = Keyword("return"); var BREAK = Keyword("break"); var NIL = Keyword("nil"); var FALSE = Keyword("false"); var TRUE = Keyword("true"); var NOT = Keyword("not"); var AND = Keyword("and"); var OR = Keyword("or"); //var CLASS = Keyword("class"); //var NEW = Keyword("new"); #endregion IdentifierTerminal Name = new IdentifierTerminal(LuaTerminalNames.Identifier); #endregion #region Declare NonTerminals Here NonTerminal Chunk = new NonTerminal(LuaTerminalNames.Chunk); NonTerminal Block = new NonTerminal(LuaTerminalNames.Block); NonTerminal Statement = new NonTerminal(LuaTerminalNames.Statement); NonTerminal LastStatement = new NonTerminal(LuaTerminalNames.LastStatement); NonTerminal FuncName = new NonTerminal(LuaTerminalNames.FunctionName); NonTerminal VarList = new NonTerminal(LuaTerminalNames.VarList); NonTerminal Var = new NonTerminal(LuaTerminalNames.Var); NonTerminal NameList = new NonTerminal(LuaTerminalNames.NameList); NonTerminal ExprList = new NonTerminal(LuaTerminalNames.ExprList); NonTerminal Expr = new NonTerminal(LuaTerminalNames.Expr); NonTerminal PrefixExpr = new NonTerminal(LuaTerminalNames.PrefixExpr); NonTerminal FunctionCall = new NonTerminal(LuaTerminalNames.FunctionCall); NonTerminal Args = new NonTerminal(LuaTerminalNames.Args); NonTerminal NamedFunction = new NonTerminal(LuaTerminalNames.NamedFunction); NonTerminal NamelessFunction = new NonTerminal(LuaTerminalNames.NamelessFunction); NonTerminal FuncBody = new NonTerminal(LuaTerminalNames.FunctionBody); NonTerminal ParList = new NonTerminal(LuaTerminalNames.ParList); NonTerminal TableConstructor = new NonTerminal(LuaTerminalNames.TableConstructor); NonTerminal FieldList = new NonTerminal(LuaTerminalNames.FieldList); NonTerminal Field = new NonTerminal(LuaTerminalNames.Field); NonTerminal FieldSep = new NonTerminal(LuaTerminalNames.FieldSeperator); NonTerminal BinOp = new NonTerminal(LuaTerminalNames.Binop); NonTerminal UnOp = new NonTerminal(LuaTerminalNames.Unop); NonTerminal LoopBlock = new NonTerminal(LuaTerminalNames.LoopBlock); NonTerminal BranchBlock = new NonTerminal(LuaTerminalNames.BranchBlock); NonTerminal Assign = new NonTerminal(LuaTerminalNames.Assign); NonTerminal LocalVar = new NonTerminal(LuaTerminalNames.LocalVar); #endregion #region Place Rules Here //Using Lua 5.1 grammar as defined in //http://www.lua.org/manual/5.1/manual.html#8 this.Root = Chunk; //chunk ::= {stat [`;´]} [laststat [`;´]] Chunk.Rule = MakeStarRule(Chunk, Statement + SEMIC.Q()) + (LastStatement + SEMIC.Q()).Q(); //block ::= chunk Block = Chunk; //stat ::= varlist `=´ explist | // functioncall | // do block end | // while exp do block end | // repeat block until exp | // if exp then block {elseif exp then block} [else block] end | // for Name `=´ exp `,´ exp [`,´ exp] do block end | // for namelist in explist do block end | // function funcname funcbody | // local function Name funcbody | // local namelist [`=´ explist] Statement.Rule = Assign | FunctionCall | DO + Block + END | LoopBlock | BranchBlock | NamedFunction | LocalVar ; Assign.Rule = VarList + EQ + ExprList; LoopBlock.Rule = WHILE + Expr + DO + Block + END | REPEAT + Block + UNTIL + Expr | FOR + Name + EQ + Expr + COMMA + Expr + (COMMA + Expr).Q() + DO + Block + END | FOR + NameList + IN + ExprList + DO + Block + END; BranchBlock.Rule = IF + Expr + THEN + Block + MakeStarRule(BranchBlock, ELSEIF + Expr + THEN + Block) + (ELSE + Block).Q() + END; LocalVar.Rule = LOCAL + NamedFunction | LOCAL + NameList + (EQ + ExprList).Q(); //laststat ::= return [explist] | break LastStatement.Rule = RETURN + ExprList.Q() | BREAK; //funcname ::= Name {`.´ Name} [`:´ Name] FuncName.Rule = Name + MakeStarRule(DOT + Name) + (COLON + Name).Q(); //NamedFunction = 'function' + FuncName + FuncBody NamedFunction.Rule = FUNCTION + FuncName + FuncBody; //varlist ::= var {`,´ var} VarList.Rule = MakePlusRule(VarList, COMMA, Var); //namelist ::= Name {`,´ Name} NameList.Rule = MakePlusRule(NameList, COMMA, Name); //explist ::= {exp `,´} exp ExprList.Rule = MakePlusRule(ExprList, COMMA, Expr); //exp ::= nil | false | true | Number | String | `...´ | function | // prefixexp | tableconstructor | exp binop exp | unop exp Expr.Rule = NIL | FALSE | TRUE | NUMBER | STRING | LONGSTRING | "..." | NamelessFunction | PrefixExpr | TableConstructor | Expr + BinOp + Expr | UnOp + Expr; //var ::= Name | prefixexp `[´ exp `]´ | prefixexp `.´ Name Var.Rule = Name | PrefixExpr + "[" + Expr + "]" | PrefixExpr + DOT + Name; //prefixexp ::= var | functioncall | `(´ exp `)´ PrefixExpr.Rule = Var | FunctionCall | "(" + Expr + ")"; //functioncall ::= prefixexp args | prefixexp `:´ Name args FunctionCall.Rule = PrefixExpr + Args | PrefixExpr + COLON + Name + Args; //args ::= `(´ [explist] `)´ | tableconstructor | String Args.Rule = "(" + ExprList.Q() + ")" | TableConstructor | STRING | LONGSTRING; //function ::= function funcbody NamelessFunction.Rule = FUNCTION + FuncBody; //funcbody ::= `(´ [parlist] `)´ block end FuncBody.Rule = "(" + ParList.Q() + ")" + Block + END; //parlist ::= namelist [`,´ `...´] | `...´ ParList.Rule = NameList + (COMMA + "...").Q() | "..."; //tableconstructor ::= `{´ [fieldlist] `}´ TableConstructor.Rule = "{" + FieldList.Q() + "}"; //fieldlist ::= field {fieldsep field} [fieldsep] //FieldList.Rule = Field + MakeStarRule(FieldSep + Field) + FieldSep.Q(); FieldList.Rule = MakePlusRule(FieldList, Field + FieldSep.Q()); //field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp Field.Rule = "[" + Expr + "]" + EQ + Expr | Name + EQ + Expr | Expr; //fieldsep ::= `,´ | `;´ FieldSep.Rule = COMMA | SEMIC; //binop ::= `+´ | `-´ | `*´ | `/´ | `^´ | `%´ | `..´ | // `<´ | `<=´ | `>´ | `>=´ | `==´ | `~=´ | // and | or BinOp.Rule = OpeAdd | OpeSub | OpeMul | OpeDiv | OpePow | OpePre | OpeLink | OpeSm | OpeSmEQ | OpeBig | OpeBigEQ | OpeEQ | OpeNEQ | AND | OR; //unop ::= `-´ | not | `#´ UnOp.Rule = NOT | OpeSub | OpeWell; #endregion #region Define Keywords and Register Symbols this.RegisterBracePair("(", ")"); this.RegisterBracePair("{", "}"); this.RegisterBracePair("[", "]"); this.MarkPunctuation(",", ";"); this.RegisterOperators(1, OR); this.RegisterOperators(2, AND); this.RegisterOperators(3, OpeBigEQ, OpeBig, OpeSm, OpeSmEQ, OpeNEQ, OpeEQ); this.RegisterOperators(4, Associativity.Right, OpeLink); this.RegisterOperators(5, OpeAdd, OpeSub); this.RegisterOperators(6, OpeMul, OpeDiv, OpePre); this.RegisterOperators(7, NOT); this.RegisterOperators(8, Associativity.Right, OpePow); #endregion }