public ConflictResolutionTestGrammar4() : base(true) { var name = new IdentifierTerminal("id"); var stmt = new NonTerminal("Statement"); var stmtList = new NonTerminal("StatementList"); var fieldModifier = new NonTerminal("fieldModifier"); var propModifier = new NonTerminal("propModifier"); var methodModifier = new NonTerminal("methodModifier"); var fieldModifierList = new NonTerminal("fieldModifierList"); var propModifierList = new NonTerminal("propModifierList"); var methodModifierList = new NonTerminal("methodModifierList"); var fieldDef = new NonTerminal("fieldDef"); var propDef = new NonTerminal("propDef"); var methodDef = new NonTerminal("methodDef"); //Rules this.Root = stmtList; stmtList.Rule = MakePlusRule(stmtList, stmt); stmt.Rule = fieldDef | propDef | methodDef; fieldDef.Rule = fieldModifierList + name + name + ";"; propDef.Rule = propModifierList + name + name + "{" + "}"; methodDef.Rule = methodModifierList + name + name + "(" + ")" + "{" + "}"; fieldModifierList.Rule = MakeStarRule(fieldModifierList, fieldModifier); propModifierList.Rule = MakeStarRule(propModifierList, propModifier); methodModifierList.Rule = MakeStarRule(methodModifierList, methodModifier); // That's the key of the problem: 3 modifiers have common members // so parser automaton has hard time deciding which modifiers list to produce - // is it a field, prop or method we are beginning to parse? fieldModifier.Rule = ToTerm("public") | "private" | "readonly" | "volatile"; propModifier.Rule = ToTerm("public") | "private" | "readonly" | "override"; methodModifier.Rule = ToTerm("public") | "private" | "override"; // conflict resolution fieldModifier.ReduceIf(thisSymbol: ";", comesBefore: new string[] { "(", "{"}); propModifier.ReduceIf(thisSymbol: "{", comesBefore: new string[] { ";", "(" }); fieldModifierList.ReduceIf(thisSymbol: ";", comesBefore: new string[] { "(", "{" }); propModifierList.ReduceIf(thisSymbol: "{", comesBefore: new string[] { ";", "(" }); MarkReservedWords("public", "private", "readonly", "volatile", "override"); }
public CicodeGrammar() : base(false) { var program = new NonTerminal("program"); var declaration = new NonTerminal("declaration"); var declarations = new NonTerminal("declarations"); var variableType = new NonTerminal("variable-type"); var parenParameters = new NonTerminal("paran-parameters"); var parameter = new NonTerminal("parameter"); var parameters = new NonTerminal("parameters"); var parameterInitializer = new NonTerminal("parameterInitializer"); var functionDeclaration = new NonTerminal("function-declaration"); var statements = new NonTerminal("statements"); var statement = new NonTerminal("statement"); var semiStatement = new NonTerminal("semi-statement"); var variableDeclaration = new NonTerminal("variable-declaration"); var block = new NonTerminal("block"); var variableInitializer = new NonTerminal("variableInitializer"); var variableInitializers = new NonTerminal("variableInitializers"); var blockContent = new NonTerminal("block-content"); var blockDeclarations = new NonTerminal("block-declarations"); var blockDeclaration = new NonTerminal("block-declaration"); var functionScope = new NonTerminal("function-scope"); var localVariableDeclaration = new NonTerminal("localVariableDeclaration"); var parameterType = new NonTerminal("parameterType"); var functionReturnType = new NonTerminal("function-returnType"); var returnStatement = new NonTerminal("return-statement"); var ifStatement = new NonTerminal("if-statement"); var optionalElseStatement = new NonTerminal("elseStatement"); var variableScope = new NonTerminal("variableScope"); var arrayIndexers = new NonTerminal("arrayIndexers"); var functionCall = new NonTerminal("functionCall"); var functionCallStatement = new NonTerminal("functionCallStatement"); var selectStatement = new NonTerminal("selectCaseStatement"); var caseStatement = new NonTerminal("caseStatement"); var caseStatements = new NonTerminal("caseStatements"); var caseExpression = new NonTerminal("caseExpression"); var caseExpressionList = new NonTerminal("caseExpressionList"); var caseElseStatement = new NonTerminal("caseElseStatement"); var whileDoStatement = new NonTerminal("whileDoStatement"); var forStatement = new NonTerminal("forStatement"); // Lexical Structure var stringLiteral = new StringLiteral("string", "\"", StringOptions.None); stringLiteral.EscapeChar = '^'; var numberLiteral = new NumberLiteral("number"); var identifier = TerminalFactory.CreateCSharpIdentifier("id"); var semi = ToTerm(";", "semi"); var colon = ToTerm(":", "colon"); var optionalSemi = new NonTerminal("semi?"); optionalSemi.Rule = Empty | semi; var dashLineComment = new CommentTerminal("comment", "//", "\n", "\r"); var bangLineComment = new CommentTerminal("comment", "!", "\n", "\r"); var blockComment = new CommentTerminal("BLOCK_COMMENT", "/*", "*/"); //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(dashLineComment); base.NonGrammarTerminals.Add(bangLineComment); base.NonGrammarTerminals.Add(blockComment); // Expressions var expression = new NonTerminal("expression"); var constantExpression = new NonTerminal("constantExpression"); var expressionList = new NonTerminal("expressionList"); var optionalExpression = new NonTerminal("optional-expression"); var literal = new NonTerminal("literal"); var term = new NonTerminal("term"); var arithmicExpression = new NonTerminal("arithmicExpression"); var parenthesizedExpression = new NonTerminal("ParExpr"); var unaryExpression = new NonTerminal("UnExpr"); var unaryOperator = new NonTerminal("UnOp"); var arithmicOperator = new NonTerminal("arithmicOperator", "operator"); var relationalOperator = new NonTerminal("relationalOperator", "operator"); var assignmentStatement = new NonTerminal("AssignmentStmt"); var assignmentOperator = new NonTerminal("assignmentOperator"); var variable = new NonTerminal("variable"); // 3. BNF rules expression.Rule = term | unaryExpression | arithmicExpression | functionCall; expressionList.Rule = expressionList + "," + expression | expression | Empty ; constantExpression.Rule = ToTerm("-") + numberLiteral | numberLiteral | stringLiteral ; optionalExpression.Rule = expression | Empty; term.Rule = literal | parenthesizedExpression | variable; parenthesizedExpression.Rule = "(" + expression + ")"; unaryExpression.Rule = unaryOperator + expression; unaryOperator.Rule = ToTerm("-") | "NOT"; arithmicExpression.Rule = expression + arithmicOperator + expression; relationalOperator.Rule = ToTerm(">") | "<" | ">=" | "<=" | "=" | "<>"; // strictly speaking not only arithmetic operators... should be refactored arithmicOperator.Rule = ToTerm("+") | "-" | "*" | "/" | "MOD" | "BITAND" | "BITOR" | "BITXOR" | relationalOperator | "AND" | "OR"; assignmentStatement.Rule = variable + assignmentOperator + expression + semi; assignmentOperator.Rule = ToTerm("="); // 4. Operators precedence RegisterOperators(2, "NOT"); RegisterOperators(3, "*", "/", "MOD"); //RegisterOperators(4, ":"); FOR FUTURE IMPL. What is this operator?? RegisterOperators(5, "+", "-"); RegisterOperators(6, ">", "<", "<=", ">="); RegisterOperators(7, "=", "<>"); RegisterOperators(8, "AND"); RegisterOperators(9, "OR"); RegisterOperators(10, "BITAND", "BITOR", "BITXOR"); // 5. Punctuation and transient terms MarkPunctuation("(", ")"); RegisterBracePair("(", ")"); MarkTransient(term, expression, arithmicOperator, unaryOperator, parenthesizedExpression); var arrayIdentifier = new NonTerminal("arrayIdentifier"); var arrayIndexer = new NonTerminal("arrayIndexer"); var arrayIndexDeclaration = new NonTerminal("arrayIndexDeclaration"); var arrayIndexDeclarations = new NonTerminal("arrayIndexDeclarations"); var arrayInitializers = new NonTerminal("arrayInitializers"); var arrayDeclaration = new NonTerminal("arrayDeclaration"); //////////////// literal.Rule = numberLiteral | stringLiteral; ifStatement.Rule = ToTerm("IF") + expression + ToTerm("THEN") + block + optionalElseStatement; optionalElseStatement.Rule = Empty | ToTerm("ELSE") + block; functionCall.Rule = identifier + "(" + expressionList + ")"; caseExpression.Rule = expression | expression + ToTerm("TO") + expression | ToTerm("IS") + relationalOperator + expression ; caseExpressionList.Rule = caseExpressionList + "," + caseExpression | caseExpression ; caseStatement.Rule = ToTerm("CASE") + caseExpressionList + statements ; caseElseStatement.Rule = ToTerm("CASE") + ToTerm("ELSE"); caseStatements.Rule = caseStatements + caseStatement | caseStatements + caseElseStatement | caseStatement; selectStatement.Rule = ToTerm("SELECT") + ToTerm("CASE") + expression + caseStatements + ToTerm("END") + ToTerm("SELECT"); whileDoStatement.Rule = ToTerm("WHILE") + expression + ToTerm("DO") + statements + ToTerm("END"); forStatement.Rule = ToTerm("FOR") + variable + ToTerm("=") + expression + ToTerm("TO") + expression + ToTerm("DO") + statements + ToTerm("END"); this.Root = program; program.Rule = declarations; declarations.Rule = MakeStarRule(declarations, declaration); variableInitializer.Rule = identifier + assignmentOperator + constantExpression; variableInitializers.Rule = variableInitializers + "," + variableInitializer | variableInitializer ; localVariableDeclaration.Rule = variableType + variableInitializers + ";" | variableType + identifier + ";" ; variableDeclaration.Rule = variableScope + variableType + variableInitializers + ";" | variableScope + variableType + identifier + ";" | arrayDeclaration + ";" ; arrayInitializers.Rule = arrayInitializers + "," + constantExpression | constantExpression ; arrayDeclaration.Rule = variableScope + variableType + identifier + arrayIndexDeclarations | variableScope + variableType + identifier + arrayIndexDeclarations + assignmentOperator + arrayInitializers; arrayIndexDeclarations.Rule = arrayIndexDeclarations + arrayIndexDeclaration | arrayIndexDeclaration ; arrayIndexers.Rule = arrayIndexers + arrayIndexer | arrayIndexer ; arrayIdentifier.Rule = identifier + arrayIndexers; arrayIndexer.Rule = "[" + expression + "]"; arrayIndexDeclaration.Rule = "[" + numberLiteral + "]"; variable.Rule = identifier | identifier + arrayIndexers ; variableType.Rule = ToTerm("INT") | ToTerm("STRING") | ToTerm("REAL") | ToTerm("OBJECT") | ToTerm("QUALITY") | ToTerm("TIMESTAMP") ; variableScope.Rule = Empty | ToTerm("GLOBAL") | ToTerm("MODULE") ; parameterInitializer.Rule = Empty | assignmentOperator + constantExpression; parameter.Rule = variableType + identifier + parameterInitializer; parameters.Rule = parameters + "," + parameter | parameter; parenParameters.Rule = ToTerm("(") + ")" | "(" + parameters + ")"; statements.Rule = MakeStarRule(statements, statement); statement.Rule = semiStatement | ifStatement | selectStatement | whileDoStatement | forStatement ; functionCallStatement.Rule = functionCall + semi; returnStatement.Rule = ToTerm("RETURN") + optionalExpression + semi; semiStatement.Rule = assignmentStatement | returnStatement | functionCallStatement ; block.Rule = blockContent + "END"; blockContent.Rule = blockDeclarations + statements ; blockDeclarations.Rule = MakeStarRule(blockDeclarations, blockDeclaration); blockDeclaration.Rule = localVariableDeclaration; functionScope.Rule = ToTerm("PUBLIC") | "PRIVATE" | Empty; // These reduce hints are needed to help determine the difference between // a function declaration and a variable declaration. functionScope.ReduceIf("FUNCTION"); variableScope.ReduceIf(semi); functionReturnType.Rule = variableType | Empty; declaration.Rule = functionDeclaration | variableDeclaration ; functionDeclaration.Rule = functionScope + functionReturnType + "FUNCTION" + identifier + parenParameters + block; MarkTransient(semiStatement, blockDeclaration); }