public ExpressionEvaluatorGrammar() : base(caseSensitive: false) { this.GrammarComments = @"Irony expression evaluator. Case-insensitive. Supports big integers, float data types, variables, assignments, arithmetic operations, augmented assignments (+=, -=), inc/dec (++,--), strings with embedded expressions; bool operations &,&&, |, ||; ternary '?:' operator."; // 1. Terminals var number = new NumberLiteral("number"); //Let's allow big integers (with unlimited number of digits): number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt }; var identifier = new IdentifierTerminal("identifier"); var comment = new CommentTerminal("comment", "#", "\n", "\r"); //comment must be added to NonGrammarTerminals list; it is not used directly in grammar rules, // so we add it to this list to let Scanner know that it is also a valid terminal. base.NonGrammarTerminals.Add(comment); var comma = ToTerm(","); //String literal with embedded expressions ------------------------------------------------------------------ var stringLit = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLit.AddStartEnd("'", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLit.AstConfig.NodeType = typeof(StringTemplateNode); var Expr = new NonTerminal("Expr"); //declare it here to use in template definition var templateSettings = new StringTemplateSettings(); //by default set to Ruby-style settings templateSettings.ExpressionRoot = Expr; //this defines how to evaluate expressions inside template this.SnippetRoots.Add(Expr); stringLit.AstConfig.Data = templateSettings; //-------------------------------------------------------------------------------------------------------- // 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 TernaryIfExpr = new NonTerminal("TernaryIf", typeof(IfNode)); var ArgList = new NonTerminal("ArgList", typeof(ExpressionListNode)); var FunctionCall = new NonTerminal("FunctionCall", typeof(FunctionCallNode)); var MemberAccess = new NonTerminal("MemberAccess", typeof(MemberAccessNode)); var IndexedAccess = new NonTerminal("IndexedAccess", typeof(IndexedAccessNode)); var ObjectRef = new NonTerminal("ObjectRef"); // foo, foo.bar or f['bar'] 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 | TernaryIfExpr; Term.Rule = number | ParExpr | stringLit | FunctionCall | identifier | MemberAccess | IndexedAccess; ParExpr.Rule = "(" + Expr + ")"; UnExpr.Rule = UnOp + Term + ReduceHere(); UnOp.Rule = ToTerm("+") | "-" | "!"; BinExpr.Rule = Expr + BinOp + Expr; BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**" | "==" | "<" | "<=" | ">" | ">=" | "!=" | "&&" | "||" | "&" | "|"; PrefixIncDec.Rule = IncDecOp + identifier; PostfixIncDec.Rule = identifier + PreferShiftHere() + IncDecOp; IncDecOp.Rule = ToTerm("++") | "--"; TernaryIfExpr.Rule = Expr + "?" + Expr + ":" + Expr; MemberAccess.Rule = Expr + PreferShiftHere() + "." + identifier; AssignmentStmt.Rule = ObjectRef + AssignmentOp + Expr; AssignmentOp.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/="; Statement.Rule = AssignmentStmt | Expr | Empty; ArgList.Rule = MakeStarRule(ArgList, comma, Expr); FunctionCall.Rule = Expr + PreferShiftHere() + "(" + ArgList + ")"; FunctionCall.NodeCaptionTemplate = "call #{0}(...)"; ObjectRef.Rule = identifier | MemberAccess | IndexedAccess; IndexedAccess.Rule = Expr + PreferShiftHere() + "[" + Expr + "]"; Program.Rule = MakePlusRule(Program, NewLine, Statement); this.Root = Program; // Set grammar root // 4. Operators precedence RegisterOperators(10, "?"); RegisterOperators(15, "&", "&&", "|", "||"); RegisterOperators(20, "==", "<", "<=", ">", ">=", "!="); RegisterOperators(30, "+", "-"); RegisterOperators(40, "*", "/"); RegisterOperators(50, Associativity.Right, "**"); RegisterOperators(60, "!"); // For precedence to work, we need to take care of one more thing: BinOp. //For BinOp which is or-combination of binary operators, we need to either // 1) mark it transient or 2) set flag TermFlags.InheritPrecedence // We use first option, making it Transient. // 5. Punctuation and transient terms MarkPunctuation("(", ")", "?", ":", "[", "]"); RegisterBracePair("(", ")"); RegisterBracePair("[", "]"); MarkTransient(Term, Expr, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr, ObjectRef); // 7. Syntax error reporting MarkNotReported("++", "--"); AddToNoReportGroup("(", "++", "--"); AddToNoReportGroup(NewLine); AddOperatorReportGroup("operator"); AddTermsReportGroup("assignment operator", "=", "+=", "-=", "*=", "/="); //8. Console ConsoleTitle = "Irony Expression Evaluator"; ConsoleGreeting = @"Irony Expression Evaluator Supports variable assignments, arithmetic operators (+, -, *, /), augmented assignments (+=, -=, etc), prefix/postfix operators ++,--, string operations. Supports big integer arithmetics, string operations. Supports strings with embedded expressions : ""name: #{name}"" Press Ctrl-C to exit the program at any time. "; ConsolePrompt = "?"; ConsolePromptMoreInput = "?"; //9. Language flags. // Automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt; }
private StringLiteral CreateStringLiteral(string name) { var term = new StringLiteral(name); term.AddStartEnd("\"", StringOptions.AllowsAllEscapes); term.AddStartEnd("'", StringOptions.AllowsDoubledQuote | StringOptions.AllowsOctalEscapes | StringOptions.AllowsUEscapes | StringOptions.AllowsXEscapes); return term; }
private StringLiteral CreateStringLiteral(string name) { var term = new StringLiteral(name); term.AddStartEnd("\"", StringOptions.AllowsAllEscapes); term.AddStartEnd("'", StringOptions.AllowsDoubledQuote | StringOptions.AllowsOctalEscapes | StringOptions.AllowsUEscapes | StringOptions.AllowsXEscapes); return(term); }
private static StringLiteral CreateScriptNetString(string name) { StringLiteral term = new StringLiteral(name, TermOptions.None); term.AddStartEnd("'", ScanFlags.AllowAllEscapes); term.AddStartEnd("\"", ScanFlags.AllowAllEscapes); term.AddPrefixFlag("@", ScanFlags.DisableEscapes | ScanFlags.AllowLineBreak | ScanFlags.AllowDoubledQuote); return(term); }
private BnfTerm CreateSqlExtIdentifier(string name) { var identifierTerminal = new IdentifierTerminal(name, null, "@"); var stringLiteral = new StringLiteral(name + "_quoted"); stringLiteral.AddStartEnd("[", "]", StringOptions.NoEscapes); stringLiteral.AddStartEnd("\"", StringOptions.NoEscapes); stringLiteral.SetOutputTerminal(this, identifierTerminal); return(identifierTerminal); }
//Covers simple identifiers like abcd, and also quoted versions: [abc d], "abc d". public static IdentifierTerminal CreateSqlExtIdentifier(Grammar grammar, string name) { var id = CreateTerm(name); StringLiteral term = new StringLiteral(name + "_qouted"); term.AddStartEnd("[", "]", StringOptions.NoEscapes); term.AddStartEnd("\"", StringOptions.NoEscapes); term.SetOutputTerminal(grammar, id); //term will be added to NonGrammarTerminals automatically return(id); }
static StringLiteral createStringLiteral() { StringLiteral term = new StringLiteral("String"); term.AddStartEnd("'", StringOptions.AllowsAllEscapes | StringOptions.AllowsLineBreak); term.AddStartEnd("\"", StringOptions.AllowsAllEscapes | StringOptions.AllowsLineBreak); term.AddStartEnd("%[", "]", StringOptions.AllowsAllEscapes | StringOptions.AllowsLineBreak); term.AddStartEnd("%(", ")", StringOptions.AllowsAllEscapes | StringOptions.AllowsLineBreak); term.AddStartEnd("%{", "}", StringOptions.AllowsAllEscapes | StringOptions.AllowsLineBreak); return(term); }
public static StringLiteral CreatePythonString(string name) { StringLiteral term = new StringLiteral(name); term.AddStartEnd("'", StringOptions.AllowsAllEscapes); term.AddStartEnd("'''", StringOptions.AllowsAllEscapes | StringOptions.AllowsLineBreak); term.AddStartEnd("\"", StringOptions.AllowsAllEscapes); term.AddStartEnd("\"\"\"", StringOptions.AllowsAllEscapes | StringOptions.AllowsLineBreak); term.AddPrefix("u", StringOptions.AllowsAllEscapes); term.AddPrefix("r", StringOptions.NoEscapes ); term.AddPrefix("ur", StringOptions.NoEscapes); return term; }
public static StringLiteral CreateVbString(string name) { StringLiteral term = new StringLiteral(name); term.AddStartEnd("\"", StringOptions.NoEscapes | StringOptions.AllowsDoubledQuote); term.AddSuffix("$", TypeCode.String); term.AddSuffix("c", TypeCode.Char); return term; }
public static StringLiteral CreateZodiacString(string name) { StringLiteral term = new StringLiteral(name); //term.AddStartEnd("'", StringOptions.AllowsAllEscapes);// AllowLineBreak?? term.AddStartEnd("\"", StringOptions.AllowsAllEscapes);// AllowLineBreak?? return term; }
private void MakeSimpleId() { Identifier = new IdentifierTerminal("simple_id"); var idStringLiteral = new StringLiteral("simple_id_quoted"); idStringLiteral.AddStartEnd("\"", StringOptions.NoEscapes); idStringLiteral.AstConfig.NodeType = typeof(IdentifierNode); idStringLiteral.SetOutputTerminal(this, Identifier); }
/// <summary> /// Create the term that represents an Entity identifier. /// </summary> public IdentifierTerminal CreateIdentifierTerm(string name) { var id = new IdentifierTerminal(name, IdOptions.IsNotKeyword); var term = new StringLiteral(name + "_quoted"); term.AddStartEnd("[", "]", StringOptions.AllowsDoubledQuote); term.SetOutputTerminal(this, id); return(id); }
private NonTerminal AttributesList(BnfTerm identifier) { var options = StringOptions.AllowsAllEscapes | StringOptions.AllowsLineBreak; var attributeValue = new StringLiteral("attributeValue", "'", options, (context, node) => node.AstNode = node.Token.ValueString); attributeValue.AddStartEnd("\"", options); var attribute = NonTerminal("attribute", null, node => new Attribute { Name = (CompositeIdentifier)node.ChildNodes[0].AstNode, Value = (string)node.ChildNodes[2].AstNode }); var attributesList = NonTerminal("attributesList", null, node => node.ChildNodes.Select(c => (Attribute)c.AstNode).ToList()); attribute.Rule = identifier + "=" + attributeValue; attributesList.Rule = MakeStarRule(attributesList, attribute); return(attributesList); }
public SqlGrammar() : base(false) { //SQL is case insensitive //Terminals var comment = new CommentTerminal("comment", "/*", "*/"); var lineComment = new CommentTerminal("line_comment", "--", "\n", "\r\n"); NonGrammarTerminals.Add(comment); NonGrammarTerminals.Add(lineComment); var number = TerminalFactory.CreateCSharpNumber("number"); number.Options = NumberOptions.AllowSign; var string_literal = new StringLiteral("string", "'", StringOptions.AllowsDoubledQuote); string_literal.AddStartEnd("N'", "'", StringOptions.AllowsDoubledQuote | StringOptions.AllowsLineBreak); var Id_simple = TerminalFactory.CreateSqlExtIdentifier(this, "id_simple"); //covers normal identifiers (abc) and quoted id's ([abc d], "abc d") Id_simple.AddPrefix("@@", IdOptions.NameIncludesPrefix); Id_simple.AddPrefix("@", IdOptions.NameIncludesPrefix); var comma = ToTerm(","); var dot = ToTerm("."); var equals = ToTerm("="); var plus = ToTerm("+"); var CREATE = ToTerm("CREATE"); var NULL = ToTerm("NULL"); var NOT = ToTerm("NOT"); var UNIQUE = ToTerm("UNIQUE"); var WITH = ToTerm("WITH"); var TABLE = ToTerm("TABLE"); var VIEW = ToTerm("VIEW"); var DATABASE = ToTerm("DATABASE"); var ALTER = ToTerm("ALTER"); var ADD = ToTerm("ADD"); var COLUMN = ToTerm("COLUMN"); var DROP = ToTerm("DROP"); var CONSTRAINT = ToTerm("CONSTRAINT"); var INDEX = ToTerm("INDEX"); var CLUSTERED = ToTerm("CLUSTERED"); var NONCLUSTERED = ToTerm("NONCLUSTERED"); var ON = ToTerm("ON"); var KEY = ToTerm("KEY"); var PRIMARY = ToTerm("PRIMARY"); var INSERT = ToTerm("INSERT"); var INTO = ToTerm("INTO"); var UPDATE = ToTerm("UPDATE"); var SET = ToTerm("SET"); var VALUES = ToTerm("VALUES"); var DELETE = ToTerm("DELETE"); var SELECT = ToTerm("SELECT"); var FROM = ToTerm("FROM"); var AS = ToTerm("AS"); var COUNT = ToTerm("COUNT"); var JOIN = ToTerm("JOIN"); var BY = ToTerm("BY"); var DEFAULT = ToTerm("DEFAULT"); var CHECK = ToTerm("CHECK"); var REPLICATION = ToTerm("REPLICATION"); var FOR = ToTerm("FOR"); var COLLATE = ToTerm("COLLATE"); var IDENTITY = ToTerm("IDENTITY"); var TEXTIMAGE_ON = ToTerm("TEXTIMAGE_ON"); var IF = ToTerm("IF"); var ELSE = ToTerm("ELSE"); var BEGIN = ToTerm("BEGIN"); var END = ToTerm("END"); var GO = ToTerm("GO"); var PRINT = ToTerm("PRINT"); var IS = ToTerm("IS"); var USE = ToTerm("USE"); var EXEC = ToTerm("EXEC"); var NOCHECK = ToTerm("NOCHECK"); var CASCADE = ToTerm("CASCADE"); var TYPE = ToTerm("TYPE"); var PROCEDURE = ToTerm("PROCEDURE"); var DECLARE = ToTerm("DECLARE"); var TRY = ToTerm("TRY"); var CATCH = ToTerm("CATCH"); var CAST = ToTerm("CAST"); var AND = ToTerm("AND"); var OR = ToTerm("OR"); var GRANT = ToTerm("GRANT"); var UNION = ToTerm("UNION"); var ALL = ToTerm("ALL"); var CASE = ToTerm("CASE"); var WHEN = ToTerm("WHEN"); var THEN = ToTerm("THEN"); var RETURN = ToTerm("RETURN"); var COMMIT = ToTerm("COMMIT"); var TRAN = ToTerm("TRAN"); var TRANSACTION = ToTerm("TRANSACTION"); var TOP = ToTerm("TOP"); var MERGE = ToTerm("MERGE"); var USING = ToTerm("USING"); var MATCHED = ToTerm("MATCHED"); var TARGET = ToTerm("TARGET"); var TRUNCATE = ToTerm("TRUNCATE"); var ROLLBACK = ToTerm("ROLLBACK"); var STATISTICS = ToTerm("STATISTICS"); var ROLE = ToTerm("ROLE"); var WHILE = ToTerm("WHILE"); var BREAK = ToTerm("BREAK"); var REBUILD = ToTerm("REBUILD"); var CHECKPOINT = ToTerm("CHECKPOINT"); var HASH = ToTerm("HASH"); var OUTPUT = ToTerm("OUTPUT"); //Non-terminals var Id = new NonTerminal("Id"); var IdWithAliasOpt = new NonTerminal("IdWithAliasOpt"); var stmt = new NonTerminal("stmt"); var createTableStmt = new NonTerminal("createTableStmt"); var createIndexStmt = new NonTerminal("createIndexStmt"); var createViewStmt = new NonTerminal("createViewStmt"); var createTypeStmt = new NonTerminal("createTypeStmt"); var createProcedureStmt = new NonTerminal("createProcedureStmt"); var variableDefLists = new NonTerminal("variableDefLists"); var variableDefList = new NonTerminal("variableDefList"); var variableDef = new NonTerminal("variableDef"); var outputOpt = new NonTerminal("outputOpt"); var primaryKeyOpt = new NonTerminal("primaryKeyOpt"); var alterStmt = new NonTerminal("alterStmt"); var dropTableStmt = new NonTerminal("dropTableStmt"); var dropIndexStmt = new NonTerminal("dropIndexStmt"); var dropViewStmt = new NonTerminal("dropViewStmt"); var dropProcedureStmt = new NonTerminal("dropProcedureStmt"); var selectStmt = new NonTerminal("selectStmt"); var insertStmt = new NonTerminal("insertStmt"); var updateStmt = new NonTerminal("updateStmt"); var deleteStmt = new NonTerminal("deleteStmt"); var ifStmt = new NonTerminal("ifStmt"); var elseStmt = new NonTerminal("elseStmt"); var fieldDef = new NonTerminal("fieldDef"); var fieldDefList = new NonTerminal("fieldDefList"); var nullSpecOpt = new NonTerminal("nullSpecOpt"); var typeName = new NonTerminal("typeName"); var constraintListOpt = new NonTerminal("constraintListOpt"); var constraintDef = new NonTerminal("constraintDef"); var indexContraintDef = new NonTerminal("indexContraintDef"); var constraintTypeOpt = new NonTerminal("constraintTypeOptOpt"); var defaultValueOpt = new NonTerminal("defaultValueOpt"); var idlist = new NonTerminal("idlist"); var idOrExpression = new NonTerminal("idOrExpression"); var idOrExpressionList = new NonTerminal("idOrExpressionList"); var idlistForSelect = new NonTerminal("idlistForSelect"); var idlistParOpt = new NonTerminal("idlistPar"); var orderList = new NonTerminal("orderList"); var orderMember = new NonTerminal("orderMember"); var orderDirOpt = new NonTerminal("orderDirOpt"); var defaultValueParams = new NonTerminal("defaultValueParams"); var indexTypeOpt = new NonTerminal("indexTypeOpt"); var indexTypeList = new NonTerminal("indexTypeList"); var withClauseOpt = new NonTerminal("withClauseOpt"); var alterCmdOpt = new NonTerminal("alterCmdOpt"); var insertData = new NonTerminal("insertData"); var intoOpt = new NonTerminal("intoOpt"); var assignList = new NonTerminal("assignList"); var whereClauseOpt = new NonTerminal("whereClauseOpt"); var andClauseOpt = new NonTerminal("andClauseOpt"); var betweenClauseOpt = new NonTerminal("betweenClauseOpt"); var assignment = new NonTerminal("assignment"); var expression = new NonTerminal("expression"); var exprList = new NonTerminal("exprList"); var selRestrOpt = new NonTerminal("selRestrOpt"); var selList = new NonTerminal("selList"); var intoClauseOpt = new NonTerminal("intoClauseOpt"); var fromClauseOpt = new NonTerminal("fromClauseOpt"); var groupClauseOpt = new NonTerminal("groupClauseOpt"); var havingClauseOpt = new NonTerminal("havingClauseOpt"); var orderClauseOpt = new NonTerminal("orderClauseOpt"); var columnItemList = new NonTerminal("columnItemList"); var columnItem = new NonTerminal("columnItem"); var columnSource = new NonTerminal("columnSource"); var asOpt = new NonTerminal("asOpt"); var aliasOpt = new NonTerminal("aliasOpt"); var aggregate = new NonTerminal("aggregate"); var aggregateArg = new NonTerminal("aggregateArg"); var aggregateName = new NonTerminal("aggregateName"); var tuple = new NonTerminal("tuple"); var joinChainOpt = new NonTerminal("joinChainOpt"); var joinKindOpt = new NonTerminal("joinKindOpt"); var term = new NonTerminal("term"); var unExpr = new NonTerminal("unExpr"); var unOp = new NonTerminal("unOp"); var binExpr = new NonTerminal("binExpr"); var binOp = new NonTerminal("binOp"); var betweenExpr = new NonTerminal("betweenExpr"); var notOpt = new NonTerminal("notOpt"); var funCall = new NonTerminal("funCall"); var stmtLine = new NonTerminal("stmtLine"); var semiOpt = new NonTerminal("semiOpt"); var stmtList = new NonTerminal("stmtList"); var funArgsOpt = new NonTerminal("funArgsOpt"); var inStmt = new NonTerminal("inStmt"); var settingList = new NonTerminal("settingList"); var settingListItem = new NonTerminal("settingListItem"); var onOpt = new NonTerminal("onOpt"); var textImageOnOpt = new NonTerminal("textImageOnOpt"); var defaultValueParamsList = new NonTerminal("defaultValueParamsList"); var typeNameParamsList = new NonTerminal("typeNameParamsList"); var notForReplOpt = new NonTerminal("notForReplOpt"); var collateOpt = new NonTerminal("collateOpt"); var columnDef = new NonTerminal("columnDef"); var identityOpt = new NonTerminal("identityOpt"); var referencesOpt = new NonTerminal("referencesOpt"); var fieldDefLists = new NonTerminal("fieldDefLists"); var onListOpt = new NonTerminal("onListOpt"); var printStmt = new NonTerminal("printStmt"); var beginEndStmt = new NonTerminal("beginEndStmt"); var beginTryCatchStmt = new NonTerminal("beginTryCatchStmt"); var beginEndStmtList = new NonTerminal("beginEndStmtList"); var isNullOpt = new NonTerminal("isNullOpt"); var setStmtOpt = new NonTerminal("setStmtOpt"); var useStmt = new NonTerminal("useStmt"); var forOpt = new NonTerminal("forOpt"); var execStmt = new NonTerminal("execStmt"); var cascadeOpt = new NonTerminal("cascadeOpt"); var cascadeListOpt = new NonTerminal("cascadeListOpt"); var alterProcedureStmt = new NonTerminal("alterProcedureStmt"); var declareStmt = new NonTerminal("declareStmt"); var concatStringItem = new NonTerminal("concatStringItem"); var concatStringList = new NonTerminal("concatStringList"); var castFunCall = new NonTerminal("castFunCall"); var funCallList = new NonTerminal("funCallList"); var funcallDelim = new NonTerminal("funcallDelim"); var declareList = new NonTerminal("declareList"); var declareListItem = new NonTerminal("declareListItem"); var grantStmt = new NonTerminal("grantStmt"); var joinChainOptList = new NonTerminal("joinChainOptList"); var leftParenOpt = new NonTerminal("leftParenOpt"); var rightParenOpt = new NonTerminal("rightParenOpt"); var unionAllOpt = new NonTerminal("unionAllOpt"); var selectCaseStmts = new NonTerminal("selectCaseStmts"); var selectCaseStmt = new NonTerminal("selectCaseStmt"); var caseWhenThenLists = new NonTerminal("caseWhenThenLists"); var caseWhenThenList = new NonTerminal("caseWhenThenList"); var caseWhenThenStmt = new NonTerminal("caseWhenThenStmt"); var unionAllListOpt = new NonTerminal("unionAllListOpt"); var returnStmt = new NonTerminal("returnStmt"); var beginTransStmt = new NonTerminal("beginTransStmt"); var rollbackTransStmt = new NonTerminal("rollbackTransStmt"); var topOpt = new NonTerminal("topOpt"); var mergeStmt = new NonTerminal("mergeStmt"); var mergeWhenMatched = new NonTerminal("mergeWhenMatched"); var mergeWhenNotMatched = new NonTerminal("mergeWhenNotMatched"); var truncateStmt = new NonTerminal("truncateStmt"); var commitTransStmt = new NonTerminal("commitTransStmt"); var noLockOpt = new NonTerminal("noLockOpt"); var declareTableStmt = new NonTerminal("declareTableStmt"); var joinStmtOpt = new NonTerminal("joinStmtOpt"); var forXmlStmtOpt = new NonTerminal("forXmlStmtOpt"); var forXmlFunCallList = new NonTerminal("forXmlFunCallList"); var funArgsList = new NonTerminal("funArgsList"); var updateStatisticsStmt = new NonTerminal("updateStatisticsStmt"); var createRoleStmt = new NonTerminal("createRoleStmt"); var whileStmt = new NonTerminal("whileStmt"); var alterIndexStmt = new NonTerminal("alterIndexStmt"); var ifCondition = new NonTerminal("ifCondition"); var ifConditionChain = new NonTerminal("ifConditionChain"); var hashOpt = new NonTerminal("hashOpt"); var IdAsType = new NonTerminal("IdAsType"); var selectWithUnion = new NonTerminal("selectWithUnion"); var withStmt = new NonTerminal("withStmt"); //BNF Rules this.Root = stmtList; stmtLine.Rule = stmt + semiOpt; semiOpt.Rule = Empty | ";"; stmtList.Rule = MakePlusRule(stmtList, stmtLine); setStmtOpt.Rule = Empty | SET + Id + Id | SET + Id + equals + (leftParenOpt + selectStmt + rightParenOpt | Id | funCall | concatStringList | expression); useStmt.Rule = USE + Id; execStmt.Rule = EXEC + (Empty | Id | Id + ".." + Id) + (leftParenOpt + funArgsList + rightParenOpt); declareStmt.Rule = DECLARE + declareList; declareTableStmt.Rule = DECLARE + Id + TABLE + "(" + fieldDefList + ")"; declareListItem.Rule = Id + typeName | Id + typeName + equals + term; declareList.Rule = MakePlusRule(declareList, comma, declareListItem); castFunCall.Rule = CAST + "(" + funCall + asOpt + (Empty | typeName) + ")" + asOpt + (Empty | typeName); grantStmt.Rule = GRANT + term + ON + TYPE + "::" + Id + "TO" + Id; returnStmt.Rule = RETURN + term; leftParenOpt.Rule = Empty | "("; rightParenOpt.Rule = Empty | ")"; unionAllOpt.Rule = Empty | UNION + ALL + leftParenOpt + selectStmt + rightParenOpt; unionAllListOpt.Rule = MakeStarRule(unionAllListOpt, unionAllOpt); idOrExpression.Rule = Id | expression; idOrExpressionList.Rule = MakeStarRule(idOrExpressionList, comma, idOrExpression); whileStmt.Rule = WHILE + expression + beginEndStmt; //ID Id.Rule = MakePlusRule(Id, dot, Id_simple); IdWithAliasOpt.Rule = Id | Id + Id | Id + AS + Id; IdAsType.Rule = Id + AS + typeName; concatStringItem.Rule = leftParenOpt + term + rightParenOpt; concatStringList.Rule = MakePlusRule(concatStringList, plus, concatStringItem); stmt.Rule = createProcedureStmt | createTableStmt | createIndexStmt | createViewStmt | createTypeStmt | createRoleStmt | declareTableStmt | alterStmt | dropTableStmt | dropIndexStmt | dropViewStmt | dropProcedureStmt | selectWithUnion | insertStmt | updateStmt | deleteStmt | whileStmt | GO | ifStmt | elseStmt | beginEndStmt | printStmt | withStmt | execStmt | setStmtOpt | useStmt | funCall | declareStmt | returnStmt | grantStmt | mergeStmt | truncateStmt | updateStatisticsStmt | beginTransStmt | commitTransStmt | rollbackTransStmt | BREAK | CHECKPOINT | ";"; onOpt.Rule = Empty | ON + Id; textImageOnOpt.Rule = Empty | TEXTIMAGE_ON + Id; forOpt.Rule = Empty | FOR + Id; onListOpt.Rule = MakePlusRule(onListOpt, onOpt); withStmt.Rule = WITH + Id + AS + leftParenOpt + selectStmt + rightParenOpt; fieldDefLists.Rule = MakePlusRule(fieldDefLists, fieldDefList); printStmt.Rule = PRINT + concatStringList; beginEndStmtList.Rule = MakePlusRule(beginEndStmtList, stmt); beginEndStmt.Rule = beginTryCatchStmt | BEGIN + beginEndStmtList + END; beginTryCatchStmt.Rule = BEGIN + TRY + beginEndStmtList + END + TRY + BEGIN + CATCH + beginEndStmtList + END + CATCH; beginTransStmt.Rule = BEGIN + (TRAN | TRANSACTION) + (Empty | Id); commitTransStmt.Rule = COMMIT + (TRAN | TRANSACTION) + (Empty | Id); rollbackTransStmt.Rule = ROLLBACK + (TRAN | TRANSACTION) + (Empty | Id); truncateStmt.Rule = TRUNCATE + TABLE + Id; isNullOpt.Rule = Empty | IS + NULL; funcallDelim.Rule = AND | OR; funCallList.Rule = MakePlusRule(funCallList, funcallDelim, funCall); // If ifStmt.Rule = IF + leftParenOpt + ifConditionChain + rightParenOpt; ifCondition.Rule = (notOpt + funCall + isNullOpt | NOT + leftParenOpt + expression + rightParenOpt) | (Empty | "EXISTS") + "(" + (Id_simple + IS + NULL | settingListItem | selectWithUnion) + ")" | "EXISTS" + "(" + selectWithUnion + ")" | (Id_simple + IS + (Empty | NOT) + NULL | settingListItem) | expression; ifConditionChain.Rule = MakePlusRule(ifConditionChain, AND | OR, ifCondition); elseStmt.Rule = ELSE; createRoleStmt.Rule = CREATE + ROLE + Id; createViewStmt.Rule = CREATE + VIEW + Id + AS + leftParenOpt + selectWithUnion + rightParenOpt + unionAllListOpt; createTypeStmt.Rule = CREATE + TYPE + Id + FROM + Id | CREATE + TYPE + Id + AS + TABLE + "(" + fieldDefLists + ")"; //Create procedure createProcedureStmt.Rule = CREATE + PROCEDURE + Id + "(" + variableDefLists + ")" + AS + BEGIN + stmtList + END; variableDefLists.Rule = MakePlusRule(variableDefLists, variableDefList); variableDefList.Rule = MakeListRule(variableDefList, comma, variableDef, TermListOptions.AllowTrailingDelimiter | TermListOptions.PlusList); variableDef.Rule = Id + typeName + outputOpt; outputOpt.Rule = Empty | OUTPUT; //Create table createTableStmt.Rule = CREATE + TABLE + Id + "(" + fieldDefLists + ")" + (onOpt | withClauseOpt) + textImageOnOpt; fieldDefList.Rule = MakeListRule(fieldDefList, comma, fieldDef, TermListOptions.AllowTrailingDelimiter | TermListOptions.PlusList); fieldDef.Rule = columnDef | constraintListOpt; columnDef.Rule = Id + typeName + collateOpt + primaryKeyOpt + nullSpecOpt + referencesOpt + defaultValueOpt + withClauseOpt | Id + typeName + collateOpt + primaryKeyOpt + nullSpecOpt + constraintListOpt + withClauseOpt | Id + typeName + collateOpt + primaryKeyOpt + notForReplOpt + nullSpecOpt + defaultValueOpt + withClauseOpt | Id + typeName + collateOpt + primaryKeyOpt + notForReplOpt + nullSpecOpt + constraintListOpt + withClauseOpt | Id + typeName + equals + term | primaryKeyOpt + indexTypeOpt + idlistParOpt + withClauseOpt | term; referencesOpt.Rule = Empty | "References" + Id + idlistParOpt; notForReplOpt.Rule = Empty | (NOT + FOR + REPLICATION); nullSpecOpt.Rule = Empty | (NOT + FOR + REPLICATION) | NULL | NOT + NULL | NOT + NULL + typeName | NULL + typeName; collateOpt.Rule = Empty | COLLATE + Id_simple; identityOpt.Rule = Empty | IDENTITY; typeNameParamsList.Rule = MakePlusRule(typeNameParamsList, comma, term); typeName.Rule = Id_simple | Id_simple + "(" + typeNameParamsList + ")" | Id_simple + "(max)"; constraintDef.Rule = CONSTRAINT + Id + constraintTypeOpt + onListOpt; indexContraintDef.Rule = constraintTypeOpt + onListOpt; constraintListOpt.Rule = MakeStarRule(constraintListOpt, constraintDef); constraintTypeOpt.Rule = Empty | defaultValueOpt + withClauseOpt | primaryKeyOpt + indexTypeList + idlistParOpt + withClauseOpt | CHECK + "(" + expression + ")" + withClauseOpt | NOT + NULL + idlistParOpt + withClauseOpt | "Foreign" + KEY + idlistParOpt + referencesOpt + notForReplOpt + withClauseOpt | "INCLUDE" + idlistParOpt + withClauseOpt + onOpt; idlistParOpt.Rule = Empty | "(" + orderList + ")"; idlist.Rule = MakePlusRule(idlist, comma, Id); idlistForSelect.Rule = MakePlusRule(idlist, comma, IdWithAliasOpt); defaultValueParamsList.Rule = MakePlusRule(defaultValueParamsList, comma, term); defaultValueOpt.Rule = Empty | (DEFAULT + defaultValueParams); defaultValueParams.Rule = term | "(" + term + ")"; //Create Index primaryKeyOpt.Rule = Empty | PRIMARY + KEY | typeName; createIndexStmt.Rule = CREATE + indexTypeList + INDEX + Id + onOpt + "(" + orderList + ")" + constraintTypeOpt + whereClauseOpt + withClauseOpt + onOpt; orderList.Rule = MakePlusRule(orderList, comma, orderMember); orderMember.Rule = Id + orderDirOpt; orderDirOpt.Rule = Empty | "ASC" | "DESC"; indexTypeOpt.Rule = Empty | UNIQUE | CLUSTERED | NONCLUSTERED; indexTypeList.Rule = MakeStarRule(indexTypeList, indexTypeOpt); settingList.Rule = MakePlusRule(settingList, comma, settingListItem); settingListItem.Rule = Id + equals + term; withClauseOpt.Rule = Empty | (WITH + PRIMARY | WITH + "Disallow" + NULL | WITH + "Ignore" + NULL | WITH + "(" + settingList + ")" + onOpt + textImageOnOpt); cascadeOpt.Rule = Empty | (ON + (UPDATE | DELETE) + CASCADE); cascadeListOpt.Rule = MakePlusRule(cascadeListOpt, cascadeOpt); noLockOpt.Rule = (Empty | WITH + leftParenOpt + "NOLOCK" + rightParenOpt); //Alter alterStmt.Rule = ALTER + (TABLE | DATABASE) + Id + setStmtOpt + alterCmdOpt | alterProcedureStmt | alterIndexStmt; alterCmdOpt.Rule = Empty | ADD + COLUMN + fieldDefList + constraintDef | CHECK + CONSTRAINT + Id | WITH + (CHECK | NOCHECK) + ADD + CONSTRAINT + Id + constraintTypeOpt + cascadeListOpt | ADD + constraintDef + forOpt | DROP + COLUMN + Id | DROP + CONSTRAINT + Id; alterProcedureStmt.Rule = ALTER + PROCEDURE + Id + leftParenOpt + fieldDefLists + rightParenOpt + asOpt + beginEndStmt; alterIndexStmt.Rule = ALTER + INDEX + Id + ON + Id + REBUILD + WITH + "(" + settingList + ")"; //Drop stmts dropTableStmt.Rule = DROP + TABLE + Id; dropIndexStmt.Rule = DROP + INDEX + Id + ON + Id; dropViewStmt.Rule = DROP + VIEW + Id; dropProcedureStmt.Rule = DROP + PROCEDURE + Id; //Insert stmt insertStmt.Rule = INSERT + (Empty | intoOpt + Id) + (idlistParOpt + insertData | execStmt); insertData.Rule = leftParenOpt + selectWithUnion + rightParenOpt | VALUES + "(" + exprList + ")"; intoOpt.Rule = Empty | INTO; //Into is optional in MSSQL //Update stmt updateStmt.Rule = UPDATE + topOpt + (Empty | Id) + SET + assignList + fromClauseOpt + joinStmtOpt + whereClauseOpt + andClauseOpt; assignList.Rule = MakePlusRule(assignList, comma, assignment); assignment.Rule = Id + "=" + expression; updateStatisticsStmt.Rule = UPDATE + STATISTICS + Id; //Delete stmt deleteStmt.Rule = DELETE + (Empty | FROM) + Id + whereClauseOpt + andClauseOpt; //Select stmt selectCaseStmt.Rule = CASE + caseWhenThenLists + ELSE + expression + END + (Empty | asOpt + Id); caseWhenThenLists.Rule = MakePlusRule(caseWhenThenLists, caseWhenThenList); caseWhenThenList.Rule = WHEN + leftParenOpt + expression + rightParenOpt + THEN + term; variableDef.Rule = Id + typeName + outputOpt; selectStmt.Rule = SELECT + topOpt + selRestrOpt + selList + intoClauseOpt + fromClauseOpt + forXmlStmtOpt + joinChainOptList + whereClauseOpt + andClauseOpt + betweenClauseOpt + groupClauseOpt + havingClauseOpt + orderClauseOpt; selectWithUnion.Rule = MakePlusRule(selectWithUnion, UNION, selectStmt); mergeStmt.Rule = MERGE + Id + AS + Id + USING + (Empty | Id) + leftParenOpt + (Empty | selectWithUnion) + rightParenOpt + AS + Id + ON + expression + mergeWhenMatched + mergeWhenNotMatched + mergeWhenNotMatched; mergeWhenMatched.Rule = WHEN + MATCHED + andClauseOpt + THEN + stmt; mergeWhenNotMatched.Rule = Empty | WHEN + NOT + MATCHED + BY + Id + THEN + stmt; forXmlStmtOpt.Rule = Empty | FOR + "XML" + forXmlFunCallList; forXmlFunCallList.Rule = MakePlusRule(forXmlFunCallList, comma, funCall); topOpt.Rule = Empty | TOP + leftParenOpt + (number | Id) + rightParenOpt; selRestrOpt.Rule = Empty | "ALL" | "DISTINCT"; selList.Rule = columnItemList + semiOpt | "*"; columnItemList.Rule = MakePlusRule(columnItemList, comma, columnItem); columnItem.Rule = columnSource; aliasOpt.Rule = Empty | asOpt + Id; asOpt.Rule = Empty | AS; columnSource.Rule = Id + aliasOpt | Id + "=" + (selectCaseStmt | concatStringList | expression) | expression | expression + asOpt + (Empty | Id) | selectCaseStmt; aggregate.Rule = aggregateName + "(" + aggregateArg + ")"; aggregateArg.Rule = expression | "*"; aggregateName.Rule = COUNT | "Avg" | "Min" | "Max" | "StDev" | "StDevP" | "Sum" | "Var" | "VarP"; intoClauseOpt.Rule = Empty | INTO + Id; fromClauseOpt.Rule = Empty | FROM + leftParenOpt + (selectStmt | funCall | idlistForSelect) + rightParenOpt + (Empty | AS + Id) + noLockOpt; joinStmtOpt.Rule = Empty | JOIN + Id + asOpt + Id + noLockOpt + ON + expression; joinChainOpt.Rule = Empty | joinKindOpt + hashOpt + joinStmtOpt; joinChainOptList.Rule = MakeStarRule(joinChainOptList, joinChainOpt); joinKindOpt.Rule = Empty | "INNER" | "OUTER" | "LEFT" | "RIGHT"; hashOpt.Rule = Empty | HASH; whereClauseOpt.Rule = Empty | "WHERE" + expression; andClauseOpt.Rule = Empty | "AND" + expression; betweenClauseOpt.Rule = Empty | "BETWEEN" + expression; groupClauseOpt.Rule = Empty | "GROUP" + BY + idOrExpressionList; havingClauseOpt.Rule = Empty | "HAVING" + expression; orderClauseOpt.Rule = Empty | "ORDER" + BY + orderList; //Expression exprList.Rule = MakePlusRule(exprList, comma, expression); expression.Rule = term | unExpr | binExpr | betweenExpr; //-- BETWEEN doesn't work - yet; brings a few parsing conflicts term.Rule = Id | IdAsType | string_literal | number | funCall | tuple | aggregate; // | inStmt; tuple.Rule = "(" + exprList + ")"; unExpr.Rule = unOp + term; unOp.Rule = NOT | "+" | "-" | "~"; binExpr.Rule = expression + binOp + expression; binOp.Rule = ToTerm("+") | "-" | "*" | "/" | "%" //arithmetic | "&" | "|" | "^" //bit | "=" | ">" | "<" | ">=" | "<=" | "<>" | "!=" | "!<" | "!>" | "AND" | "OR" | "LIKE" | NOT + "LIKE" | IS | "IN" | NOT + "IN"; betweenExpr.Rule = expression + notOpt + "BETWEEN" + expression + "AND" + expression; notOpt.Rule = Empty | NOT; //funCall covers some psedo-operators and special forms like ANY(...), SOME(...), ALL(...), EXISTS(...), IN(...) funCall.Rule = Id + "(" + funArgsList + ")" + (Empty | AS + typeName); funArgsOpt.Rule = Empty | selectStmt | expression | string_literal | Id + "=" + term; funArgsList.Rule = MakePlusRule(funArgsList, comma, funArgsOpt); inStmt.Rule = expression + "IN" + "(" + exprList + ")"; //Operators RegisterOperators(10, "*", "/", "%"); RegisterOperators(9, "+", "-"); RegisterOperators(8, "=", ">", "<", ">=", "<=", "<>", "!=", "!<", "!>", "LIKE", "IN"); RegisterOperators(7, "^", "&", "|"); RegisterOperators(6, NOT); RegisterOperators(5, "AND"); RegisterOperators(4, "OR"); MarkPunctuation(",", "(", ")"); MarkPunctuation(asOpt, semiOpt); //Note: we cannot declare binOp as transient because it includes operators "NOT LIKE", "NOT IN" consisting of two tokens. // Transient non-terminals cannot have more than one non-punctuation child nodes. // Instead, we set flag InheritPrecedence on binOp , so that it inherits precedence value from it's children, and this precedence is used // in conflict resolution when binOp node is sitting on the stack base.MarkTransient(stmt, term, asOpt, aliasOpt, stmtLine, expression, unOp, tuple); binOp.SetFlag(TermFlags.InheritPrecedence); } //constructor
private BnfTerm CreateSqlExtIdentifier(string name) { IdentifierTerminal identifierTerminal = new IdentifierTerminal(name, null, "@"); StringLiteral stringLiteral = new StringLiteral(name + "_quoted"); stringLiteral.AddStartEnd("[", "]", StringOptions.NoEscapes); stringLiteral.AddStartEnd("\"", StringOptions.NoEscapes); stringLiteral.SetOutputTerminal(this, (Terminal)identifierTerminal); return identifierTerminal; }
public RubyGrammar() { #region Terminals //String Literals with single and double-quote start/end symbols StringLiteral STRING = new StringLiteral("STRING", TermOptions.SpecialIgnoreCase); STRING.AddStartEnd("\"", ScanFlags.None); STRING.AddStartEnd("'", ScanFlags.None); Terminal HereDoc = new Terminal("HereDoc"); //-- implement me! Terminal RegExLiteral = new Terminal("RegExLiteral"); //-- implement me! IdentifierTerminal IDENTIFIER = new IdentifierTerminal("identifier", "_!?", "_$@"); // name extraChars extraFirstChars IDENTIFIER.DisplayName = "variable"; //we need to isolate reserved words to avoid ambiguities in grammar IDENTIFIER.AddKeywords("do", "end", "def", "class", "if", "case", "return", "yield", "while", "until"); //and some others... Terminal Number = new NumberLiteral("Number"); Terminal Comment = new CommentTerminal("Comment", "#", "\n"); NonGrammarTerminals.Add(Comment); //add comment explicitly to this list as it is not reachable from Root //some conveniency variables Terminal Pipe = Symbol("|"); Terminal dot = Symbol("."); Terminal comma = Symbol(","); #endregion #region NonTerminals //NT variables names match element names in original grammar NonTerminal PROGRAM = new NonTerminal("PROGRAM"); NonTerminal COMPSTMT = new NonTerminal("COMPSTMT"); NonTerminal STMT = new NonTerminal("STMT"); NonTerminal BLOCK = new NonTerminal("BLOCK"); NonTerminal EXPR = new NonTerminal("EXPR"); //NonTerminal CALL = new NonTerminal("CALL"); NonTerminal COMMAND = new NonTerminal("COMMAND"); NonTerminal FUNCTION = new NonTerminal("FUNCTION"); NonTerminal ARG = EXPR;// new NonTerminal("ARG"); NonTerminal PRIMARY = new NonTerminal("PRIMARY", "operand"); NonTerminal WHEN_ARGS = new NonTerminal("WHEN_ARGS"); NonTerminal THEN = new NonTerminal("THEN"); NonTerminal BLOCK_BEGIN = new NonTerminal("BLOCK_BEGIN"); NonTerminal BLOCK_END = new NonTerminal("BLOCK_END"); NonTerminal BLOCK_VAR = new NonTerminal("BLOCK_VAR"); // NonTerminal MLHS_ITEM = new NonTerminal("MLHS_ITEM"); NonTerminal LHS = new NonTerminal("LHS"); NonTerminal MRHS = new NonTerminal("MRHS"); // NonTerminal MLHS = MRHS; // new NonTerminal("MLHS"); NonTerminal CALL_ARGS = new NonTerminal("CALL_ARGS"); NonTerminal CALL_ARGS_P = new NonTerminal("CALL_ARGS_P"); NonTerminal AMP_ARG = new NonTerminal("AMP_ARG"); NonTerminal STAR_ARG = new NonTerminal("STAR_ARG"); NonTerminal ARGS = new NonTerminal("ARGS"); NonTerminal ARGDECL = new NonTerminal("ARGDECL"); NonTerminal ARGLIST = new NonTerminal("ARGLIST"); // NonTerminal SINGLETON = new NonTerminal("SINGLETON"); NonTerminal ASSOCS = new NonTerminal("ASSOCS"); NonTerminal ASSOC = new NonTerminal("ASSOC"); // NonTerminal VARIABLE = new NonTerminal("VARIABLE"); --merged into IDENTIFIER NonTerminal LITERAL = new NonTerminal("LITERAL", "value"); NonTerminal TERM = new NonTerminal("TERM"); NonTerminal DO = new NonTerminal("DO"); // NonTerminal VARNAME = new NonTerminal("VARNAME"); // note 1 NonTerminal GLOBAL = new NonTerminal("GLOBAL"); NonTerminal RETURN_STMT = new NonTerminal("RETURN_STMT"); NonTerminal YIELD_STMT = new NonTerminal("YIELD_STMT"); NonTerminal DEFINEDQ_STMT = new NonTerminal("DEFINEDQ_STMT"); NonTerminal FUNCTION_STMT = new NonTerminal("FUNCTION_STMT"); NonTerminal IF_STMT = new NonTerminal("IF_STMT"); NonTerminal UNLESS_STMT = new NonTerminal("UNLESS_STMT"); NonTerminal WHILE_STMT = new NonTerminal("WHILE_STMT"); NonTerminal UNTIL_STMT = new NonTerminal("UNTIL_STMT"); NonTerminal CASE_STMT = new NonTerminal("CASE_STMT"); NonTerminal FOR_STMT = new NonTerminal("FOR_STMT"); NonTerminal BLOCK_STMT = new NonTerminal("BLOCK_STMT"); NonTerminal CLASS_DEF = new NonTerminal("CLASS_DEF"); NonTerminal BASE_REF = new NonTerminal("BASE_REF"); NonTerminal MODULE = new NonTerminal("MODULE_STMT"); NonTerminal DEFFUNC_STMT = new NonTerminal("DEFFUNC_STMT"); NonTerminal DEFSING_STMT = new NonTerminal("DEFSING_STMT"); NonTerminal SINGLETON = new NonTerminal("SINGLETON"); NonTerminal END = new NonTerminal("end"); NonTerminal SYMBOL = new NonTerminal("SYMBOL"); //Not in original grammar NonTerminal FNAME = new NonTerminal("FNAME"); BLOCK_BEGIN.Rule = Symbol("do") | "{"; BLOCK_END.Rule = Symbol("end") | "}"; NonTerminal OPERATION = new NonTerminal("OPERATION"); // Terminal VARNAME = IDENTIFIER; NonTerminal AUG_ASGN = new NonTerminal("AUG_ASGN"); NonTerminal BINOP = new NonTerminal("BINOP", "operator"); NonTerminal UNOP = new NonTerminal("UNOP"); NonTerminal DELIM = new NonTerminal("DELIM"); #endregion #region Rules //Set grammar root this.Root = PROGRAM; //PROGRAM : COMPSTMT PROGRAM.Rule = COMPSTMT; // +Grammar.Eof; //COMPSTMT : STMT (TERM EXPR)* [TERM] COMPSTMT.Rule = NewLine.Q() + STMT.Plus(TERM) + TERM.Q(); /* STMT : CALL do [`|' [BLOCK_VAR] `|'] COMPSTMT end | undef FNAME | alias FNAME FNAME | STMT if EXPR | STMT while EXPR | STMT unless EXPR | STMT until EXPR | `BEGIN' `{' COMPSTMT `}' | `"end"' `{' COMPSTMT `}' | LHS `=' COMMAND [do [`|' [BLOCK_VAR] `|'] COMPSTMT end] | EXPR */ STMT.Rule = FUNCTION | COMMAND + BLOCK.Q() | "undef" + FNAME | "alias" + FNAME + FNAME | STMT + (Symbol("if")|"while"|"unless"|"until") + EXPR | Symbol("BEGIN") + "{" + COMPSTMT + "}" // | Symbol("end") + BLOCK_BEGIN + COMPSTMT + BLOCK_END // don't quite get it // | LHS + "=" + COMMAND + BLOCK.Q() | LHS + "=" + EXPR //changed this | LHS + AUG_ASGN + EXPR | EXPR; BLOCK.Rule = "do" + WithQ(Pipe + BLOCK_VAR.Q() + Pipe) + COMPSTMT + "end"; /* EXPR : MLHS `=' MRHS | return CALL_ARGS | yield CALL_ARGS | EXPR and EXPR | EXPR or EXPR | not EXPR | COMMAND | `!' COMMAND | ARG */ //this one is completely changed, for better or worse... EXPR.Rule = // MRHS + "=" + EXPR | //changed to EXPR // LHS + "=" + EXPR //changed this // | LHS + AUG_ASGN + EXPR EXPR + BINOP + EXPR | UNOP + EXPR //| "(" + EXPR + ")" | EXPR + "?" + EXPR + ":" + EXPR //added this to cover "?" operator | "defined?" + ARG | PRIMARY ; ARG = EXPR; // CALL : FUNCTION | COMMAND // CALL.Expression = FUNCTION | COMMAND; //expression embedded directly into STMT /* COMMAND : OPERATION CALL_ARGS | PRIMARY `.' OPERATION CALL_ARGS | PRIMARY `::' OPERATION CALL_ARGS | super CALL_ARGS */ COMMAND.Rule = OPERATION + CALL_ARGS | PRIMARY + DELIM + OPERATION + CALL_ARGS | "super" + CALL_ARGS; OPERATION.Rule = IDENTIFIER; DELIM.Rule = dot | "::"; /* FUNCTION : OPERATION [`(' [CALL_ARGS] `)'] | PRIMARY `.' OPERATION `(' [CALL_ARGS] `)' | PRIMARY `::' OPERATION `(' [CALL_ARGS] `)' | PRIMARY `.' OPERATION | PRIMARY `::' OPERATION | super `(' [CALL_ARGS] `)' | super */ FUNCTION.Rule = OPERATION + CALL_ARGS_P | PRIMARY + DELIM + OPERATION + CALL_ARGS_P.Q() | "super" + CALL_ARGS_P; CALL_ARGS_P.Rule = "(" + CALL_ARGS.Q() + ")"; /* ARG : LHS `=' ARG | LHS OP_ASGN ARG | ARG `..' ARG | ARG `...' ARG | ARG `+' ARG | ARG `-' ARG | ARG `*' ARG | ARG `/' ARG | ARG `%' ARG | ARG `**' ARG | `+' ARG | `-' ARG | ARG `|' ARG | ARG `^' ARG | ARG `&' ARG | ARG `<=>' ARG | ARG `>' ARG | ARG `>=' ARG | ARG `<' ARG | ARG `<=' ARG | ARG `==' ARG | ARG `===' ARG | ARG `!=' ARG | ARG `=~' ARG | ARG `!~' ARG | `!' ARG | `~' ARG | ARG `<<' ARG | ARG `>>' ARG | ARG `&&' ARG | ARG `||' ARG | defined? ARG | PRIMARY */ /* ARG.Expression = LHS + "=" + EXPR //changed this | LHS + AUG_ASGN + EXPR | ARG + BINOP + ARG //moved to EXPR | UNOP + ARG | "defined?" + ARG | PRIMARY ; */ AUG_ASGN.Rule = Symbol("+=") | "-=" | "*=" | "/=" | "%=" | "**=" | "&=" | "|=" | "^=" | "<<=" | ">>=" | "&&=" | "||="; BINOP.Rule = Symbol("..") | "..." | "+" | "-" | "*" | "/" | "%" | "**" | "|" | "^" | "&" | "<=>" | ">" | ">=" | "<" | "<=" | "==" | "===" | "!=" | "=~" | "!~" | "<<" | ">>" | "&&" | "||" | "and" | "or"; //added these two here UNOP.Rule = Symbol("+") | "-" | "!" | "~"; /*PRIMARY: */ /* `(' COMPSTMT `)' | LITERAL | VARIABLE | PRIMARY `::' IDENTIFIER | `::' IDENTIFIER | PRIMARY `[' [ARGS] `]' | `[' [ARGS [`,']] `]' | `{' [(ARGS|ASSOCS) [`,']] `}' | return [`(' [CALL_ARGS] `)'] | yield [`(' [CALL_ARGS] `)'] | defined? `(' ARG `)' | FUNCTION | FUNCTION `{' [`|' [BLOCK_VAR] `|'] COMPSTMT `}' | if EXPR THEN COMPSTMT (elsif EXPR THEN COMPSTMT)* [else COMPSTMT] end | unless EXPR THEN COMPSTMT [else COMPSTMT] end | while EXPR DO COMPSTMT end | until EXPR DO COMPSTMT end | case COMPSTMT (when WHEN_ARGS THEN COMPSTMT)+ [else COMPSTMT] end | for BLOCK_VAR in EXPR DO COMPSTMT end | begin COMPSTMT [rescue [ARGS] DO COMPSTMT]+ [else COMPSTMT] [ensure COMPSTMT] end | class IDENTIFIER [`<' IDENTIFIER] COMPSTMT end"= | module IDENTIFIER COMPSTMT end | def FNAME ARGDECL COMPSTMT end | def SINGLETON (`.'|`::') FNAME ARGDECL COMPSTMT end */ PRIMARY.Rule = // "(" + COMPSTMT + ")" | //-- removed this to fix ambiguity LITERAL | LHS //note 1. | "[" + WithQ(ARGS + comma.Q()) + "]" | "{" + WithQ( (ARGS|ASSOC) + comma.Q() ) + "}" | RETURN_STMT | YIELD_STMT | DEFINEDQ_STMT | FUNCTION_STMT | IF_STMT | UNLESS_STMT | WHILE_STMT | UNTIL_STMT | CASE_STMT | FOR_STMT | BLOCK_STMT | CLASS_DEF | MODULE | DEFFUNC_STMT | DEFSING_STMT; // LHS.Expression = VARIABLE | PRIMARY + "[" + ARGS.Q() + "]" | PRIMARY + "." + IDENTIFIER; RETURN_STMT.Rule = "return" + EXPR;// CALL_ARGS_P.Q(); //changed this YIELD_STMT.Rule = "yield" + CALL_ARGS_P.Q(); DEFINEDQ_STMT.Rule = Symbol("defined?") + "(" + ARG + ")"; FUNCTION_STMT.Rule = FUNCTION + WithQ("{" + WithQ("|" + BLOCK_VAR.Q() + "|") + COMPSTMT + "}"); IF_STMT.Rule = "if" + EXPR + THEN + COMPSTMT + WithStar("elsif" + EXPR + THEN + COMPSTMT) + WithQ("else" + COMPSTMT) + END; UNLESS_STMT.Rule = "unless" + EXPR + THEN + COMPSTMT + "else" + COMPSTMT + END; WHILE_STMT.Rule = "while" + EXPR + DO + COMPSTMT + END; UNTIL_STMT.Rule = "until" + EXPR + DO + COMPSTMT + END; CASE_STMT.Rule = "case" + COMPSTMT + WithPlus("when" + WHEN_ARGS + THEN + COMPSTMT) + WithQ("else" + COMPSTMT) + END; FOR_STMT.Rule = "for" + BLOCK_VAR + "in" + EXPR + DO + COMPSTMT + END; BLOCK_STMT.Rule = "begin" + COMPSTMT + WithPlus("rescue" + ARGS.Q() + DO + COMPSTMT) + WithQ("else" + COMPSTMT) + WithQ("ensure" + COMPSTMT) + END; CLASS_DEF.Rule = "class" + IDENTIFIER + BASE_REF.Q() + COMPSTMT + END; BASE_REF.Rule = "<" + IDENTIFIER; MODULE.Rule = "module" + IDENTIFIER + COMPSTMT + END; DEFFUNC_STMT.Rule = "def" + FNAME + ARGDECL.Q() + COMPSTMT + END; DEFSING_STMT.Rule = "def" + SINGLETON + (dot|"::") + FNAME + ARGDECL.Q() + COMPSTMT + END; END.Rule = "end"; // TERM.Q() + "end"; // SINGLETON : VARIABLE | `(' EXPR `)' SINGLETON.Rule = IDENTIFIER | "(" + EXPR + ")"; // WHEN_ARGS : ARGS [`,' `*' ARG] | `*' ARG WHEN_ARGS.Rule = ARGS + WithQ(comma + "*" + ARG) | "*" + ARG; // THEN : TERM | then | TERM then THEN.Rule = TERM | "then" | TERM + "then"; // DO : TERM | do | TERM do DO.Rule = TERM | "do" | TERM + "do"; // BLOCK_VAR : LHS | MLHS // BLOCK_VAR.Expression = LHS | MLHS; // -- ambiguous, changing to the following: BLOCK_VAR.Rule = IDENTIFIER | "(" + IDENTIFIER.Plus(comma) + ")"; // MLHS : MLHS_ITEM `,' [MLHS_ITEM (`,' MLHS_ITEM)*] [`*' [LHS]] | `*' LHS // MLHS.Expression = MLHS_ITEM.Plus(",") + WithQ("*" + LHS.Q()) | "*" + LHS; --ambiguous //MLHS.Expression = PRIMARY.Plus(",") + WithQ("*" + LHS.Q()) | "*" + LHS; // MLHS_ITEM : LHS | '(' MLHS ')' //MLHS_ITEM.Expression = LHS | "(" + MLHS + ")"; //--ambiguous!!! using PRIMARY //MLHS_ITEM = PRIMARY; /* LHS : VARIABLE | PRIMARY `[' [ARGS] `]' | PRIMARY `.' IDENTIFIER */ // LHS.Expression = IDENTIFIER | PRIMARY + "[" + ARGS.Q() + "]" | PRIMARY + dot + IDENTIFIER; LHS.Rule = OPERATION | PRIMARY + "[" + ARGS.Q() + "]" | "(" + EXPR + ")"; // MRHS : ARGS [`,' `*' ARG] | `*' ARG MRHS.Rule = ARGS + WithQ(comma + "*" + ARG) | "*" + ARG; /* CALL_ARGS : ARGS | ARGS [`,' ASSOCS] [`,' `*' ARG] [`,' `&' ARG] | ASSOCS [`,' `*' ARG] [`,' `&' ARG] | `*' ARG [`,' `&' ARG] | `&' ARG | COMMAND */ CALL_ARGS.Rule = // ARGS | //removed this - it is covered by next expression ARGS + WithQ(comma + ASSOCS) + STAR_ARG.Q() + AMP_ARG.Q() | ASSOCS + STAR_ARG.Q() + AMP_ARG.Q() | "*" + ARG + AMP_ARG.Q() | "&" + ARG | COMMAND; AMP_ARG.Rule = comma + "&" + ARG; STAR_ARG.Rule = comma + "*" + ARG; // ARGS : ARG (`,' ARG)* ARGS.Rule = ARG.Plus(comma); // ARGDECL : `(' ARGLIST `)' | ARGLIST TERM ARGDECL.Rule = "(" + ARGLIST + ")" | ARGLIST + TERM; /* ARGLIST : IDENTIFIER(`,'IDENTIFIER)*[`,'`*'[IDENTIFIER]][`,'`&'IDENTIFIER] | `*'IDENTIFIER[`,'`&'IDENTIFIER] | [`&'IDENTIFIER] */ ARGLIST.Rule = IDENTIFIER.Plus(comma) + WithQ(comma + "*" + IDENTIFIER.Q()) + WithQ(comma + "&" + IDENTIFIER) | "*" + IDENTIFIER + WithQ(comma + "&" + IDENTIFIER) | "&" + IDENTIFIER; // ASSOCS : ASSOC (`,' ASSOC)* ASSOCS.Rule = ASSOC.Plus(comma); //ASSOC : ARG `=>' ARG ASSOC.Rule = ARG + "=>" + ARG; // VARIABLE : VARNAME | nil | self -- variable is merged into IDENTIFIER //VARIABLE.Expression = IDENTIFIER | "nil" | "self"; // LITERAL : numeric | SYMBOL | STRING | STRING2 | HERE_DOC | REGEXP LITERAL.Rule = Number | SYMBOL | STRING | HereDoc | RegExLiteral; SYMBOL.Rule = Symbol(":") + IDENTIFIER; // (FNAME | VARNAME); //note 1. /* FNAME : IDENTIFIER | `..' | `|' | `^' | `&' | `<=>' | `==' | `===' | `=~' | `>' | `>=' | `<' | `<=' | `+' | `-' | `*' | `/' | `%' | `**' | `<<' | `>>' | `~' | `+@' | `-@' | `[]' | `[]=' */ FNAME.Rule = IDENTIFIER | ".." | "|" | "^" | "&" | "<=>" | "==" | "===" | "=~" | ">" | ">=" | "<" | "<=" | "+" | "-" | "*" | "/" | "%" | "**" | "<<" | ">>" | "~" | "+@" | "-@" | "[]" | "[]="; // TERM : `;' | `\n' TERM.Rule = NewLine | ";"; //NewLine is produced by token filter #endregion //error handling EXPR.ErrorRule = SyntaxError; DEFFUNC_STMT.ErrorRule = "def" + SyntaxError + COMPSTMT + END; #region misc: Operators, TokenFilters, etc //Register operators - not sure if precedence is assigned correctly RegisterOperators(100, Associativity.Right, "**"); RegisterOperators( 90, "<<", ">>"); RegisterOperators( 80, "*", "/", "%"); RegisterOperators( 70, "+", "-"); RegisterOperators( 60, "&", "&&", "and"); RegisterOperators( 50, "|", "||", "or", "^"); RegisterOperators( 40, ">", ">=", "<", "<=", "?"); RegisterOperators( 30, "<=>" , "==" , "===" , "!=" , "=~" , "!~"); RegisterOperators( 20, "..", "..."); RegisterPunctuation("(", ")", "," ); CodeOutlineFilter filter = new CodeOutlineFilter(false); TokenFilters.Add(filter); #endregion }
public ReportingLanguage():base(false) { // 1. Terminals var numberLiteral = TerminalFactory.CreateCSharpNumber("Number"); var boolean = new ConstantTerminal("Boolean"); boolean.Add("true", true); boolean.Add("false", false); boolean.Priority = 10; var nil = new ConstantTerminal("Null"); nil.Add("null", null); nil.Add("nothing", null); nil.Priority = 10; var identifier = new IdentifierTerminal("Identifier"); var stringLiteral = new StringLiteral("String","'",StringFlags.AllowsDoubledQuote); stringLiteral.AddStartEnd("\"",StringFlags.AllowsAllEscapes); Terminal dot = Symbol(".", "dot"); Terminal less = Symbol("<"); Terminal greater = Symbol(">"); Terminal LCb = Symbol("("); Terminal RCb = Symbol(")"); Terminal RFb = Symbol("}"); Terminal LFb = Symbol("{"); Terminal comma = Symbol(","); // Terminal LSb = Symbol("["); // Terminal RSb = Symbol("]"); var exclamationMark = Symbol("!"); Terminal and = Symbol("and"); and.Priority = 10; Terminal or = Symbol("or"); or.Priority = 10; var UserSection = Symbol("User"); var GlobalSection = Symbol("Globals"); var ParameterSection = Symbol("Parameters"); var FieldsSection = Symbol("Fields"); // 2. Non-terminals var FieldRef = new NonTerminal("FieldRef"); var userSectionStmt = new NonTerminal("UserSectionStmt"); var globalSectionStmt = new NonTerminal("GlobalSectionStmt"); var parameterSectionStmt = new NonTerminal("ParameterSectionStmt"); var fieldsSectionStmt = new NonTerminal("FieldsSectionStmt"); var QualifiedName = new NonTerminal("QualifiedName"); var FunctionExpression = new NonTerminal("FunctionExpression"); var Condition = new NonTerminal("Condition"); var Conditional = new NonTerminal("IfThen"); var Expr = new NonTerminal("Expr"); var BinOp = new NonTerminal("BinOp"); var LUnOp = new NonTerminal("LUnOp"); var ExprList = new NonTerminal("ExprList"); var BinExpr = new NonTerminal("BinExpr", typeof(BinExprNode)); var ProgramLine = new NonTerminal("ProgramLine"); var Program = new NonTerminal("Program", typeof(StatementListNode)); // 3. BNF rules #region Reporting userSectionStmt.Rule = UserSection + exclamationMark + Symbol("UserId") |UserSection + exclamationMark + Symbol("Language"); globalSectionStmt.Rule = GlobalSection + exclamationMark + Symbol("PageNumber") | GlobalSection + exclamationMark + Symbol("TotalPages") | GlobalSection + exclamationMark + Symbol("ExecutionTime") | GlobalSection + exclamationMark + Symbol("ReportFolder") | GlobalSection + exclamationMark + Symbol("ReportName"); parameterSectionStmt.Rule = ParameterSection + exclamationMark + identifier; fieldsSectionStmt.Rule = FieldsSection + exclamationMark + identifier; #endregion Expr.Rule = Symbol("null") | boolean | nil | stringLiteral | numberLiteral | QualifiedName | FunctionExpression | LCb + Expr + RCb | LFb + QualifiedName + RFb | Conditional | BinExpr //| Expr + BinOp + Expr //| LUnOp + Expr | parameterSectionStmt | globalSectionStmt | userSectionStmt | fieldsSectionStmt; ExprList.Rule = MakePlusRule(ExprList, comma, Expr); BinOp.Rule = Symbol("+") | "-" | "*" | "%" | "^" | "&" | "|" | "/" | "&&" | "||" | "==" | "!=" | greater | less | ">=" | "<=" | "is" | "<>" | "=" //| "+=" | "-=" | "." | and | or; LUnOp.Rule = Symbol("-") | "!"; FunctionExpression.Rule = QualifiedName + LCb + ExprList.Q() + RCb | QualifiedName + LCb + BinExpr + RCb; QualifiedName.Rule = identifier | QualifiedName + dot + identifier | parameterSectionStmt + "!" + identifier | "#" + identifier ; Condition.Rule = LCb + Expr + RCb; Conditional.Rule = "if" + Condition + "then" + Expr | "if" + Condition + "then" + Expr + "else" + Expr | "if" + Condition + "then" + Expr + "otherwise" + Expr; BinExpr.Rule = Expr + BinOp + Expr | LUnOp + Expr; ProgramLine.Rule = Expr + NewLine; Program.Rule = MakeStarRule(Program, ProgramLine); this.Root = Program; // Set grammar root #region 5. Operators precedence RegisterOperators(1, "is", "=", "==", "!=", "<>", ">", "<", ">=", "<="); RegisterOperators(2, "+", "-"); RegisterOperators(3, "*", "/", "%"); RegisterOperators(4, Associativity.Right, "^"); RegisterOperators(5, "|", "||", "or"); RegisterOperators(6, "&", "&&", "and"); RegisterOperators(7, "!"); #endregion RegisterPunctuation("(", ")", "[", "]", "{", "}", ",", ";"); MarkTransient( Expr, BinOp); //automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source this.SetLanguageFlags(LanguageFlags.NewLineBeforeEOF | LanguageFlags.SupportsInterpreter | LanguageFlags.AutoDetectTransient |LanguageFlags.CreateAst); }
public static StringLiteral CreateDasmString(string name, Options options) { var lit = new StringLiteral(name); lit.AddStartEnd("\"", StringOptions.AllowsXEscapes); return lit; }
public static StringLiteral CreateDasmCharacter(string name, Options options) { var lit = new StringLiteral(name); lit.AddStartEnd("'", StringOptions.AllowsXEscapes | StringOptions.IsChar); return lit; }
public DslPayoffGrammar() : base(false) { #region 1. Terminals var number = new NumberLiteral("number", NumberOptions.NoDotAfterInt) { //Let's allow big integers (with unlimited number of digits): DefaultIntTypes = new [] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt } }; var comma = ToTerm(","); var identifier = new IdentifierTerminal("identifier"); var scheduleId = new RegexBasedTerminal("scheduleId", @"[a-z]+date"); scheduleId.AstConfig.NodeType = typeof(ScheduleIdNode); //String literal with embedded expressions ------------------------------------------------------------------ var stringLit = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLit.AddStartEnd("'", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLit.AstConfig.NodeType = typeof(StringTemplateNode); var Expr = new NonTerminal("Expr"); //declare it here to use in template definition var templateSettings = new StringTemplateSettings //by default set to Ruby-style settings { //this defines how to evaluate expressions inside template ExpressionRoot = Expr }; this.SnippetRoots.Add(Expr); stringLit.AstConfig.Data = templateSettings; //-------------------------------------------------------------------------------------------------------- #endregion #region 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 TernaryIfExpr = new NonTerminal("TernaryIf", typeof(IfNode)); var ArgList = new NonTerminal("ArgList", typeof(ExpressionListNode)); var FunctionCall = new NonTerminal("FunctionCall", typeof(FunctionCallNode)); var MemberAccess = new NonTerminal("MemberAccess", typeof(MemberAccessNode)); var UnOp = new NonTerminal("UnOp"); var BinOp = new NonTerminal("BinOp", "operator"); var Fixing = new NonTerminal("Fixing", typeof(FixingNode)); #endregion #region 3. BNF rules Expr.Rule = Term | UnExpr | BinExpr | TernaryIfExpr | Fixing; Term.Rule = number | ParExpr | stringLit | FunctionCall | identifier | MemberAccess; ParExpr.Rule = "(" + Expr + ")"; UnExpr.Rule = UnOp + Term + ReduceHere(); UnOp.Rule = ToTerm("+") | "-" | "!"; BinExpr.Rule = Expr + BinOp + Expr; BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**" | "==" | "<" | "<=" | ">" | ">=" | "!=" | "&&" | "||" | "&" | "|"; TernaryIfExpr.Rule = Expr + "?" + Expr + ":" + Expr; MemberAccess.Rule = Expr + PreferShiftHere() + "." + identifier; ArgList.Rule = MakeStarRule(ArgList, comma, Expr); FunctionCall.Rule = identifier + PreferShiftHere() + "(" + ArgList + ")"; FunctionCall.NodeCaptionTemplate = "call #{0}(...)"; Fixing.Rule = (identifier) + PreferShiftHere() + "@" + scheduleId; #endregion Root = Expr; // Set grammar root #region 4. Operators precedence RegisterOperators(10, "?"); RegisterOperators(15, "&", "&&", "|", "||"); RegisterOperators(20, "==", "<", "<=", ">", ">=", "!="); RegisterOperators(30, "+", "-"); RegisterOperators(40, "*", "/"); RegisterOperators(50, Associativity.Right, "**"); RegisterOperators(60, "!"); // For precedence to work, we need to take care of one more thing: BinOp. //For BinOp which is or-combination of binary operators, we need to either // 1) mark it transient or 2) set flag TermFlags.InheritPrecedence // We use first option, making it Transient. // 5. Punctuation and transient terms MarkPunctuation("(", ")", "?", ":", "[", "]"); RegisterBracePair("(", ")"); RegisterBracePair("[", "]"); MarkTransient(Term, Expr, BinOp, UnOp, ParExpr); // 7. Syntax error reporting MarkNotReported("++", "--"); AddToNoReportGroup("(", "++", "--"); AddToNoReportGroup(NewLine); AddOperatorReportGroup("operator"); AddTermsReportGroup("assignment operator", "=", "+=", "-=", "*=", "/="); #endregion //9. Language flags. // Automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt; }
public static StringLiteral CreateSqlExtIdentifier(String name) { StringLiteral term = new StringLiteral(name); term.AddStartEnd("[", "]", StringFlags.NoEscapes); term.AddStartEnd("\"", StringFlags.NoEscapes); return term; }
private void MakeSimpleId() { Identifier = new IdentifierTerminal("simple_id"); var idStringLiteral = new StringLiteral("simple_id_quoted"); idStringLiteral.AddStartEnd("\"", StringOptions.NoEscapes); idStringLiteral.AstConfig.NodeType = typeof(IdentifierNode); idStringLiteral.SetOutputTerminal(this, Identifier); }
private void InitGrammar() { this.GrammarComments = @"One first go at it."; // 1. Non-terminals var Expr = new NonTerminal("Expr"); //declare it here to use in template definition 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 TernaryIfExpr = new NonTerminal("TernaryIf", typeof(IfNode)); var ArgList = new NonTerminal("ArgList", typeof(ExpressionListNode)); var FunctionCall = new NonTerminal("FunctionCall", typeof(FunctionCallNode)); var MemberAccess = new NonTerminal("MemberAccess", typeof(MemberAccessNode)); // var IndexedAccess = new NonTerminal("IndexedAccess", typeof(IndexedAccessNode)); // var ObjectRef = new NonTerminal("ObjectRef"); // foo, foo.bar or f['bar'] 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"); // selects var SelectStatement = new NonTerminal("SelectStatement", typeof(SelectStatement)); var SelectRoot = new NonTerminal("SelectRoot", typeof(SelectRoot)); var SelectRootModel = new NonTerminal("SelectRootModel", typeof(EmptyStatementNode)); var SelectRootElementList = new NonTerminal("SelectRootElementList", typeof(EmptyStatementNode)); var SelectRootElement = new NonTerminal("SelectRootElement", typeof(EmptyStatementNode)); var SelectExpression = new NonTerminal("SelectExpression", typeof(SelectExpressionNode)); var SelectFunction = new NonTerminal("SelectFunction", typeof(SelectFunctionNode)); var SelectMemberAccess = new NonTerminal("SelectMemberAccess", typeof(SelectMemberAccessNode)); var SelectProperty = new NonTerminal("SelectProperty", typeof(SelectPropertyNode)); var SelectFunctionName = new NonTerminal("SelectFunctionName", typeof(EmptyStatementNode)); var SelectTerm = new NonTerminal("SelectItem", typeof(EmptyStatementNode)); var NumberOrEmpty = new NonTerminal("NumberOrEmpty", typeof(EmptyStatementNode)); var IfcClassProperty = new NonTerminal("IfcClassProperty", typeof(IfcClassPropertyNode)); // core var Statement = new NonTerminal("Statement"); var Program = new NonTerminal("Program", typeof(StatementListNode)); // 2. Terminals var number = new NumberLiteral("number"); number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64 }; //Let's allow big integers (with unlimited number of digits): var identifier = new IdentifierTerminal("identifier"); var comma = ToTerm(","); var PositiveIntegerNumber = new NumberLiteral("IntegerNumber", NumberOptions.IntOnly); var stringLit = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes); var ElementIdStart = ToTerm("@"); stringLit.AddStartEnd("'", StringOptions.AllowsAllEscapes); /* * for embedded expressions: var templateSettings = new StringTemplateSettings(); //by default set to Ruby-style settings templateSettings.ExpressionRoot = Expr; //this defines how to evaluate expressions inside template this.SnippetRoots.Add(Expr); stringLit.AstConfig.Data = templateSettings; */ // 3. BNF rules Expr.Rule = Term | UnExpr | BinExpr | PrefixIncDec | PostfixIncDec | TernaryIfExpr; Term.Rule = number | ParExpr | stringLit | FunctionCall | identifier | IfcClassProperty | MemberAccess; // | IndexedAccess; // | MemberAccess; ParExpr.Rule = "(" + Expr | SelectStatement + ")"; UnExpr.Rule = UnOp + Term + ReduceHere(); UnOp.Rule = ToTerm("+") | "-" | "!"; BinExpr.Rule = Expr + BinOp + Expr; BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**" | "==" | "<" | "<=" | ">" | ">=" | "!=" | "&&" | "||" | "&" | "|"; PrefixIncDec.Rule = IncDecOp + identifier; PostfixIncDec.Rule = identifier + PreferShiftHere() + IncDecOp; IncDecOp.Rule = ToTerm("++") | "--"; TernaryIfExpr.Rule = Expr + "?" + Expr + ":" + Expr; MemberAccess.Rule = Expr + PreferShiftHere() + "." + identifier; IfcClassProperty.Rule = ElementIdStart + identifier; AssignmentStmt.Rule = identifier + AssignmentOp + Expr; AssignmentOp.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/="; Statement.Rule = AssignmentStmt | Expr | SelectStatement | Empty; ArgList.Rule = MakeStarRule(ArgList, comma, Expr); FunctionCall.Rule = Expr + PreferShiftHere() + "(" + ArgList + ")"; FunctionCall.NodeCaptionTemplate = "call #{0}(...)"; // select var dot = ToTerm("."); dot.SetFlag(TermFlags.IsTransient); var select = ToTerm("select"); select.SetFlag(TermFlags.IsTransient); SelectStatement.Rule = select + SelectRoot + SelectExpression; var ModelAt = ToTerm("@"); ModelAt.SetFlag(TermFlags.IsTransient); SelectRoot.Rule = SelectRootModel + ModelAt + SelectRootElementList; SelectRootModel.Rule = identifier | Empty; SelectRootElementList.Rule = MakeStarRule(SelectRootElementList, comma, SelectRootElement); // can be empty SelectRootElement.Rule = identifier | PositiveIntegerNumber | ToTerm("*"); SelectExpression.Rule = Empty | SelectMemberAccess; SelectMemberAccess.Rule = dot + PreferShiftHere() + SelectTerm + SelectExpression; SelectTerm.Rule = SelectFunction | SelectProperty; SelectProperty.Rule = identifier; SelectFunction.Rule = SelectFunctionName + PreferShiftHere() + ToTerm("(") + ArgList + ")"; SelectFunctionName.Rule = ToTerm("Where") | "Range" | "Count"; Program.Rule = MakePlusRule(Program, NewLine, Statement); this.Root = Program; // Set grammar root // 4. Operators precedence RegisterOperators(10, "?"); RegisterOperators(15, "&", "&&", "|", "||"); RegisterOperators(20, "==", "<", "<=", ">", ">=", "!="); RegisterOperators(30, "+", "-"); RegisterOperators(40, "*", "/"); RegisterOperators(50, Associativity.Right, "**"); RegisterOperators(60, "!"); // For precedence to work, we need to take care of one more thing: BinOp. //For BinOp which is or-combination of binary operators, we need to either // 1) mark it transient or 2) set flag TermFlags.InheritPrecedence // We use first option, making it Transient. // 5. Punctuation and transient terms MarkPunctuation("(", ")", "?", ":"); //, "[", "]"); RegisterBracePair("(", ")"); // RegisterBracePair("[", "]"); MarkTransient(Term, Expr, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr); //, ObjectRef); MarkTransient(NumberOrEmpty, SelectExpression); MarkTransient(SelectTerm); // 7. Syntax error reporting MarkNotReported("++", "--"); AddToNoReportGroup("(", "++", "--"); AddToNoReportGroup(NewLine); AddOperatorReportGroup("operator"); AddTermsReportGroup("assignment operator", "=", "+=", "-=", "*=", "/="); //8. Console ConsoleTitle = "mah"; ConsoleGreeting = @"Irony Expression Evaluator"; ConsolePrompt = "?"; ConsolePromptMoreInput = "?"; //9. Language flags. // Automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.SupportsBigInt | LanguageFlags.CreateAst; }
//Covers simple identifiers like abcd, and also quoted versions: [abc d], "abc d". public static IdentifierTerminal CreateSqlExtIdentifier(Grammar grammar, string name) { var id = new IdentifierTerminal(name); StringLiteral term = new StringLiteral(name + "_qouted"); term.AddStartEnd("[", "]", StringOptions.NoEscapes); term.AddStartEnd("\"", StringOptions.NoEscapes); term.SetOutputTerminal(grammar, id); //term will be added to NonGrammarTerminals automatically return id; }
public ExpressionEvaluatorGrammar() : base(caseSensitive: false) { this.GrammarComments = @"Irony expression evaluator. Case-insensitive. Supports big integers, float data types, variables, assignments, arithmetic operations, augmented assignments (+=, -=), inc/dec (++,--), strings with embedded expressions; bool operations &,&&, |, ||; ternary '?:' operator."; // 1. Terminals var number = new NumberLiteral("number"); //Let's allow big integers (with unlimited number of digits): number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt }; var identifier = new IdentifierTerminal("identifier"); var comment = new CommentTerminal("comment", "#", "\n", "\r"); //comment must be added to NonGrammarTerminals list; it is not used directly in grammar rules, // so we add it to this list to let Scanner know that it is also a valid terminal. base.NonGrammarTerminals.Add(comment); var comma = ToTerm(","); //String literal with embedded expressions ------------------------------------------------------------------ var stringLit = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLit.AddStartEnd("'", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLit.AstNodeType = typeof(StringTemplateNode); var Expr = new NonTerminal("Expr"); //declare it here to use in template definition var templateSettings = new StringTemplateSettings(); //by default set to Ruby-style settings templateSettings.ExpressionRoot = Expr; //this defines how to evaluate expressions inside template this.SnippetRoots.Add(Expr); stringLit.AstData = templateSettings; //-------------------------------------------------------------------------------------------------------- // 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 TernaryIfExpr = new NonTerminal("TernaryIf", typeof(IfNode)); var ArgList = new NonTerminal("ArgList", typeof(ExpressionListNode)); var FunctionCall = new NonTerminal("FunctionCall", typeof(FunctionCallNode)); var MemberAccess = new NonTerminal("MemberAccess", typeof(MemberAccessNode)); var IndexedAccess = new NonTerminal("IndexedAccess", typeof(IndexedAccessNode)); var ObjectRef = new NonTerminal("ObjectRef"); // foo, foo.bar or f['bar'] 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 | TernaryIfExpr; Term.Rule = number | ParExpr | stringLit | FunctionCall | identifier | MemberAccess | IndexedAccess; ParExpr.Rule = "(" + Expr + ")"; UnExpr.Rule = UnOp + Term + ReduceHere(); UnOp.Rule = ToTerm("+") | "-"; BinExpr.Rule = Expr + BinOp + Expr; BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**" | "==" | "<" | "<=" | ">" | ">=" | "!=" | "&&" | "||" | "&" | "|"; PrefixIncDec.Rule = IncDecOp + identifier; PostfixIncDec.Rule = identifier + PreferShiftHere() + IncDecOp; IncDecOp.Rule = ToTerm("++") | "--"; TernaryIfExpr.Rule = Expr + "?" + Expr + ":" + Expr; MemberAccess.Rule = Expr + PreferShiftHere() + "." + identifier; AssignmentStmt.Rule = ObjectRef + AssignmentOp + Expr; AssignmentOp.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/="; Statement.Rule = AssignmentStmt | Expr | Empty; ArgList.Rule = MakeStarRule(ArgList, comma, Expr); FunctionCall.Rule = Expr + PreferShiftHere() + "(" + ArgList + ")"; FunctionCall.NodeCaptionTemplate = "call #{0}(...)"; ObjectRef.Rule = identifier | MemberAccess | IndexedAccess; IndexedAccess.Rule = Expr + PreferShiftHere() + "[" + Expr + "]"; Program.Rule = MakePlusRule(Program, NewLine, Statement); this.Root = Program; // Set grammar root // 4. Operators precedence RegisterOperators(10, "?"); RegisterOperators(15, "&", "&&", "|", "||"); RegisterOperators(20, "==", "<", "<=", ">", ">=", "!="); RegisterOperators(30, "+", "-"); RegisterOperators(40, "*", "/"); RegisterOperators(50, Associativity.Right, "**"); // 5. Punctuation and transient terms MarkPunctuation("(", ")", "?", ":", "[", "]"); RegisterBracePair("(", ")"); RegisterBracePair("[", "]"); MarkTransient(Term, Expr, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr, ObjectRef); // 7. Syntax error reporting MarkNotReported("++", "--"); AddToNoReportGroup("(", "++", "--"); AddToNoReportGroup(NewLine); AddOperatorReportGroup("operator"); AddTermsReportGroup("assignment operator", "=", "+=", "-=", "*=", "/="); //8. Console ConsoleTitle = "Irony Expression Evaluator"; ConsoleGreeting = @"Irony Expression Evaluator Supports variable assignments, arithmetic operators (+, -, *, /), augmented assignments (+=, -=, etc), prefix/postfix operators ++,--, string operations. Supports big integer arithmetics, string operations. Supports strings with embedded expressions : ""name: #{name}"" Press Ctrl-C to exit the program at any time. "; ConsolePrompt = "?"; ConsolePromptMoreInput = "?"; //9. Language flags. // Automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt; }
public ODataFilterGrammar() { //Terminals var simpleIdentifier = TerminalFactory.CreateCSharpIdentifier("Identifier"); var stringLiteral = new StringLiteral("StringLiteral", "'", StringOptions.NoEscapes | StringOptions.AllowsDoubledQuote); var numberLiteral = new NumberLiteral("NumberLiteral"); // This impl has problems with .NET 4.5 - so ToTerm methods below were used instead. //var constant = new ConstantTerminal("Constant", typeof(Object)); //constant.Add("true", true); //constant.Add("false", false); //constant.Add("null", null); var trueLiteral = ToTerm("true", "Constant"); var falseLiteral = ToTerm("false", "Constant"); var nullLiteral = ToTerm("null", "Constant"); var dateTimeOffsetLiteral = new StringLiteral("DateTimeOffsetLiteral"); dateTimeOffsetLiteral.AddStartEnd("datetimeoffset'", "'", StringOptions.None); var dateTimeLiteral = new StringLiteral("DateTimeLiteral"); dateTimeLiteral.AddStartEnd("datetime'", "'", StringOptions.None); var timeLiteral = new StringLiteral("TimeLiteral"); timeLiteral.AddStartEnd("time'", "'", StringOptions.None); var guidLiteral = new StringLiteral("GuidLiteral"); guidLiteral.AddStartEnd("guid'", "'", StringOptions.None); //NonTerminals var baseExpr = new NonTerminal("BaseExpr"); var compositeIdentifier = new NonTerminal("CompositeIdentifier"); var parenExpr = new NonTerminal("ParenExpr"); var methodCallExpr = new NonTerminal("MethodCallExpr"); var literalExpr = new NonTerminal("LiteralExpr"); var subExpr = new NonTerminal("SubExpr"); var lambdaExpr = new NonTerminal("LambdaExpr"); var lambdaVariable = new NonTerminal("LambdaVariable"); var memberExpr = new NonTerminal("MemberExpr"); var binaryExpr = new NonTerminal("BinaryExpr"); var binaryExprOp = new NonTerminal("BinaryExprOp"); var unaryExpr = new NonTerminal("UnaryExpr"); var unaryExprOp = new NonTerminal("UnaryExprOp"); #region Methods // bool var anyMethodCallExpr = new NonTerminal("AnyMethodCallExpr"); var allMethodCallExpr = new NonTerminal("AllMethodCallExpr"); var substringOfMethodCallExpr = new NonTerminal("SubstringOfMethodCallExpr"); var endsWithMethodCallExpr = new NonTerminal("EndsWithMethodCallExpr"); var startsWithMethodCallExpr = new NonTerminal("StartsWithMethodCallExpr"); // int var lengthMethodCallExpr = new NonTerminal("LengthMethodCallExpr"); var indexOfMethodCallExpr = new NonTerminal("IndexOfMethodCallExpr"); // string var replaceMethodCallExpr = new NonTerminal("ReplaceMethodCallExpr"); var substring1MethodCallExpr = new NonTerminal("Substring1MethodCallExpr"); var substring2MethodCallExpr = new NonTerminal("Substring2MethodCallExpr"); var toLowerMethodCallExpr = new NonTerminal("ToLowerMethodCallExpr"); var toUpperMethodCallExpr = new NonTerminal("ToUpperMethodCallExpr"); var trimMethodCallExpr = new NonTerminal("TrimMethodCallExpr"); var concatMethodCallExpr = new NonTerminal("ConcatMethodCallExpr"); // date var secondMethodCallExpr = new NonTerminal("SecondMethodCallExpr"); var minuteMethodCallExpr = new NonTerminal("MinuteMethodCallExpr"); var hourMethodCallExpr = new NonTerminal("HourMethodCallExpr"); var dayMethodCallExpr = new NonTerminal("DayMethodCallExpr"); var monthMethodCallExpr = new NonTerminal("MonthMethodCallExpr"); var yearMethodCallExpr = new NonTerminal("YearMethodCallExpr"); // math var roundMethodCallExpr = new NonTerminal("RoundMethodCallExpr"); var floorMethodCallExpr = new NonTerminal("FloorMethodCallExpr"); var ceilingMethodCallExpr = new NonTerminal("CeilingMethodCallExpr"); // type var isOf1MethodCallExpr = new NonTerminal("isOf1MethodCallExpr"); var isOf2MethodCallExpr = new NonTerminal("isOf2MethodCallExpr"); #endregion Root = baseExpr; baseExpr.Rule = parenExpr | literalExpr | memberExpr | methodCallExpr | binaryExpr | unaryExpr; parenExpr.Rule = "(" + baseExpr + ")"; literalExpr.Rule = stringLiteral | numberLiteral // | constant | trueLiteral | falseLiteral | nullLiteral | dateTimeLiteral | dateTimeOffsetLiteral | timeLiteral | guidLiteral; subExpr.Rule = simpleIdentifier | anyMethodCallExpr | allMethodCallExpr; KeyTerm backSlash = ToTerm("/", "backslash"); compositeIdentifier.Rule = MakePlusRule(compositeIdentifier, backSlash, subExpr); memberExpr.Rule = compositeIdentifier; lambdaVariable.Rule = simpleIdentifier + ":"; lambdaExpr.Rule = lambdaVariable + baseExpr; unaryExpr.Rule = unaryExprOp + baseExpr; unaryExprOp.Rule = (BnfExpression)"not" | "-"; binaryExpr.Rule = baseExpr + binaryExprOp + baseExpr; binaryExprOp.Rule = (BnfExpression)"eq" | "ne" | "lt" | "le" | "gt" | "ge" | "add" | "sub" | "mul" | "div" | "mod" | "and" | "or"; methodCallExpr.Rule = anyMethodCallExpr | allMethodCallExpr | replaceMethodCallExpr | substring1MethodCallExpr | substring2MethodCallExpr | toLowerMethodCallExpr | toUpperMethodCallExpr | trimMethodCallExpr | concatMethodCallExpr | lengthMethodCallExpr | indexOfMethodCallExpr | secondMethodCallExpr | minuteMethodCallExpr | hourMethodCallExpr | dayMethodCallExpr | monthMethodCallExpr | yearMethodCallExpr | roundMethodCallExpr | floorMethodCallExpr | ceilingMethodCallExpr | isOf1MethodCallExpr | isOf2MethodCallExpr | substringOfMethodCallExpr | startsWithMethodCallExpr | endsWithMethodCallExpr; anyMethodCallExpr.Rule = (BnfExpression)"any" + "(" + lambdaExpr + ")"; allMethodCallExpr.Rule = (BnfExpression)"all" + "(" + lambdaExpr + ")"; replaceMethodCallExpr.Rule = (BnfExpression)"replace" + "(" + baseExpr + "," + baseExpr + "," + baseExpr + ")"; substring1MethodCallExpr.Rule = (BnfExpression)"substring" + "(" + baseExpr + "," + baseExpr + ")"; substring2MethodCallExpr.Rule = (BnfExpression)"substring" + "(" + baseExpr + "," + baseExpr + "," + baseExpr + ")"; toLowerMethodCallExpr.Rule = (BnfExpression)"tolower" + "(" + baseExpr + ")"; toUpperMethodCallExpr.Rule = (BnfExpression)"toupper" + "(" + baseExpr + ")"; trimMethodCallExpr.Rule = (BnfExpression)"trim" + "(" + baseExpr + ")"; concatMethodCallExpr.Rule = (BnfExpression)"concat" + "(" + baseExpr + "," + baseExpr + ")"; lengthMethodCallExpr.Rule = (BnfExpression)"length" + "(" + baseExpr + ")"; indexOfMethodCallExpr.Rule = (BnfExpression)"indexof" + "(" + baseExpr + "," + baseExpr + ")"; substringOfMethodCallExpr.Rule = (BnfExpression)"substringof" + "(" + baseExpr + "," + baseExpr + ")"; startsWithMethodCallExpr.Rule = (BnfExpression)"startswith" + "(" + baseExpr + "," + baseExpr + ")"; endsWithMethodCallExpr.Rule = (BnfExpression)"endswith" + "(" + baseExpr + "," + baseExpr + ")"; secondMethodCallExpr.Rule = (BnfExpression)"second" + "(" + baseExpr + ")"; minuteMethodCallExpr.Rule = (BnfExpression)"minute" + "(" + baseExpr + ")"; hourMethodCallExpr.Rule = (BnfExpression)"hour" + "(" + baseExpr + ")"; dayMethodCallExpr.Rule = (BnfExpression)"day" + "(" + baseExpr + ")"; monthMethodCallExpr.Rule = (BnfExpression)"month" + "(" + baseExpr + ")"; yearMethodCallExpr.Rule = (BnfExpression)"year" + "(" + baseExpr + ")"; roundMethodCallExpr.Rule = (BnfExpression)"round" + "(" + baseExpr + ")"; ceilingMethodCallExpr.Rule = (BnfExpression)"ceiling" + "(" + baseExpr + ")"; floorMethodCallExpr.Rule = (BnfExpression)"floor" + "(" + baseExpr + ")"; isOf1MethodCallExpr.Rule = (BnfExpression)"isof" + "(" + baseExpr + ")"; isOf2MethodCallExpr.Rule = (BnfExpression)"isof" + "(" + baseExpr + "," + baseExpr + ")"; RegisterOperators(10, "or"); RegisterOperators(20, "and"); RegisterOperators(30, "eq", "ne", "lt", "le", "gt", "ge"); RegisterOperators(40, "add", "sub", "mul", "div", "mod"); RegisterOperators(50, "-"); RegisterBracePair("(", ")"); MarkPunctuation(",", "(", ")", "/", ":"); MarkTransient(baseExpr); MarkTransient(binaryExprOp); MarkTransient(unaryExprOp); MarkTransient(parenExpr); MarkTransient(methodCallExpr); MarkTransient(literalExpr); MarkTransient(subExpr); MarkTransient(lambdaVariable); }
public QueryLanguageGrammar() : base(false) { var comment = new CommentTerminal("lineComment", "//", "\n", "\r\n"); NonGrammarTerminals.Add(comment); var comma = ToTerm(","); //LITERALS var integerLiteral = new NumberLiteral("integerLiteral", NumberOptions.IntOnly | NumberOptions.NoDotAfterInt); var stringLiteral = new StringLiteral("stringLiteral"); stringLiteral.AddStartEnd("\"", StringOptions.NoEscapes); stringLiteral.AddStartEnd("'", StringOptions.NoEscapes); var decimalLiteral = new NumberLiteral("decimalLiteral", NumberOptions.AllowSign | NumberOptions.AllowStartEndDot); var parsedLiteral = new NonTerminal("parsedLiteral"); var parsedLiteralType = CreateNonTerminal("parsedLiteralType", ToTerm("date") | "timeofday" | "datetime"); parsedLiteral.Rule = parsedLiteralType + stringLiteral; var literals = CreateNonTerminal("literals", ToTerm("null") | "true" | "false" | integerLiteral | stringLiteral | decimalLiteral | parsedLiteral); //OPERATORS var binaryOperator = CreateNonTerminal("binaryOperator", ToTerm("*") | "-" | "+" | "/" | "%" | "=" | "!=" | "<>" | "<" | "<=" | ">" | ">=" | "is" | "contains" | "starts with" | "ends with" | "matches" | "like" | "and" | "or" | "not"); //CLAUSES var selectClause = new NonTerminal("selectClause"); var whereClause = new NonTerminal("whereClause"); var groupByClause = new NonTerminal("groupByClause"); var pivotClause = new NonTerminal("pivotClause"); var orderByClause = new NonTerminal("orderByClause"); var limitClause = new NonTerminal("limitClause"); var offsetClause = new NonTerminal("offsetClause"); var labelClause = new NonTerminal("labelClause"); var formatClause = new NonTerminal("formatClause"); var optionsClause = new NonTerminal("optionsClause"); //IDENTIFIERS AND EXPRESSIONS var identifier = CreateIdentifier(); var identifierList = new NonTerminal("identifierList"); var selectList = new NonTerminal("selectList"); var expressionList = new NonTerminal("expressionList"); var expression = new NonTerminal("expression"); //var unaryExpression = new NonTerminal("unaryExpression"); var binaryExpression = new NonTerminal("binaryExpression"); var parExpression = new NonTerminal("parExpression"); var aggregate = new NonTerminal("aggregate"); var aggregateName = new NonTerminal("aggregateName"); //TODO: var scalar var term = new NonTerminal("term"); var orderBy = new NonTerminal("orderBy"); var orderDirection = new NonTerminal("orderDirection"); var orderByList = new NonTerminal("orderByList"); var label = new NonTerminal("label"); var labelList = new NonTerminal("labelList"); //ROOT var query = new NonTerminal("query"); this.Root = query; query.Rule = selectClause + whereClause + groupByClause + pivotClause + orderByClause + limitClause + offsetClause + labelClause + formatClause + optionsClause; selectClause.Rule = Empty | "select" + selectList; whereClause.Rule = Empty | "where" + expression; groupByClause.Rule = Empty | "group by" + identifierList; pivotClause.Rule = Empty | "pivot" + identifierList; orderByClause.Rule = Empty | "order by" + orderByList; limitClause.Rule = Empty | "limit" + integerLiteral; offsetClause.Rule = Empty | "offset" + integerLiteral; labelClause.Rule = Empty | "label" + labelList; formatClause.Rule = Empty | "format" + labelList; optionsClause.Rule = Empty | "options" + "no_format" | "options" + "no_values"; selectList.Rule = ToTerm("*") | expressionList; expressionList.Rule = MakePlusRule(expressionList, comma, expression); expression.Rule = term | binaryExpression; // unaryExpression term.Rule = literals | parExpression | identifier | aggregate; parExpression.Rule = "(" + expression + ")"; //unaryExpression = unaryOperator + term; //unaryOperator.Rule = binaryExpression.Rule = expression + binaryOperator + expression; aggregate.Rule = aggregateName + "(" + identifier + ")"; aggregateName.Rule = ToTerm("avg") | "count" | "max" | "min" | "sum"; identifierList.Rule = MakePlusRule(identifierList, comma, identifier); orderBy.Rule = expression + orderDirection; orderDirection.Rule = Empty | "asc" | "desc"; orderByList.Rule = MakePlusRule(orderByList, comma, orderBy); label.Rule = expression + stringLiteral; labelList.Rule = MakePlusRule(labelList, comma, label); //TODO: clean up, differentiate between comparison and calculation, add scalars MarkPunctuation(",", "(", ")"); RegisterBracePair("(", ")"); RegisterOperators(10, "*", "/", "%"); RegisterOperators(9, "+", "-"); RegisterOperators(8, "<", "<=", ">", ">="); RegisterOperators(7, "=", "<>", "!=", "is", "contains", "starts with", "ends with", "matches", "like"); RegisterOperators(6, "and"); RegisterOperators(5, "not"); RegisterOperators(4, "or"); MarkTransient(term, expression, parExpression, binaryOperator, aggregateName, parsedLiteralType, literals, selectList, expressionList, labelList, orderByList, orderDirection); }
public MiaGrammar() : base(caseSensitive: true) { // 1. Terminals var number = TerminalFactory.CreatePythonNumber("number"); var identifier = TerminalFactory.CreatePythonIdentifier("identifier"); //var propertyId = MiaTerminalFactory.CreatePropertyId("property"); var varId = MiaTerminalFactory.CreateVariableId("variable"); var nounId = MiaTerminalFactory.CreateNounId("noun"); var verbId = MiaTerminalFactory.CreateVerbId("verb"); var comment = new CommentTerminal("comment", "//", "\n", "\r"); //comment must to be added to NonGrammarTerminals list; it is not used directly in grammar rules, // so we add it to this list to let Scanner know that it is also a valid terminal. base.NonGrammarTerminals.Add(comment); var comma = ToTerm(","); var colon = ToTerm(":"); var semicolon = ToTerm(";"); var snippet1 = new StringLiteral("snippet"); var snippet2 = new StringLiteral("snippet2"); //snippet.AddStartEnd("{", "}", StringOptions.None); snippet1.AddStartEnd("{", "}", StringOptions.AllowsLineBreak); snippet2.AddStartEnd("{%", "%}", StringOptions.AllowsLineBreak); // 2. Non-terminals var Snippet = new NonTerminal("Snippet"); var Constituent = new NonTerminal("Constituent"); var Expr = new NonTerminal("Expr"); var Term = new NonTerminal("Term"); var BinExpr = new NonTerminal("BinExpr"); var ParExpr = new NonTerminal("ParExpr"); var UnExpr = new NonTerminal("UnExpr"); var UnOp = new NonTerminal("UnOp", "unary-operator"); var BinOp = new NonTerminal("BinOp", "binary-operator"); var ColonExpr = new NonTerminal("ColonExpr", "ColonExpr"); var CommaExpr = new NonTerminal("CommaExpr", "CommaExpr"); var PropertyExpr = new NonTerminal("PropertyExpr", "PropertyExpr"); var AssignmentStmt = new NonTerminal("AssignmentStmt"); var Stmt = new NonTerminal("Stmt"); var ExtStmt = new NonTerminal("ExtStmt"); // var ReturnStmt = new NonTerminal("return"); var PassStmt = new NonTerminal("pass"); var Block = new NonTerminal("Block"); var StmtList = new NonTerminal("StmtList"); // var DeclBlock = new NonTerminal("DeclBlock"); var DeclStmtList = new NonTerminal("DeclStmtList"); var ParamList = new NonTerminal("ParamList"); var ArgList = new NonTerminal("ArgList"); var FunctionDef = new NonTerminal("FunctionDef"); var FunctionCall = new NonTerminal("FunctionCall"); // var NamespaceDef = new NonTerminal("NamespaceDef"); var BrainDef = new NonTerminal("BrainDef"); var ExpertDef = new NonTerminal("ExpertDef"); var MethodDef = new NonTerminal("MethodDef"); var PredicateDef = new NonTerminal("PredicateDef"); var ClauseExpr = new NonTerminal("ClauseExpr"); var PropertyList = new NonTerminal("PropertyList"); // var WhereActions = new NonTerminal("WhereActions"); var WhereAction = new NonTerminal("WhereAction"); var WhereStmt = new NonTerminal("WhereStmt"); var IfTrueStmt = new NonTerminal("IfTrueStmt"); var IfFalseStmt = new NonTerminal("IfFalseStmt"); var IfAllTrueStmt = new NonTerminal("IfAllTrueStmt"); var IfAllFalseStmt = new NonTerminal("IfAllFalseStmt"); // var SelectStmt = new NonTerminal("SelectStmt"); var CaseStmt = new NonTerminal("CaseStmt"); // 3. BNF rules //Expr.Rule = Term | UnExpr | BinExpr; Expr.Rule = Term | UnExpr | BinExpr | PropertyExpr; Constituent.Rule = number | ParExpr | nounId | varId | Snippet; Snippet.Rule = snippet1 | snippet2; Term.Rule = varId | nounId | ClauseExpr; ParExpr.Rule = "(" + Expr + ")"; UnExpr.Rule = UnOp + Expr | UnOp + UnExpr; UnOp.Rule = ToTerm("+") | "-" | "*" | "@" | "/" | "not"; BinExpr.Rule = Expr + BinOp + Expr; CommaExpr.Rule = Expr + "," + Eos + Block; ColonExpr.Rule = Expr + ":" + Eos + Block; PropertyExpr.Rule = Term + "`" + Term; BinOp.Rule = ToTerm("&&") | "||" | "~=" | "==" | "->"; AssignmentStmt.Rule = identifier + "=" + Expr; Stmt.Rule = AssignmentStmt | Snippet | Expr | PassStmt | ReturnStmt | Empty; ReturnStmt.Rule = "return" + (Expr | Empty); PassStmt.Rule = "pass"; //Eos is End-Of-Statement token produced by CodeOutlineFilter Block.Rule = Indent + StmtList + Dedent; DeclBlock.Rule = Indent + StmtList + Dedent; StmtList.Rule = MakePlusRule(StmtList, ExtStmt); ExtStmt.Rule = Stmt + Eos | ColonExpr | CommaExpr | NamespaceDef | BrainDef | ExpertDef | MethodDef | WhereStmt | PredicateDef | SelectStmt | CaseStmt; ParamList.Rule = MakeStarRule(ParamList, comma, identifier); ArgList.Rule = MakeStarRule(ArgList, comma, Expr); FunctionDef.Rule = "def" + identifier + "(" + ParamList + ")" + colon + Eos + Block; FunctionDef.NodeCaptionTemplate = "def #{1}(...)"; FunctionCall.Rule = identifier + "(" + ArgList + ")"; FunctionCall.NodeCaptionTemplate = "call #{0}(...)"; // NamespaceDef.Rule = "namespace" + identifier + Eos + Block; BrainDef.Rule = "brain" + identifier + Eos + Block; ExpertDef.Rule = "expert" + identifier + Eos + Block; //MethodDef.Rule = "method" + identifier + "(" + (Expr | Empty) + ")" + Eos + Block; MethodDef.Rule = ("method" + identifier + "(" + ArgList + ")" + Eos + Block) | ("method" + identifier + Eos + Block); PredicateDef.Rule = "predicate" + identifier + "(" + ParamList + ")" + Eos; // WhereActions.Rule = MakePlusRule(WhereActions, WhereAction); WhereAction.Rule = IfTrueStmt | IfFalseStmt | IfAllTrueStmt | IfAllFalseStmt; WhereStmt.Rule = "where" + Eos + Block + WhereActions; IfTrueStmt.Rule = "-->" + Eos + Block; IfFalseStmt.Rule = "~->" + Eos + Block; IfAllTrueStmt.Rule = "==>" + Eos + Block; IfAllFalseStmt.Rule = "~=>" + Eos + Block; // SelectStmt.Rule = "select" + Eos + Block; CaseStmt.Rule = "case" + Snippet + Eos + Block; // PropertyList.Rule = MakeStarRule(PropertyList, comma, Expr); // ClauseExpr.Rule = verbId | (Constituent + verbId) | (verbId + Constituent) | (Constituent + verbId + Constituent); // // this.Root = StmtList; // Set grammar root // 4. Token filters - created in a separate method CreateTokenFilters // we need to add continuation symbol to NonGrammarTerminals because it is not used anywhere in grammar NonGrammarTerminals.Add(ToTerm(@"\")); // 5. Operators precedence //RegisterOperators(1, "+", "-"); //RegisterOperators(2, "*", "/"); //RegisterOperators(3, Associativity.Right, "**"); // 6. Miscellaneous: punctuation, braces, transient nodes MarkPunctuation("(", ")", ":"); RegisterBracePair("(", ")"); //MarkTransient(Term, Expr, Stmt, ExtStmt, UnOp, BinOp, ExtStmt, ParExpr, Block); MarkTransient(Term, Expr, Stmt, UnOp, BinOp, ExtStmt, ParExpr, Block, Constituent, Snippet); // 7. Error recovery rule ExtStmt.ErrorRule = SyntaxError + Eos; FunctionDef.ErrorRule = SyntaxError + Dedent; // 8. Syntax error reporting AddToNoReportGroup("("); AddToNoReportGroup(Eos); AddOperatorReportGroup("operator"); // 9. Initialize console attributes ConsoleTitle = "Mini-Python Console"; ConsoleGreeting = @"Irony Sample Console for mini-Python. Supports a small sub-set of Python: assignments, arithmetic operators, function declarations with 'def'. Supports big integer arithmetics. Supports Python indentation and line-joining rules, including '\' as a line joining symbol. Press Ctrl-C to exit the program at any time. "; ConsolePrompt = ">>>"; ConsolePromptMoreInput = "..."; // 10. Language flags //this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt; this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.SupportsBigInt; }//constructor
private NonTerminal InitEmbeddedCs(KeyTerm beginSegment, KeyTerm endSegment) { var regexNonDirective = new RegexBasedTerminal("NonDirectivePrefix", "(?![+=@])") { ErrorAlias = "<#@ can only be declared before any text or embedded code", SkipsWhitespaceAfter = false }; _embeddedCs = new NonTerminal("embeddedCs"); var embeddedCsText = new FreeTextLiteral("embeddedCsText", endSegment.Text); var stringLit = new StringLiteral("embeddedCsText"); stringLit.AddStartEnd(beginSegment.Text, endSegment.Text, StringOptions.AllowsLineBreak); _embeddedCs.Rule = beginSegment + regexNonDirective + embeddedCsText + endSegment; return EmbeddedCs; }
public ReportingLanguage() : base(false) { // 1. Terminals var numberLiteral = TerminalFactory.CreateCSharpNumber("Number"); var boolean = new ConstantTerminal("Boolean"); boolean.Add("true", true); boolean.Add("false", false); boolean.Priority = 10; var nil = new ConstantTerminal("Null"); nil.Add("null", null); nil.Add("nothing", null); nil.Priority = 10; var identifier = new IdentifierTerminal("Identifier"); var stringLiteral = new StringLiteral("String", "'", StringFlags.AllowsDoubledQuote); stringLiteral.AddStartEnd("\"", StringFlags.AllowsAllEscapes); Terminal dot = Symbol(".", "dot"); Terminal less = Symbol("<"); Terminal greater = Symbol(">"); Terminal LCb = Symbol("("); Terminal RCb = Symbol(")"); Terminal RFb = Symbol("}"); Terminal LFb = Symbol("{"); Terminal comma = Symbol(","); // Terminal LSb = Symbol("["); // Terminal RSb = Symbol("]"); var exclamationMark = Symbol("!"); Terminal and = Symbol("and"); and.Priority = 10; Terminal or = Symbol("or"); or.Priority = 10; var UserSection = Symbol("User"); var GlobalSection = Symbol("Globals"); var ParameterSection = Symbol("Parameters"); var FieldsSection = Symbol("Fields"); // 2. Non-terminals var FieldRef = new NonTerminal("FieldRef"); var userSectionStmt = new NonTerminal("UserSectionStmt"); var globalSectionStmt = new NonTerminal("GlobalSectionStmt"); var parameterSectionStmt = new NonTerminal("ParameterSectionStmt"); var fieldsSectionStmt = new NonTerminal("FieldsSectionStmt"); var QualifiedName = new NonTerminal("QualifiedName"); var FunctionExpression = new NonTerminal("FunctionExpression"); var Condition = new NonTerminal("Condition"); var Conditional = new NonTerminal("IfThen"); var Expr = new NonTerminal("Expr"); var BinOp = new NonTerminal("BinOp"); var LUnOp = new NonTerminal("LUnOp"); var ExprList = new NonTerminal("ExprList"); var BinExpr = new NonTerminal("BinExpr", typeof(BinExprNode)); var ProgramLine = new NonTerminal("ProgramLine"); var Program = new NonTerminal("Program", typeof(StatementListNode)); // 3. BNF rules #region Reporting userSectionStmt.Rule = UserSection + exclamationMark + Symbol("UserId") | UserSection + exclamationMark + Symbol("Language"); globalSectionStmt.Rule = GlobalSection + exclamationMark + Symbol("PageNumber") | GlobalSection + exclamationMark + Symbol("TotalPages") | GlobalSection + exclamationMark + Symbol("ExecutionTime") | GlobalSection + exclamationMark + Symbol("ReportFolder") | GlobalSection + exclamationMark + Symbol("ReportName"); parameterSectionStmt.Rule = ParameterSection + exclamationMark + identifier; fieldsSectionStmt.Rule = FieldsSection + exclamationMark + identifier; #endregion Expr.Rule = Symbol("null") | boolean | nil | stringLiteral | numberLiteral | QualifiedName | FunctionExpression | LCb + Expr + RCb | LFb + QualifiedName + RFb | Conditional | BinExpr //| Expr + BinOp + Expr //| LUnOp + Expr | parameterSectionStmt | globalSectionStmt | userSectionStmt | fieldsSectionStmt; ExprList.Rule = MakePlusRule(ExprList, comma, Expr); BinOp.Rule = Symbol("+") | "-" | "*" | "%" | "^" | "&" | "|" | "/" | "&&" | "||" | "==" | "!=" | greater | less | ">=" | "<=" | "is" | "<>" | "=" //| "+=" | "-=" | "." | and | or; LUnOp.Rule = Symbol("-") | "!"; FunctionExpression.Rule = QualifiedName + LCb + ExprList.Q() + RCb; QualifiedName.Rule = identifier | QualifiedName + dot + identifier | parameterSectionStmt + "!" + identifier | "#" + identifier; Condition.Rule = LCb + Expr + RCb; Conditional.Rule = "if" + Condition + "then" + Expr | "if" + Condition + "then" + Expr + "else" + Expr | "if" + Condition + "then" + Expr + "otherwise" + Expr; BinExpr.Rule = Expr + BinOp + Expr | LUnOp + Expr; ProgramLine.Rule = Expr + NewLine; Program.Rule = MakeStarRule(Program, ProgramLine); this.Root = Program; // Set grammar root #region 5. Operators precedence RegisterOperators(1, "is", "=", "==", "!=", "<>", ">", "<", ">=", "<="); RegisterOperators(2, "+", "-"); RegisterOperators(3, "*", "/", "%"); RegisterOperators(4, Associativity.Right, "^"); RegisterOperators(5, "|", "||", "or"); RegisterOperators(6, "&", "&&", "and"); RegisterOperators(7, "!"); #endregion RegisterPunctuation("(", ")", "[", "]", "{", "}", ",", ";"); MarkTransient(Expr, BinOp); //automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source this.SetLanguageFlags(LanguageFlags.NewLineBeforeEOF | LanguageFlags.SupportsInterpreter | LanguageFlags.AutoDetectTransient | LanguageFlags.CreateAst); }
public LabGrammar() : base(false) { var numberLiteral = new NumberLiteral("number") { DefaultIntTypes = new TypeCode[1] { TypeCode.Double } }; var identifierTerminal = new IdentifierTerminal("identifier"); NonGrammarTerminals.Add(new CommentTerminal("comment", "#", "\n", "\r")); KeyTerm term = ToTerm(","); var stringLiteral = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLiteral.AddStartEnd("'", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLiteral.AstConfig.NodeType = typeof(StringTemplateNode); var nonTerminal1 = new NonTerminal("Expr"); var templateSettings = new StringTemplateSettings { ExpressionRoot = nonTerminal1 }; SnippetRoots.Add(nonTerminal1); stringLiteral.AstConfig.Data = templateSettings; var nonTerminal2 = new NonTerminal("Term"); var nonTerminal3 = new NonTerminal("BinExpr", typeof(BinaryOperationNode)); var nonTerminal4 = new NonTerminal("ParExpr"); var nonTerminal5 = new NonTerminal("UnExpr", typeof(UnaryOperationNode)); var nonTerminal6 = new NonTerminal("TernaryIf", typeof(IfNode)); var listNonTerminal1 = new NonTerminal("ArgList", typeof(ExpressionListNode)); var nonTerminal7 = new NonTerminal("FunctionCall", typeof(FunctionCallNode)); var nonTerminal8 = new NonTerminal("MemberAccess", typeof(MemberAccessNode)); var nonTerminal9 = new NonTerminal("IndexedAccess", typeof(IndexedAccessNode)); var nonTerminal10 = new NonTerminal("ObjectRef"); var nonTerminal11 = new NonTerminal("UnOp"); var nonTerminal12 = new NonTerminal("BinOp", "operator"); var nonTerminal13 = new NonTerminal("PrefixIncDec", typeof(IncDecNode)); var nonTerminal14 = new NonTerminal("PostfixIncDec", typeof(IncDecNode)); var nonTerminal15 = new NonTerminal("IncDecOp"); var nonTerminal16 = new NonTerminal("AssignmentStmt", typeof(AssignmentNode)); var nonTerminal17 = new NonTerminal("AssignmentOp", "assignment operator"); var nonTerminal18 = new NonTerminal("Statement"); var listNonTerminal2 = new NonTerminal("Program", typeof(StatementListNode)); nonTerminal1.Rule = nonTerminal2 | nonTerminal5 | nonTerminal3 | nonTerminal13 | nonTerminal14 | nonTerminal6; nonTerminal2.Rule = numberLiteral | nonTerminal4 | stringLiteral | nonTerminal7 | identifierTerminal | nonTerminal8 | nonTerminal9; nonTerminal4.Rule = "(" + nonTerminal1 + ")"; nonTerminal5.Rule = nonTerminal11 + nonTerminal2 + ReduceHere(); nonTerminal11.Rule = ToTerm("+") | "-" | "!"; nonTerminal3.Rule = nonTerminal1 + nonTerminal12 + nonTerminal1; nonTerminal12.Rule = ToTerm("+") | "-" | "*" | "/" | "**" | "==" | "<" | "<=" | ">" | ">=" | "!=" | "&&" | "||" | "&" | "|"; nonTerminal13.Rule = nonTerminal15 + identifierTerminal; nonTerminal14.Rule = identifierTerminal + PreferShiftHere() + nonTerminal15; nonTerminal15.Rule = ToTerm("++") | "--"; nonTerminal6.Rule = nonTerminal1 + "?" + nonTerminal1 + ":" + nonTerminal1; nonTerminal8.Rule = nonTerminal1 + PreferShiftHere() + "." + identifierTerminal; nonTerminal16.Rule = nonTerminal10 + nonTerminal17 + nonTerminal1; nonTerminal17.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/="; nonTerminal18.Rule = nonTerminal16 | nonTerminal1 | Empty; listNonTerminal1.Rule = MakeStarRule(listNonTerminal1, term, nonTerminal1); nonTerminal7.Rule = nonTerminal1 + PreferShiftHere() + "(" + listNonTerminal1 + ")"; nonTerminal7.NodeCaptionTemplate = "call #{0}(...)"; nonTerminal10.Rule = identifierTerminal | nonTerminal8 | nonTerminal9; nonTerminal9.Rule = nonTerminal1 + PreferShiftHere() + "[" + nonTerminal1 + "]"; listNonTerminal2.Rule = MakePlusRule(listNonTerminal2, NewLine, nonTerminal18); Root = listNonTerminal2; RegisterOperators(10, "?"); RegisterOperators(15, "&", "&&", "|", "||"); RegisterOperators(20, "==", "<", "<=", ">", ">=", "!="); RegisterOperators(30, "+", "-"); RegisterOperators(40, "*", "/"); RegisterOperators(50, Associativity.Right, "**"); RegisterOperators(60, "!"); MarkPunctuation("(", ")", "?", ":", "[", "]"); RegisterBracePair("(", ")"); RegisterBracePair("[", "]"); MarkTransient(nonTerminal2, nonTerminal1, nonTerminal18, nonTerminal12, nonTerminal11, nonTerminal15, nonTerminal17, nonTerminal4, nonTerminal10); MarkNotReported("++", "--"); AddToNoReportGroup("(", "++", "--"); AddToNoReportGroup(NewLine); AddOperatorReportGroup("operator"); AddTermsReportGroup("assignment operator", "=", "+=", "-=", "*=", "/="); LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt; }
IdentifierTerminal CreateIdentifier() { var identifier = new IdentifierTerminal("identifier"); var quotedIdentifier = new StringLiteral("identifier_quoted"); quotedIdentifier.AddStartEnd("`", StringOptions.NoEscapes); quotedIdentifier.SetOutputTerminal(this, identifier); return identifier; }
public ODataFilterGrammar() { //Terminals var simpleIdentifier = TerminalFactory.CreateCSharpIdentifier("Identifier"); var stringLiteral = new StringLiteral("StringLiteral", "'", StringOptions.NoEscapes | StringOptions.AllowsDoubledQuote); var numberLiteral = new NumberLiteral("NumberLiteral"); // This impl has problems with .NET 4.5 - so ToTerm methods below were used instead. //var constant = new ConstantTerminal("Constant", typeof(Object)); //constant.Add("true", true); //constant.Add("false", false); //constant.Add("null", null); var trueLiteral = ToTerm("true", "Constant"); var falseLiteral = ToTerm("false", "Constant"); var nullLiteral = ToTerm("null", "Constant"); var dateTimeOffsetLiteral = new StringLiteral("DateTimeOffsetLiteral"); dateTimeOffsetLiteral.AddStartEnd("datetimeoffset'","'", StringOptions.None); var dateTimeLiteral = new StringLiteral("DateTimeLiteral"); dateTimeLiteral.AddStartEnd("datetime'", "'", StringOptions.None); var timeLiteral = new StringLiteral("TimeLiteral"); timeLiteral.AddStartEnd("time'", "'", StringOptions.None); var guidLiteral = new StringLiteral("GuidLiteral"); guidLiteral.AddStartEnd("guid'", "'", StringOptions.None); //NonTerminals var baseExpr = new NonTerminal("BaseExpr"); var compositeIdentifier = new NonTerminal("CompositeIdentifier"); var parenExpr = new NonTerminal("ParenExpr"); var methodCallExpr = new NonTerminal("MethodCallExpr"); var literalExpr = new NonTerminal("LiteralExpr"); var subExpr= new NonTerminal("SubExpr"); var lambdaExpr = new NonTerminal("LambdaExpr"); var lambdaVariable = new NonTerminal("LambdaVariable"); var memberExpr = new NonTerminal("MemberExpr"); var binaryExpr = new NonTerminal("BinaryExpr"); var binaryExprOp = new NonTerminal("BinaryExprOp"); var unaryExpr = new NonTerminal("UnaryExpr"); var unaryExprOp = new NonTerminal("UnaryExprOp"); #region Methods // bool var anyMethodCallExpr = new NonTerminal("AnyMethodCallExpr"); var allMethodCallExpr = new NonTerminal("AllMethodCallExpr"); var substringOfMethodCallExpr = new NonTerminal("SubstringOfMethodCallExpr"); var endsWithMethodCallExpr = new NonTerminal("EndsWithMethodCallExpr"); var startsWithMethodCallExpr = new NonTerminal("StartsWithMethodCallExpr"); // int var lengthMethodCallExpr = new NonTerminal("LengthMethodCallExpr"); var indexOfMethodCallExpr = new NonTerminal("IndexOfMethodCallExpr"); // string var replaceMethodCallExpr = new NonTerminal("ReplaceMethodCallExpr"); var substring1MethodCallExpr = new NonTerminal("Substring1MethodCallExpr"); var substring2MethodCallExpr = new NonTerminal("Substring2MethodCallExpr"); var toLowerMethodCallExpr = new NonTerminal("ToLowerMethodCallExpr"); var toUpperMethodCallExpr = new NonTerminal("ToUpperMethodCallExpr"); var trimMethodCallExpr = new NonTerminal("TrimMethodCallExpr"); var concatMethodCallExpr = new NonTerminal("ConcatMethodCallExpr"); // date var secondMethodCallExpr = new NonTerminal("SecondMethodCallExpr"); var minuteMethodCallExpr = new NonTerminal("MinuteMethodCallExpr"); var hourMethodCallExpr = new NonTerminal("HourMethodCallExpr"); var dayMethodCallExpr = new NonTerminal("DayMethodCallExpr"); var monthMethodCallExpr = new NonTerminal("MonthMethodCallExpr"); var yearMethodCallExpr = new NonTerminal("YearMethodCallExpr"); // math var roundMethodCallExpr = new NonTerminal("RoundMethodCallExpr"); var floorMethodCallExpr = new NonTerminal("FloorMethodCallExpr"); var ceilingMethodCallExpr = new NonTerminal("CeilingMethodCallExpr"); // type var isOf1MethodCallExpr = new NonTerminal("isOf1MethodCallExpr"); var isOf2MethodCallExpr = new NonTerminal("isOf2MethodCallExpr"); #endregion Root = baseExpr; baseExpr.Rule = parenExpr | literalExpr | memberExpr | methodCallExpr | binaryExpr | unaryExpr; parenExpr.Rule = "(" + baseExpr + ")"; literalExpr.Rule = stringLiteral | numberLiteral // | constant | trueLiteral | falseLiteral | nullLiteral | dateTimeLiteral | dateTimeOffsetLiteral | timeLiteral | guidLiteral; subExpr.Rule = simpleIdentifier | anyMethodCallExpr | allMethodCallExpr; KeyTerm backSlash = ToTerm("/", "backslash"); compositeIdentifier.Rule = MakePlusRule(compositeIdentifier, backSlash, subExpr); memberExpr.Rule = compositeIdentifier; lambdaVariable.Rule = simpleIdentifier + ":"; lambdaExpr.Rule = lambdaVariable + baseExpr; unaryExpr.Rule = unaryExprOp + baseExpr; unaryExprOp.Rule = (BnfExpression) "not" | "-"; binaryExpr.Rule = baseExpr + binaryExprOp + baseExpr; binaryExprOp.Rule = (BnfExpression)"eq" | "ne" | "lt" | "le" | "gt" | "ge" | "add" | "sub" | "mul" | "div" | "mod" | "and" | "or"; methodCallExpr.Rule = anyMethodCallExpr | allMethodCallExpr | replaceMethodCallExpr | substring1MethodCallExpr | substring2MethodCallExpr | toLowerMethodCallExpr | toUpperMethodCallExpr | trimMethodCallExpr | concatMethodCallExpr | lengthMethodCallExpr | indexOfMethodCallExpr | secondMethodCallExpr | minuteMethodCallExpr | hourMethodCallExpr | dayMethodCallExpr | monthMethodCallExpr | yearMethodCallExpr | roundMethodCallExpr | floorMethodCallExpr | ceilingMethodCallExpr | isOf1MethodCallExpr | isOf2MethodCallExpr | substringOfMethodCallExpr | startsWithMethodCallExpr | endsWithMethodCallExpr; anyMethodCallExpr.Rule = (BnfExpression) "any" + "(" + lambdaExpr + ")"; allMethodCallExpr.Rule = (BnfExpression) "all" + "(" + lambdaExpr + ")"; replaceMethodCallExpr.Rule = (BnfExpression)"replace" + "(" + baseExpr + "," + baseExpr + "," + baseExpr + ")"; substring1MethodCallExpr.Rule = (BnfExpression)"substring" + "(" + baseExpr + "," + baseExpr + ")"; substring2MethodCallExpr.Rule = (BnfExpression)"substring" + "(" + baseExpr + "," + baseExpr + "," + baseExpr + ")"; toLowerMethodCallExpr.Rule = (BnfExpression)"tolower" + "(" + baseExpr + ")"; toUpperMethodCallExpr.Rule = (BnfExpression)"toupper" + "(" + baseExpr + ")"; trimMethodCallExpr.Rule = (BnfExpression)"trim" + "(" + baseExpr + ")"; concatMethodCallExpr.Rule = (BnfExpression)"concat" + "(" + baseExpr + "," + baseExpr + ")"; lengthMethodCallExpr.Rule = (BnfExpression)"length" + "(" + baseExpr + ")"; indexOfMethodCallExpr.Rule = (BnfExpression)"indexof" + "(" + baseExpr + "," + baseExpr + ")"; substringOfMethodCallExpr.Rule = (BnfExpression)"substringof" + "(" + baseExpr + "," + baseExpr + ")"; startsWithMethodCallExpr.Rule = (BnfExpression)"startswith" + "(" + baseExpr + "," + baseExpr + ")"; endsWithMethodCallExpr.Rule = (BnfExpression)"endswith" + "(" + baseExpr + "," + baseExpr + ")"; secondMethodCallExpr.Rule = (BnfExpression)"second" + "(" + baseExpr + ")"; minuteMethodCallExpr.Rule = (BnfExpression)"minute" + "(" + baseExpr + ")"; hourMethodCallExpr.Rule = (BnfExpression)"hour" + "(" + baseExpr + ")"; dayMethodCallExpr.Rule = (BnfExpression)"day" + "(" + baseExpr + ")"; monthMethodCallExpr.Rule = (BnfExpression)"month" + "(" + baseExpr + ")"; yearMethodCallExpr.Rule = (BnfExpression)"year" + "(" + baseExpr + ")"; roundMethodCallExpr.Rule = (BnfExpression)"round" + "(" + baseExpr + ")"; ceilingMethodCallExpr.Rule = (BnfExpression)"ceiling" + "(" + baseExpr + ")"; floorMethodCallExpr.Rule = (BnfExpression)"floor" + "(" + baseExpr + ")"; isOf1MethodCallExpr.Rule = (BnfExpression)"isof" + "(" + baseExpr + ")"; isOf2MethodCallExpr.Rule = (BnfExpression)"isof" + "(" + baseExpr + "," + baseExpr + ")"; RegisterOperators(10, "or"); RegisterOperators(20, "and"); RegisterOperators(30, "eq", "ne", "lt", "le", "gt", "ge"); RegisterOperators(40, "add", "sub", "mul", "div", "mod"); RegisterOperators(50, "-"); RegisterBracePair("(", ")"); MarkPunctuation(",", "(", ")" , "/", ":"); MarkTransient(baseExpr); MarkTransient(binaryExprOp); MarkTransient(unaryExprOp); MarkTransient(parenExpr); MarkTransient(methodCallExpr); MarkTransient(literalExpr); MarkTransient(subExpr); MarkTransient(lambdaVariable); }