// It is loosely based on R6RS specs.  
    // See Grammar Errors tab in GrammarExplorer for remaining conflicts.
    public SchemeGrammar() {

      #region Terminals
      ConstantTerminal Constant = new ConstantTerminal("Constant");
      Constant.Add("#T", 1);
      Constant.Add("#t", 1);
      Constant.Add("#F", null);
      Constant.Add("#f", null);
      Constant.Add("'()", null);
      Constant.Add(@"#\nul", '\u0000');
      Constant.Add(@"#\alarm", '\u0007');
      Constant.Add(@"#\backspace", '\b');
      Constant.Add(@"#\tab", '\t');
      Constant.Add(@"#\linefeed", '\n');
      Constant.Add(@"#\vtab", '\v');
      Constant.Add(@"#\page", '\f');
      Constant.Add(@"#\return", '\r');
      Constant.Add(@"#\esc", '\u001B');
      Constant.Add(@"#\space", ' ');
      Constant.Add(@"#\delete", '\u007F');

      // TODO: build SchemeCharLiteral
      // the following is nonsense, just to put something there
      var charLiteral = new StringLiteral("Char", "'", StringOptions.None); 
      var stringLiteral = new StringLiteral("String", "\"", StringOptions.AllowsAllEscapes);
      //Identifiers. Note: added "-", just to allow IDs starting with "->" 
      var SimpleIdentifier = new IdentifierTerminal("SimpleIdentifier", "_+-*/.@?!<>=", "_+-*/.@?!<>=$%&:^~");
      //                                                           name                extraChars      extraFirstChars  
      var Number = TerminalFactory.CreateSchemeNumber("Number");
      var Byte = new NumberLiteral("Byte", NumberOptions.IntOnly); 

      //Comments
      Terminal Comment = new CommentTerminal("Comment", "#|", "|#");
      Terminal LineComment = new CommentTerminal("LineComment", ";", "\n");
      NonGrammarTerminals.Add(Comment); //add comments explicitly to this list as it is not reachable from Root
      NonGrammarTerminals.Add(LineComment);
      #endregion

      #region NonTerminals
      var Module = new NonTerminal("Module");
      var Library = new NonTerminal("Library");
      var LibraryList = new NonTerminal("Library+");
      var Script = new NonTerminal("Script");

      var Abbreviation = new NonTerminal("Abbreviation");
      var Vector = new NonTerminal("Vector");
      var ByteList = new NonTerminal("ByteList");
      var ByteVector = new NonTerminal("ByteVector");
      var Datum = new NonTerminal("Datum"); //Datum in R6RS terms
      var DatumOpt = new NonTerminal("DatumOpt"); //Datum in R6RS terms
      var DatumList = new NonTerminal("Datum+");
      var DatumListOpt = new NonTerminal("Datum*");
      var Statement = new NonTerminal("Statement");
      var Atom = new NonTerminal("Atom");
      var CompoundDatum = new NonTerminal("CompoundDatum");
      var AbbrevPrefix = new NonTerminal("AbbrevPrefix");

      var LibraryName = new NonTerminal("LibraryName");
      var LibraryBody = new NonTerminal("LibraryBody");
      var ImportSection = new NonTerminal("ImportSection");
      var ExportSection = new NonTerminal("ExportSection");
      var ImportSpec = new NonTerminal("ImportSpec");
      var ImportSpecList = new NonTerminal("ImportSpecList");
      var ExportSpec = new NonTerminal("ExportSpec");
      var ExportSpecList = new NonTerminal("ExportSpecList");
      var LP = new NonTerminal("LP"); //"(" or "["
      var RP = new NonTerminal("RP"); // ")" or "]"
      var Identifier = new NonTerminal("Identifier");
      var IdentifierList = new NonTerminal("IdentifierList");
      var IdentifierListOpt = new NonTerminal("IdentifierListOpt");
      var PeculiarIdentifier = new NonTerminal("PeculiarIdentifier");
      var LibraryVersion = new NonTerminal("LibraryVersion");
      var VersionListOpt = new NonTerminal("VersionListOpt");

      var FunctionCall = new NonTerminal("FunctionCall");
      var FunctionRef = new NonTerminal("FunctionRef");
      var SpecialForm = new NonTerminal("SpecialForm");
      var DefineVarForm = new NonTerminal("DefineVarForm");
      var DefineFunForm = new NonTerminal("DefineFunForm");
      var LambdaForm = new NonTerminal("LambdaForm");
      var IfForm = new NonTerminal("IfForm");
      var CondForm = new NonTerminal("CondForm");
      var CondClause = new NonTerminal("CondClause");
      var CondClauseList = new NonTerminal("CondClauseList");
      var CondElseOpt = new NonTerminal("CondElseOpt");
      var BeginForm = new NonTerminal("BeginForm");
      var LetForm = new NonTerminal("LetForm"); //not implemented
      var LetRecForm = new NonTerminal("LetRecForm"); //not implemented
      var LetPair = new NonTerminal("LetPair");
      var LetPairList = new NonTerminal("LetPairList");
      #endregion

      #region Rules
      base.Root = Module; 

      LP.Rule = ToTerm("(") | "[";  //R6RS allows mix & match () and []
      RP.Rule = ToTerm(")") | "]";

      // Module.Rule = LibraryListOpt + Script; -- this brings conflicts
      Module.Rule = LibraryList + Script | Script;
      LibraryList.Rule = MakePlusRule(LibraryList, Library);
      Script.Rule = ImportSection + DatumList | DatumList; 

      //Library
      // the following doesn't work - brings conflicts that incorrectly resolved by default shifting
      //Library.Rule = LP + "library" + LibraryName + ExportSectionOpt + ImportSectionOpt + DatumListOpt + RP;
      Library.Rule = LP + "library" + LibraryName + LibraryBody + RP;
      //Note - we should be using DatumListOpt, but that brings 2 conflicts, so for now it is just DatumList
      //Note that the following style of BNF expressions is strongly discouraged - all productions should be of the same length, 
      // so that the process of mapping child nodes to parent's properties is straightforward.
      LibraryBody.Rule = ExportSection + ImportSection + DatumList
                       | ExportSection + DatumList
                       | ImportSection + DatumList
                       | DatumList; 
      LibraryName.Rule = LP + IdentifierList + LibraryVersion.Q() + RP;
      LibraryVersion.Rule = LP + VersionListOpt + RP; //zero or more subversion numbers
      VersionListOpt.Rule = MakeStarRule(VersionListOpt, Number);
      ExportSection.Rule = LP + "export" + ExportSpecList + RP;
      ImportSection.Rule = LP + "import" + ImportSpecList + RP;
      ExportSpecList.Rule = MakePlusRule(ExportSpecList, ExportSpec);
      ImportSpecList.Rule = MakePlusRule(ImportSpecList, ImportSpec);
      ExportSpec.Rule = Identifier | LP + "rename"  +  LP + Identifier + Identifier + RP + RP;
      ImportSpec.Rule = LP + Identifier + RP;   // - much more complex in R6RS

      //Datum
      Datum.Rule = Atom | CompoundDatum;
      DatumOpt.Rule = Empty | Datum;
      DatumList.Rule = MakePlusRule(DatumList, Datum);
      DatumListOpt.Rule = MakeStarRule(DatumListOpt, Datum);
      Atom.Rule = Number | Identifier | stringLiteral | Constant | charLiteral | ".";
      CompoundDatum.Rule = Statement | Abbreviation | Vector | ByteVector;
      Identifier.Rule = SimpleIdentifier | PeculiarIdentifier;
      IdentifierList.Rule = MakePlusRule(IdentifierList, Identifier);
      IdentifierListOpt.Rule = MakeStarRule(IdentifierListOpt, Identifier);

      //TODO: create PeculiarIdentifier custom terminal instead of var 
      // or just custom SchemeIdentifier terminal
      PeculiarIdentifier.Rule = ToTerm("+") | "-" | "..."; // |"->" + subsequent; (should be!) 
      Abbreviation.Rule = AbbrevPrefix + Datum;
      AbbrevPrefix.Rule = ToTerm("'") | "`" | ",@" | "," | "#'" | "#`" | "#,@" | "#,";
      Vector.Rule = "#(" + DatumListOpt + ")";
      ByteVector.Rule = "#vu8(" + ByteList + ")";
      ByteList.Rule = MakeStarRule(ByteList, Byte);

      Statement.Rule = FunctionCall | SpecialForm;

      FunctionCall.Rule = LP + FunctionRef + DatumListOpt + RP;
      FunctionRef.Rule = Identifier | Statement;

      SpecialForm.Rule = DefineVarForm | DefineFunForm | LambdaForm | IfForm | CondForm | BeginForm | LetForm | LetRecForm;
      DefineVarForm.Rule = LP + "define" + Identifier + Datum + RP;
      DefineFunForm.Rule = LP + "define" + LP + Identifier + IdentifierListOpt + RP + DatumList + RP;
      LambdaForm.Rule = LP + "lambda" + LP + IdentifierListOpt + RP + DatumList + RP;
      IfForm.Rule = LP + "if" + Datum + Datum + DatumOpt + RP;

      CondForm.Rule = LP + "cond" + CondClauseList + CondElseOpt + RP;
      CondClauseList.Rule = MakePlusRule(CondClauseList, CondClause);
      CondClause.Rule = LP + Datum + DatumList + RP;
      CondElseOpt.Rule = Empty | LP + "else" + DatumList + RP;
      LetForm.Rule = LP + "let" + LP + LetPairList + RP + DatumList + RP;
      LetRecForm.Rule = LP + "letrec" + LP + LetPairList + RP + DatumList + RP;
      BeginForm.Rule = LP + "begin" + DatumList + RP;
      LetPairList.Rule = MakePlusRule(LetPairList, LetPair);
      LetPair.Rule = LP + Identifier + Datum + RP;
      #endregion 

      //Register brace  pairs
      RegisterBracePair("(", ")"); 
      RegisterBracePair("[", "]");

      MarkPunctuation(LP, RP);
      MarkTransient(Datum, CompoundDatum, Statement, SpecialForm, Atom); 

      //Scheme is tail-recursive language
      base.LanguageFlags |= LanguageFlags.TailRecursive; 

    }//constructor
Exemple #2
0
        public SeeNoSQLGrammar()
            : base(false)
        {
            //Terminals
            var lineComment = new CommentTerminal("LINE_COMMENT", "//", "\n", "\r\n");
            var blockComment = new CommentTerminal("BLOCK_COMMENT", "/*", "*/");
            NonGrammarTerminals.Add(lineComment);
            NonGrammarTerminals.Add(blockComment);

            var number = new NumberLiteral("number");
            var intVal = new NumberLiteral("integer", NumberOptions.IntOnly);
            var stringLiteral = new StringLiteral("string", "'", StringOptions.AllowsDoubledQuote);
            var id = new IdentifierTerminal("id") {Priority = Terminal.HighestPriority};
            var param = new IdentifierTerminal("param");
            param.AddPrefix("@",IdOptions.None);
            param.Priority = Terminal.LowestPriority;
            var constantTerminal = new ConstantTerminal("constantTerminal");
            constantTerminal.Add("true", true);
            constantTerminal.Add("false", false);
            constantTerminal.Add("null", null);
            constantTerminal.Add("MAX_STRING", new object());
            constantTerminal.Add("MIN_STRING", null);
            constantTerminal.Priority = Terminal.HighestPriority;

            var ALL = ToTerm("ALL");
            var ALLOW_STALE = ToTerm("ALLOW_STALE");
            var AND = ToTerm("AND");
            var BETWEEN = ToTerm("BETWEEN");
            var COMMA = ToTerm(",");
            var DESCENDING = ToTerm("DESCENDING");
            var DOCUMENT = ToTerm("DOCUMENT");
            var FALSE = ToTerm("false");
            var FROM = ToTerm("FROM");
            var GROUP = ToTerm("GROUP");
            var GROUP_LEVEL = ToTerm("GROUP_LEVEL");
            var IN = ToTerm("IN");
            var INCLUDE_DOCS = ToTerm("INCLUDE_DOCS");
            var INCLUSIVE_END = ToTerm("INCLUSIVE_END");
            var KEY = ToTerm("KEY");
            var LIMIT = ToTerm("LIMIT");
            var OR = ToTerm("OR");
            var QUERYOPTIONS = ToTerm("QUERYOPTIONS");
            var REDUCE = ToTerm("REDUCE");
            var SKIP = ToTerm("SKIP");
            var TRUE = ToTerm("true");
            var UNION = ToTerm("UNION");
            var USING = ToTerm("USING");
            var VIEW = ToTerm("VIEW");
            var WHERE = ToTerm("WHERE");
            var WITH = ToTerm("WITH");

            //Non-terminals
            var betweenStatement = new NonTerminal("between");
            var binExpr = new NonTerminal("binExpr");
            var binOp = new NonTerminal("binOp");
            var constOperand = new NonTerminal("constOperand");
            var documentStatement = new NonTerminal("documentStatement");
            var expression = new NonTerminal("expression");
            var fromStatement = new NonTerminal("from");
            var keyArrayStatement = new NonTerminal("keyArray");
            var keyList = new NonTerminal("keys");
            var keyObjectStatement = new NonTerminal("keyObject");
            var keyValueStatement = new NonTerminal("keyValue");
            var keyStatement = new NonTerminal("key");
            var query = new NonTerminal("query");
            var queryOption = new NonTerminal("queryOption");
            var queryOptionList = new NonTerminal("queryOptionList");
            var queryOptions = new NonTerminal("queryOptions");
            var stmt = new NonTerminal("stmt");
            var unionStatement = new NonTerminal("unionStatement");
            var term = new NonTerminal("term");
            var view = new NonTerminal("view");
            var whereStatement = new NonTerminal("where");


            //Rules
            this.Root = query;
            query.Rule = MakePlusRule(query, unionStatement, stmt);
            stmt.Rule = fromStatement + queryOptions + keyStatement + whereStatement | fromStatement + queryOptions;
            unionStatement.Rule = UNION + ALL;

            term.Rule = id | stringLiteral | number | param | constOperand;
            binOp.Rule = ToTerm("=") | ">" | "<" | ">=" | "<=" | AND | OR | IN | BETWEEN;
            binExpr.Rule = expression + binOp + expression;
            expression.Rule = term | binExpr | betweenStatement | "(" + expression + ")";

            constOperand.Rule = constantTerminal;
            view.Rule = VIEW + "(" + id + COMMA + id + ")";
            queryOptions.Rule = Empty | USING + QUERYOPTIONS + "(" + queryOptionList + ")";
            queryOption.Rule = ALLOW_STALE + binOp + constOperand | DESCENDING + binOp + constOperand | GROUP + binOp + constOperand |
                               GROUP_LEVEL + binOp + intVal | INCLUDE_DOCS + binOp + constOperand | INCLUSIVE_END + binOp + constOperand |
                               LIMIT + binOp + intVal | REDUCE + binOp + constOperand | SKIP + binOp + intVal;
            queryOptionList.Rule = MakePlusRule(queryOptionList, COMMA, queryOption);
            fromStatement.Rule = FROM + view | FROM + documentStatement;
            documentStatement.Rule = DOCUMENT + "(" + term + ")";

            keyStatement.Rule = keyArrayStatement | keyObjectStatement | keyValueStatement;
            keyArrayStatement.Rule = WITH + KEY + "[" + keyList + "]";
            keyObjectStatement.Rule = WITH + KEY + "{" + keyList + "}";
            keyValueStatement.Rule = WITH + KEY + id;
            keyList.Rule = MakePlusRule(keyList, COMMA, id);

            whereStatement.Rule = Empty | WHERE + expression;
            betweenStatement.Rule = "(" + term + COMMA + term + ")";
            
            //Operators
            RegisterOperators(10, "=", "<", ">", "<=", ">=", "BETWEEN");
            RegisterOperators(9, "AND");
            RegisterOperators(8, "OR");
            RegisterOperators(7, "IN");
            MarkPunctuation("[", "]", "(", ")", "{", "}", ",");
            MarkTransient(term,expression, binOp, constOperand, keyStatement);
        }
		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);
		}
    /// <summary>
    /// Initializes a new instance of the <see cref="QueryGrammar"/> class.
    /// </summary>
    public QueryGrammar()
      : base(false) { // true means case sensitive
      GrammarComments = @"A Query Language based on JET where clauses. Case-insensitive.";

      // Terminals (Lexing)
      NumberLiteral number = new NumberLiteral("number");
      StringLiteral STRING = new StringLiteral("STRING", "\"");

      //Let's allow big integers (with unlimited number of digits):
      number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt };
      IdentifierTerminal Name = new IdentifierTerminal("Name");
      //var Name = TerminalFactory.CreateSqlExtIdentifier(this, "id_simple");
      CommentTerminal 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. 
      NonGrammarTerminals.Add(comment);
      comment = new CommentTerminal("multilineComment", "/*", "*/");
      NonGrammarTerminals.Add(comment);

      ConstantTerminal CONSTANT = new ConstantTerminal("CONSTANT");
      CONSTANT.Add("NULL", null);


      // Non-Terminals (Parsing)
      NonTerminal query = new NonTerminal("Query");
      NonTerminal tableExpression = new NonTerminal("TableExpression");
      NonTerminal tableExpressions = new NonTerminal("TableExpressions");
      NonTerminal table = new NonTerminal("Table");
      NonTerminal column = new NonTerminal("Column");
      NonTerminal tableOperator = new NonTerminal("TableOperator");
      NonTerminal value = new NonTerminal("Value");
      NonTerminal logicOp = new NonTerminal("LogicOp");
      NonTerminal parameter = new NonTerminal("Parameter");
      NonTerminal list = new NonTerminal("List");
      NonTerminal enclosure = new NonTerminal("Enclosure");
      NonTerminal closure = new NonTerminal("Closure");
      NonTerminal logicExpression = new NonTerminal("logicExpression");
      NonTerminal queryExpression = new NonTerminal("queryExpression");
      NonTerminal betweenStmt = new NonTerminal("BetweenStmt");
      NonTerminal expList = new NonTerminal("ExpList");

      //keywords
      KeyTerm AND = ToTerm("AND");
      KeyTerm OR = ToTerm("OR");
      KeyTerm IN = ToTerm("IN");
      KeyTerm BETWEEN = ToTerm("BETWEEN");
      KeyTerm LIKE = ToTerm("LIKE");
      KeyTerm NOT = ToTerm("NOT");
      KeyTerm dot = ToTerm(".", "dot");
      KeyTerm comma = ToTerm(",", "comma");
      KeyTerm LeftSquareBrace = ToTerm("[", "LeftSquareBrace");
      KeyTerm RightSquareBrace = ToTerm("]", "RightSquareBrace");
      KeyTerm LeftCurlyBrace = ToTerm("{", "LeftSCurlyBrace");
      KeyTerm RightCurlyBrace = ToTerm("}", "RightCurlyBrace");
      KeyTerm LeftQuote = ToTerm("\"", "LeftQuote");
      KeyTerm RightQuote = ToTerm("\"", "RightQuote");

      //set precedence of operators.
      RegisterOperators(90, AND);
      RegisterOperators(80, OR);
      RegisterOperators(70, "=", ">", "<", "<>", ">=", "<=", "IN", "LIKE", "NOT LIKE", "IS", "IS NOT", "BETWEEN");

      MarkPunctuation(",", "(", ")", "[", "]", ".", "\"", "{", "}");

      logicExpression.Rule = tableExpression + logicOp + tableExpression | "(" + logicExpression + ")";
      //queryExpression.Rule = MakePlusRule(queryExpression,logicOp,logicExpression);
      tableExpression.Rule = table + dot + column + tableOperator + value;
      tableExpression.ErrorRule = SyntaxError + ";";
      betweenStmt.Rule = BETWEEN + value + "AND";
      tableOperator.Rule = ToTerm("=") | ">" | "<" | "<>" | ">=" | "<=" | "LIKE" | "IN" | "NOT LIKE" | "IS" | "IS NOT" | betweenStmt;
      value.Rule = number | parameter | STRING | CONSTANT | expList;
      enclosure.Rule = ToTerm("(") | Empty;
      closure.Rule = ToTerm(")") | Empty;
      parameter.Rule = LeftQuote + "{" + Name + "}" + "\"" | "{" + Name + "}" | "#" + "{" + Name + "}" + "#";
      logicOp.Rule = AND | OR;
      expList.Rule = "(" + list + ")";
      list.Rule = MakePlusRule(list, comma, value);
      table.Rule = LeftSquareBrace + Name + RightSquareBrace;
      table.ErrorRule = SyntaxError + ";";
      column.Rule = LeftSquareBrace + Name + RightSquareBrace;
      column.ErrorRule = SyntaxError + ";";
      query.Rule = MakePlusRule(query, logicOp, logicExpression);

      Root = query;
    }
Exemple #5
0
        // It is loosely based on R6RS specs.
        // See Grammar Errors tab in GrammarExplorer for remaining conflicts.
        public SchemeGrammar()
        {
            #region Terminals
              ConstantTerminal Constant = new ConstantTerminal("Constant");
              Constant.Add("#T", 1);
              Constant.Add("#t", 1);
              Constant.Add("#F", null);
              Constant.Add("#f", null);
              Constant.Add("'()", null);
              Constant.Add(@"#\nul", '\u0000');
              Constant.Add(@"#\alarm", '\u0007');
              Constant.Add(@"#\backspace", '\b');
              Constant.Add(@"#\tab", '\t');
              Constant.Add(@"#\linefeed", '\n');
              Constant.Add(@"#\vtab", '\v');
              Constant.Add(@"#\page", '\f');
              Constant.Add(@"#\return", '\r');
              Constant.Add(@"#\esc", '\u001B');
              Constant.Add(@"#\space", ' ');
              Constant.Add(@"#\delete", '\u007F');

              // TODO: build SchemeCharLiteral
              // the following is nonsense, just to put something there
              var charLiteral = new StringLiteral("Char", "'", StringFlags.None);
              var stringLiteral = new StringLiteral("String", "\"", StringFlags.AllowsAllEscapes);
              //Identifiers. Note: added "-", just to allow IDs starting with "->"
              var SimpleIdentifier = new IdentifierTerminal("SimpleIdentifier", "_+-*/.@?!<>=", "_+-*/.@?!<>=$%&:^~");
              //                                                           name                extraChars      extraFirstChars
              var Number = TerminalFactory.CreateSchemeNumber("Number");
              var Byte = new NumberLiteral("Byte", NumberFlags.IntOnly);

              //Comments
              Terminal Comment = new CommentTerminal("Comment", "#|", "|#");
              Terminal LineComment = new CommentTerminal("LineComment", ";", "\n");
              NonGrammarTerminals.Add(Comment); //add comments explicitly to this list as it is not reachable from Root
              NonGrammarTerminals.Add(LineComment);
              #endregion

              #region NonTerminals
              var Module = new NonTerminal("Module");
              var Library = new NonTerminal("Library");
              var LibraryList = new NonTerminal("Library+");
              var Script = new NonTerminal("Script");

              var Abbreviation = new NonTerminal("Abbreviation");
              var Vector = new NonTerminal("Vector");
              var ByteList = new NonTerminal("ByteList");
              var ByteVector = new NonTerminal("ByteVector");
              var Datum = new NonTerminal("Datum"); //Datum in R6RS terms
              var DatumOpt = new NonTerminal("DatumOpt"); //Datum in R6RS terms
              var DatumList = new NonTerminal("Datum+", typeof(StatementListNode));
              var DatumListOpt = new NonTerminal("Datum*", typeof(StatementListNode));
              var Statement = new NonTerminal("Statement");
              var Atom = new NonTerminal("Atom");
              var CompoundDatum = new NonTerminal("CompoundDatum");
              var AbbrevPrefix = new NonTerminal("AbbrevPrefix");

              var LibraryName = new NonTerminal("LibraryName");
              var LibraryBody = new NonTerminal("LibraryBody");
              var ImportSection = new NonTerminal("ImportSection");
              var ExportSection = new NonTerminal("ExportSection");
              var ImportSpec = new NonTerminal("ImportSpec");
              var ImportSpecList = new NonTerminal("ImportSpecList");
              var ExportSpec = new NonTerminal("ExportSpec");
              var ExportSpecList = new NonTerminal("ExportSpecList");
              var LP = new NonTerminal("LP"); //"(" or "["
              var RP = new NonTerminal("RP"); // ")" or "]"
              var Identifier = new NonTerminal("Identifier", typeof(VarRefNode));
              var IdentifierList = new NonTerminal("IdentifierList");
              var IdentifierListOpt = new NonTerminal("IdentifierListOpt");
              var PeculiarIdentifier = new NonTerminal("PeculiarIdentifier");
              var LibraryVersion = new NonTerminal("LibraryVersion");
              var VersionListOpt = new NonTerminal("VersionListOpt");

              var FunctionCall = new NonTerminal("FunctionCall", CreateFunctionCallNode);
              var FunctionRef = new NonTerminal("FunctionRef");
              var SpecialForm = new NonTerminal("SpecialForm");
              var DefineVarForm = new NonTerminal("DefineVarForm", CreateDefineVarNode);
              var DefineFunForm = new NonTerminal("DefineFunForm", CreateDefineFunNode);
              var LambdaForm = new NonTerminal("LambdaForm", CreateLambdaNode);
              var IfForm = new NonTerminal("IfForm", CreateIfThenElseNode);
              var CondForm = new NonTerminal("CondForm", CreateCondFormNode);
              var CondClause = new NonTerminal("CondClause", CreateCondClauseNode);
              var CondClauseList = new NonTerminal("CondClauseList");
              var CondElseOpt = new NonTerminal("CondElseOpt");
              var BeginForm = new NonTerminal("BeginForm", CreateBeginNode);
              var LetForm = new NonTerminal("LetForm"); //not implemented
              var LetRecForm = new NonTerminal("LetRecForm"); //not implemented
              var LetPair = new NonTerminal("LetPair");
              var LetPairList = new NonTerminal("LetPairList");
              #endregion

              #region Rules
              //
              // Using optional elements in Scheme grammar brings some nasty conflicts - by default the parser selects "shift" over reduce
              // which leads to failure to parse simple programs without libraries and export/import sections.
              // This trouble comes from that the fact that Scheme has soooooo many parenthesis. Therefore, using a single next symbol
              // as a lookahead (as it happens in LALR parsing) doesn't help much - the next symbol is almost always a parenthesis,
              // not some meaningful symbol. That's why in the following expressions I had to use explicit listing of variants,
              // instead of simply marking some elements as optional (see Module, Script, LibraryBody elements) - this clears the conflicts
              // but would make node construction more difficult.
              base.Root = Module;

              LP.Rule = Symbol("(") | "[";  //R6RS allows mix & match () and []
              RP.Rule = Symbol(")") | "]";

              // Module.Rule = LibraryListOpt + Script; -- this brings conflicts
              Module.Rule = LibraryList + Script | Script;
              LibraryList.Rule = MakePlusRule(LibraryList, Library);
              Script.Rule = ImportSection + DatumList | DatumList;

              //Library
              // the following doesn't work - brings conflicts that incorrectly resolved by default shifting
              //Library.Rule = LP + "library" + LibraryName + ExportSectionOpt + ImportSectionOpt + DatumListOpt + RP;
              Library.Rule = LP + "library" + LibraryName + LibraryBody + RP;
              //Note - we should be using DatumListOpt, but that brings 2 conflicts, so for now it is just DatumList
              //Note that the following style of BNF expressions is strongly discouraged - all productions should be of the same length,
              // so that the process of mapping child nodes to parent's properties is straightforward.
              LibraryBody.Rule = ExportSection + ImportSection + DatumList
                       | ExportSection + DatumList
                       | ImportSection + DatumList
                       | DatumList;
              LibraryName.Rule = LP + IdentifierList + LibraryVersion.Q() + RP;
              LibraryVersion.Rule = LP + VersionListOpt + RP; //zero or more subversion numbers
              VersionListOpt.Rule = MakeStarRule(VersionListOpt, Number);
              ExportSection.Rule = LP + "export" + ExportSpecList + RP;
              ImportSection.Rule = LP + "import" + ImportSpecList + RP;
              ExportSpecList.Rule = MakePlusRule(ExportSpecList, ExportSpec);
              ImportSpecList.Rule = MakePlusRule(ImportSpecList, ImportSpec);
              ExportSpec.Rule = Identifier | LP + "rename"  +  LP + Identifier + Identifier + RP + RP;
              ImportSpec.Rule = LP + Identifier + RP;   // - much more complex in R6RS

              //Datum
              Datum.Rule = Atom | CompoundDatum;
              DatumOpt.Rule = Empty | Datum;
              DatumList.Rule = MakePlusRule(DatumList, Datum);
              DatumListOpt.Rule = MakeStarRule(DatumListOpt, Datum);
              Atom.Rule = Number | Identifier | stringLiteral | Constant | charLiteral | ".";
              CompoundDatum.Rule = Statement | Abbreviation | Vector | ByteVector;
              Identifier.Rule = SimpleIdentifier | PeculiarIdentifier;
              IdentifierList.Rule = MakePlusRule(IdentifierList, Identifier);
              IdentifierListOpt.Rule = MakeStarRule(IdentifierListOpt, Identifier);

              //TODO: create PeculiarIdentifier custom terminal instead of var
              // or just custom SchemeIdentifier terminal
              PeculiarIdentifier.Rule = Symbol("+") | "-" | "..."; // |"->" + subsequent; (should be!)
              Abbreviation.Rule = AbbrevPrefix + Datum;
              AbbrevPrefix.Rule = Symbol("'") | "`" | ",@" | "," | "#'" | "#`" | "#,@" | "#,";
              Vector.Rule = "#(" + DatumListOpt + ")";
              ByteVector.Rule = "#vu8(" + ByteList + ")";
              ByteList.Rule = MakeStarRule(ByteList, Byte);

              Statement.Rule = FunctionCall | SpecialForm;

              FunctionCall.Rule = LP + FunctionRef + DatumListOpt + RP;
              FunctionRef.Rule = Identifier | Statement;

              SpecialForm.Rule = DefineVarForm | DefineFunForm | LambdaForm | IfForm | CondForm | BeginForm | LetForm | LetRecForm;
              DefineVarForm.Rule = LP + "define" + Identifier + Datum + RP;
              DefineFunForm.Rule = LP + "define" + LP + Identifier + IdentifierListOpt + RP + DatumList + RP;
              LambdaForm.Rule = LP + "lambda" + LP + IdentifierListOpt + RP + DatumList + RP;
              IfForm.Rule = LP + "if" + Datum + Datum + DatumOpt + RP;

              CondForm.Rule = LP + "cond" + CondClauseList + CondElseOpt + RP;
              CondClauseList.Rule = MakePlusRule(CondClauseList, CondClause);
              CondClause.Rule = LP + Datum + DatumList + RP;
              CondElseOpt.Rule = Empty | LP + "else" + DatumList + RP;
              LetForm.Rule = LP + "let" + LP + LetPairList + RP + DatumList + RP;
              LetRecForm.Rule = LP + "letrec" + LP + LetPairList + RP + DatumList + RP;
              BeginForm.Rule = LP + "begin" + DatumList + RP;
              LetPairList.Rule = MakePlusRule(LetPairList, LetPair);
              LetPair.Rule = LP + Identifier + Datum + RP;
              #endregion

              //Register brace  pairs
              RegisterBracePair("(", ")");
              RegisterBracePair("[", "]");

              RegisterPunctuation(LP, RP);

              //Filters and other stuff
              BraceMatchFilter filter = new BraceMatchFilter();
              TokenFilters.Add(filter);

              //Scheme is tail-recursive language
              base.LanguageFlags = LanguageFlags.BubbleNodes | LanguageFlags.TailRecursive |
                  LanguageFlags.SupportsInterpreter | LanguageFlags.SupportsConsole;
              //keywords - just for colorizer
              base.AddKeywords("define", "lambda", "cond", "if", "begin", "let");
        }
        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);
        }
Exemple #7
0
        public Gramatica()
        {
            #region ER
            StringLiteral      CADENA  = new StringLiteral("cadena", "'");
            var                ENTERO  = new NumberLiteral("entero");
            var                DECIMAL = new RegexBasedTerminal("decimal", "[0-9]+'.'[0-9]+");
            IdentifierTerminal ID      = new IdentifierTerminal("id");

            ConstantTerminal BOOLEANO = new ConstantTerminal("booleano");
            BOOLEANO.Add("true", true);
            BOOLEANO.Add("false", false);

            CommentTerminal comentarioLinea  = new CommentTerminal("comentarioLinea", "//", "\n", "\r\n");
            CommentTerminal comentarioBloque = new CommentTerminal("comentarioBloque", "(*", "*)");
            #endregion

            #region Terminales
            var PROGRAM    = ToTerm("program");
            var USES       = ToTerm("uses");
            var BEGIN      = ToTerm("begin");
            var END        = ToTerm("end");
            var WRITE      = ToTerm("write");
            var WRITELN    = ToTerm("writeln");
            var READLN     = ToTerm("readln");
            var EXIT       = ToTerm("exit");
            var GRAFICARTS = ToTerm("graficar_ts");
            var SETLENGTH  = ToTerm("setlength");
            var VAR        = ToTerm("var");
            var CONST      = ToTerm("const");
            var TYPE       = ToTerm("type");
            var VOID       = ToTerm("void");
            var INTEGER    = ToTerm("integer");
            var DOUBLE     = ToTerm("double");
            var REAL       = ToTerm("real");
            var CHAR       = ToTerm("char");
            var STRING     = ToTerm("string");
            var OBJECT     = ToTerm("object");
            var IF         = ToTerm("if");
            var THEN       = ToTerm("then");
            var ELSE       = ToTerm("else");
            var CASE       = ToTerm("case");
            var OF         = ToTerm("of");
            var AND        = ToTerm("and");
            var OR         = ToTerm("or");
            var NOT        = ToTerm("not");
            var WHILE      = ToTerm("while");
            var FOR        = ToTerm("for");
            var TO         = ToTerm("to");
            var DO         = ToTerm("do");
            var REPEAT     = ToTerm("repeat");
            var UNTIL      = ToTerm("until");
            var BREAK      = ToTerm("break");
            var CONTINUE   = ToTerm("continue");
            var ARRAY      = ToTerm("array");
            var FUNCTION   = ToTerm("function");
            var PROCEDURE  = ToTerm("procedure");

            var PTCOMA   = ToTerm(";");
            var PTO      = ToTerm(".");
            var COMA     = ToTerm(",");
            var PARIZQ   = ToTerm("(");
            var PARDER   = ToTerm(")");
            var COMILLA  = ToTerm("'");
            var DOSPTS   = ToTerm(":");
            var CORIZQ   = ToTerm("[");
            var CORDER   = ToTerm("]");
            var MAS      = ToTerm("+");
            var MENOS    = ToTerm("-");
            var POR      = ToTerm("*");
            var DIV      = ToTerm("/");
            var MOD      = ToTerm("%");
            var MAYQUE   = ToTerm(">");
            var MENQUE   = ToTerm("<");
            var MAYIGQUE = ToTerm(">=");
            var MENIGQUE = ToTerm("<=");
            var DIF      = ToTerm("<>");
            var IGUAL    = ToTerm("=");

            RegisterOperators(1, IGUAL, DIF, MENQUE, MENIGQUE, MAYQUE, MAYIGQUE);
            RegisterOperators(2, MAS, MENOS, OR);
            RegisterOperators(3, POR, DIV, MOD, AND);
            RegisterOperators(4, NOT);

            NonGrammarTerminals.Add(comentarioLinea);
            NonGrammarTerminals.Add(comentarioBloque);

            #endregion

            #region No Terminales

            NonTerminal inicio              = new NonTerminal("inicio");
            NonTerminal inicio_bloques      = new NonTerminal("inicio_bloques");
            NonTerminal bloque_general      = new NonTerminal("bloque_general");
            NonTerminal bloque_uses         = new NonTerminal("bloque_uses");
            NonTerminal lista_uses          = new NonTerminal("lista_uses");
            NonTerminal bloques             = new NonTerminal("bloques");
            NonTerminal bloques2            = new NonTerminal("bloques2");
            NonTerminal bloque_principal    = new NonTerminal("bloque_principal");
            NonTerminal bloque_variables    = new NonTerminal("bloque_variables");
            NonTerminal bloque_variables2   = new NonTerminal("bloque_variables2");
            NonTerminal declaraciones_var   = new NonTerminal("declaraciones_var");
            NonTerminal declaracion_var     = new NonTerminal("declaracion_var");
            NonTerminal lista_ids           = new NonTerminal("lista_ids");
            NonTerminal tipo_var            = new NonTerminal("tipo_var");
            NonTerminal bloque_tipos        = new NonTerminal("bloque_tipos");
            NonTerminal declaraciones_tipos = new NonTerminal("declaraciones_tipos");
            NonTerminal declaracion_tipos   = new NonTerminal("declaracion_tipos");
            NonTerminal tipo_index          = new NonTerminal("tipo_index");
            NonTerminal index               = new NonTerminal("index");
            NonTerminal tipo_object         = new NonTerminal("tipo_object");
            NonTerminal bloque_constantes   = new NonTerminal("bloque_constantes");
            NonTerminal definiciones_const  = new NonTerminal("definiciones_const");
            NonTerminal definicion_const    = new NonTerminal("definicion_const");
            NonTerminal asignacion          = new NonTerminal("asignacion");
            NonTerminal lista_expresiones   = new NonTerminal("lista_expresiones");
            NonTerminal instruccion         = new NonTerminal("instruccion");
            NonTerminal instrucciones       = new NonTerminal("instrucciones");
            NonTerminal instruccion_sin_ptc = new NonTerminal("instruccion_sin_ptc");
            NonTerminal bloque_compuesto    = new NonTerminal("bloque_compuesto");
            NonTerminal print               = new NonTerminal("print");
            NonTerminal lista_exprs         = new NonTerminal("lista_exprs");
            NonTerminal read                  = new NonTerminal("read");
            NonTerminal length_array          = new NonTerminal("length_array");
            NonTerminal graficar              = new NonTerminal("graficar_ts");
            NonTerminal salir                 = new NonTerminal("salir");
            NonTerminal sent_if               = new NonTerminal("sent_if");
            NonTerminal sent_if2              = new NonTerminal("sent_if2");
            NonTerminal sent_case             = new NonTerminal("sent_case");
            NonTerminal lista_casos           = new NonTerminal("lista_casos");
            NonTerminal caso                  = new NonTerminal("caso");
            NonTerminal ciclo_for             = new NonTerminal("ciclo_for");
            NonTerminal ciclo_while           = new NonTerminal("ciclo_while");
            NonTerminal ciclo_repeat          = new NonTerminal("ciclo_repeat");
            NonTerminal bloque_funcion        = new NonTerminal("bloque_funcion");
            NonTerminal argumentos_header     = new NonTerminal("argumentos_header");
            NonTerminal argumentos_header2    = new NonTerminal("argumentos_header2");
            NonTerminal cuerpo_funcion        = new NonTerminal("cuerpo_funcion");
            NonTerminal lista_argumentos      = new NonTerminal("lista_argumentos");
            NonTerminal lista_argumentos2     = new NonTerminal("lista_argumentos2");
            NonTerminal argumentos            = new NonTerminal("argumentos");
            NonTerminal llamada_funcion       = new NonTerminal("llamada_funcion");
            NonTerminal bloque_procedimiento  = new NonTerminal("bloque_procedimiento");
            NonTerminal llamada_procedimiento = new NonTerminal("llamada_procedimiento");
            NonTerminal expresion             = new NonTerminal("expresion");
            NonTerminal expresion_imprimible  = new NonTerminal("expresion_imprimible");
            NonTerminal dato                  = new NonTerminal("dato");

            #endregion

            #region Gramatica

            inicio.Rule = inicio_bloques;

            inicio_bloques.Rule = PROGRAM + ID + ";" + bloque_principal
                                  | PROGRAM + ID + ";" + bloques + bloque_principal;

            bloques.Rule = this.MakePlusRule(bloques, bloques2);
            //bloques.Rule = bloques + bloques2
            //| bloques2;

            bloques2.Rule = bloque_funcion
                            | bloque_procedimiento
                            | bloque_variables
                            | bloque_tipos
                            | bloque_constantes;

            bloque_principal.Rule = BEGIN + instrucciones + END + ".";

            //---------------------- DECLARACIONES DE VARIABLES----------------------------

            bloque_variables.Rule = bloque_constantes + bloque_variables2
                                    | bloque_variables2;

            bloque_variables2.Rule = VAR + declaraciones_var;

            declaraciones_var.Rule = this.MakePlusRule(declaraciones_var, declaracion_var);
            //declaraciones_var.Rule = declaraciones_var + declaracion_var
            //| declaracion_var;

            declaracion_var.Rule = lista_ids + DOSPTS + tipo_var + PTCOMA
                                   | ID + DOSPTS + ARRAY + CORIZQ + tipo_index + CORDER + OF + tipo_var + PTCOMA
                                   | ID + DOSPTS + tipo_var + IGUAL + expresion + PTCOMA;

            lista_ids.Rule = this.MakeListRule(lista_ids, ToTerm(","), ID);
            //lista_ids=lista_ids ',' id
            //| id

            tipo_var.Rule = INTEGER | DOUBLE | REAL | CHAR | STRING | PARIZQ + expresion + PARDER | ID;

            //---------------------- DECLARACIONES DE TIPOS----------------------------

            bloque_tipos.Rule = TYPE + declaraciones_tipos;

            declaraciones_tipos.Rule = this.MakePlusRule(declaraciones_tipos, declaracion_tipos);
            //declaraciones_tipos=declaraciones_tipos declaracion_tipos
            //| declaracion_tipos

            declaracion_tipos.Rule = lista_ids + IGUAL + tipo_var + PTCOMA                                        //declarando un tipo simple
                                     | ID + IGUAL + ARRAY + CORIZQ + tipo_index + CORDER + OF + tipo_var + PTCOMA //declarando un tipo array
                                     | ID + IGUAL + ARRAY + OF + tipo_var + PTCOMA                                //declarando un tipo array dinamico
                                     | tipo_object + PTCOMA;

            tipo_index.Rule = this.MakeListRule(tipo_index, ToTerm(","), index);
            //tipo_index.Rule = tipo_index + COMA index
            //| index

            index.Rule = dato + PTO + PTO + dato;

            tipo_object.Rule = ID + IGUAL + OBJECT + VAR + bloque_variables2 + END;

            //----------------------------------BLOQUE DE CONSTANTES ----------------------------------------
            bloque_constantes.Rule = CONST + definiciones_const;

            definiciones_const.Rule = definiciones_const + definicion_const
                                      | definicion_const;

            definicion_const.Rule = ID + IGUAL + dato + PTCOMA;

            //---------------------------------- - ASIGNACIONES - ACCESOS----------------------------------------
            asignacion.Rule = ID + DOSPTS + IGUAL + expresion
                              | ID + CORIZQ + lista_expresiones + CORDER + DOSPTS + IGUAL + expresion
                              | ID + DOSPTS + IGUAL + ID + CORIZQ + lista_expresiones + CORDER;

            lista_expresiones.Rule = this.MakeListRule(lista_expresiones, ToTerm(","), expresion);
            //lista_expresiones=lista_expresiones ',' expresion
            //| expresion
            //----------------------------------------------------------------------------------------------------

            //instrucciones.Rule = this.MakePlusRule(instrucciones, instruccion);
            instrucciones.Rule = instrucciones + instruccion
                                 | instruccion;

            instruccion.Rule = print + ";"
                               | read + PTCOMA
                               | asignacion + PTCOMA
                               | sent_if + PTCOMA
                               | sent_case + PTCOMA
                               | ciclo_for + PTCOMA
                               | ciclo_while + PTCOMA
                               | ciclo_repeat + PTCOMA
                               | bloque_compuesto + PTCOMA
                               | llamada_funcion + PTCOMA
                               | llamada_procedimiento + PTCOMA
                               | length_array + PTCOMA
                               | graficar + PTCOMA
                               | salir + PTCOMA;

            instruccion_sin_ptc.Rule = print | read | asignacion | sent_if | sent_case | ciclo_for | ciclo_while | ciclo_repeat | bloque_compuesto | llamada_funcion | llamada_procedimiento | length_array | graficar | salir;

            bloque_compuesto.Rule = BEGIN + instrucciones + END;

            print.Rule = WRITE + "(" + lista_exprs + ")"
                         | WRITELN + "(" + lista_exprs + ")"
                         | WRITELN;

            lista_exprs.Rule = lista_exprs + COMA + expresion_imprimible
                               | expresion_imprimible;

            read.Rule = READLN + PARIZQ + dato + PARDER;

            length_array.Rule = SETLENGTH + PARIZQ + ID + COMA + lista_expresiones + PARDER;

            graficar.Rule = GRAFICARTS + PARIZQ + PARDER
                            | GRAFICARTS;

            salir.Rule = EXIT + PARIZQ + lista_expresiones + PARDER
                         | EXIT;

            //---------------------------------------- CONDICIONES Y CICLOS----------------------------------------
            sent_if.Rule = IF + expresion + THEN + sent_if;

            sent_if2.Rule = instruccion
                            | instruccion_sin_ptc + ELSE + sent_if
                            | instruccion_sin_ptc + ELSE + instruccion;

            sent_case.Rule = CASE + PARIZQ + expresion + PARDER + OF + lista_casos + END + PTCOMA
                             | CASE + PARIZQ + expresion + PARDER + OF + lista_casos + ELSE + instruccion + END + PTCOMA;

            lista_casos.Rule = this.MakePlusRule(lista_casos, caso);
            //lista_casos=lista_casos caso
            //| caso

            caso.Rule = expresion + DOSPTS + instruccion;

            ciclo_for.Rule = FOR + asignacion + TO + dato + DO + instruccion;

            ciclo_while.Rule = WHILE + PARIZQ + expresion + PARDER + DO + instruccion;

            ciclo_repeat.Rule = REPEAT + instrucciones + UNTIL + expresion;

            //--------------------------------------------------FUNCIONES--------------------------------------------------

            bloque_funcion.Rule = FUNCTION + ID + argumentos_header + DOSPTS + tipo_var + PTCOMA + cuerpo_funcion;

            argumentos_header.Rule = PARIZQ + argumentos_header2
                                     | Empty;

            argumentos_header2.Rule = lista_argumentos + PARDER
                                      | PARDER;

            cuerpo_funcion.Rule = bloque_variables2 + bloque_compuesto + PTCOMA
                                  | bloque_compuesto + PTCOMA;

            lista_argumentos.Rule = argumentos + lista_argumentos2;

            lista_argumentos2.Rule = PTCOMA + argumentos + lista_argumentos2
                                     | Empty;

            argumentos.Rule = VAR + lista_ids + DOSPTS + tipo_var
                              | lista_ids + DOSPTS + tipo_var;

            llamada_funcion.Rule = ID + DOSPTS + IGUAL + ID + PARIZQ + lista_argumentos + PARDER
                                   | ID + DOSPTS + IGUAL + ID + PARIZQ + PARDER;

            //------------------------------------------------PROCEDIMIENTOS-----------------------------------------------

            bloque_procedimiento.Rule = PROCEDURE + ID + argumentos_header + PTCOMA + cuerpo_funcion;

            llamada_procedimiento.Rule = ID + PARIZQ + lista_argumentos + PARDER
                                         | ID + PARIZQ + PARDER;

            //------------------------------------------------ OPERACIONES Y EXPRESIONES----------------------------------------------
            expresion.Rule = expresion + MAS + expresion
                             | expresion + MENOS + expresion
                             | expresion + POR + expresion
                             | expresion + DIV + expresion
                             | expresion + MOD + expresion
                             | expresion + IGUAL + expresion
                             | expresion + DIF + expresion
                             | expresion + MAYQUE + expresion
                             | expresion + MENQUE + expresion
                             | expresion + MAYIGQUE + expresion
                             | expresion + MENIGQUE + expresion
                             | expresion + AND + expresion
                             | expresion + OR + expresion
                             | NOT + expresion
                             | PARIZQ + expresion + PARDER
                             | dato;

            expresion_imprimible.Rule = expresion + DOSPTS + ENTERO + DOSPTS + ENTERO
                                        | expresion;

            dato.Rule = ID | CADENA | ENTERO | DECIMAL | BOOLEANO;

            #endregion

            #region Preferencias
            this.Root = inicio;
            MarkPunctuation("(", ")", ";", ".", ",");
            #endregion
        }
Exemple #8
0
        public PythonGrammar()
        {
            #region Declare Terminals
              ConstantTerminal Constants = new ConstantTerminal("Constants");
              Constants.Add("True", true);
              Constants.Add("False", false);
              IdentifierTerminal Identifier = new IdentifierTerminal("Identifier");
              Terminal Comment = new CommentTerminal("Comment", "#", "\n");
              NonGrammarTerminals.Add(Comment);

              Terminal comma = Symbol(",", "comma");
              //commaQ is optional trailing comma in lists; it causes several conflicts in this grammar
              // so we get rid of it (by assigning it Empty value)
              //NonTerminal commaQ = comma.Q();  //this causes several conflicts
              NonTerminal commaQ = Empty;
              Terminal dot = Symbol(".", "dot");
              Terminal LBr   = Symbol("[");
              Terminal RBr   = Symbol("]");
              Terminal bQuote   = Symbol("`");
              Terminal ellipsis   = Symbol("...");
              Terminal colon = Symbol(":");
              Terminal NAME = Identifier;
              Terminal NEWLINE = Grammar.NewLine;
              Terminal INDENT = Grammar.Indent;
              Terminal DEDENT = Grammar.Dedent;
              Terminal semicolon = Symbol(";");
              Terminal EOF = Grammar.Eof;
              Terminal NUMBER = TerminalFactory.CreatePythonNumber("NUMBER");
              #endregion

              #region Declare NonTerminals
              StringLiteral STRING = TerminalFactory.CreatePythonString("String");
              NonTerminal single_input = new NonTerminal("single_input");
              NonTerminal file_input = new NonTerminal("file_input");
              NonTerminal eval_input = new NonTerminal("eval_input");
              NonTerminal decorator = new NonTerminal("decorator");
              NonTerminal funcdef = new NonTerminal("funcdef");
              NonTerminal parameters = new NonTerminal("parameters");
              NonTerminal varargslist = new NonTerminal("varargslist");
              NonTerminal vararg = new NonTerminal("vararg");
              NonTerminal fpdef = new NonTerminal("fpdef");
              NonTerminal fpdef_ext = new NonTerminal("fpdef_ext");
              NonTerminal fplist = new NonTerminal("fplist");
              NonTerminal stmt = new NonTerminal("stmt");
              NonTerminal simple_stmt = new NonTerminal("simple_stmt");
              NonTerminal small_stmt = new NonTerminal("small_stmt");
              NonTerminal expr_stmt = new NonTerminal("expr_stmt");
              NonTerminal yield_or_testlist = new NonTerminal("yield_or_testlist");
              NonTerminal augassign = new NonTerminal("augassign");
              NonTerminal print_stmt = new NonTerminal("print_stmt");
              NonTerminal del_stmt = new NonTerminal("del_stmt");
              NonTerminal pass_stmt = new NonTerminal("pass_stmt");
              NonTerminal flow_stmt = new NonTerminal("flow_stmt");
              NonTerminal break_stmt = new NonTerminal("break_stmt");
              NonTerminal continue_stmt = new NonTerminal("continue_stmt");
              NonTerminal return_stmt = new NonTerminal("return_stmt");
              NonTerminal yield_stmt = new NonTerminal("yield_stmt");
              NonTerminal raise_stmt = new NonTerminal("raise_stmt");
              NonTerminal import_stmt = new NonTerminal("import_stmt");
              NonTerminal import_name = new NonTerminal("import_name");
              NonTerminal import_from = new NonTerminal("import_from");
              NonTerminal import_as_name = new NonTerminal("import_as_name");
              NonTerminal dotted_as_name = new NonTerminal("dotted_as_name");
              NonTerminal import_as_names = new NonTerminal("import_as_names");
              NonTerminal dotted_as_names = new NonTerminal("dotted_as_names");
              NonTerminal dotted_name = new NonTerminal("dotted_name");
              NonTerminal global_stmt = new NonTerminal("global_stmt");
              NonTerminal exec_stmt = new NonTerminal("exec_stmt");
              NonTerminal assert_stmt = new NonTerminal("assert_stmt");
              NonTerminal compound_stmt = new NonTerminal("compound_stmt");
              NonTerminal if_stmt = new NonTerminal("if_stmt");
              NonTerminal else_clause = new NonTerminal("else_clause");
              NonTerminal while_stmt = new NonTerminal("while_stmt");
              NonTerminal for_stmt = new NonTerminal("for_stmt");
              NonTerminal try_stmt = new NonTerminal("try_stmt");
              NonTerminal finally_block = new NonTerminal("finally_block");
              NonTerminal with_stmt = new NonTerminal("with_stmt");
              NonTerminal with_var = new NonTerminal("with_var");
              NonTerminal except_clause = new NonTerminal("except_clause");
              NonTerminal suite = new NonTerminal("suite");
              NonTerminal testlist_safe = new NonTerminal("testlist_safe");
              NonTerminal old_test = new NonTerminal("old_test");
              NonTerminal old_lambdef = new NonTerminal("old_lambdef");
              NonTerminal test = new NonTerminal("test");
              NonTerminal testlist = new NonTerminal("testlist");
              NonTerminal testlist1 = new NonTerminal("testlist1");
              NonTerminal or_test = new NonTerminal("or_test");
              NonTerminal and_test = new NonTerminal("and_test");
              NonTerminal not_test = new NonTerminal("not_test");
              NonTerminal comparison = new NonTerminal("comparison");
              NonTerminal comp_op = new NonTerminal("comp_op");
              NonTerminal expr = new NonTerminal("expr");
              NonTerminal xor_expr = new NonTerminal("xor_expr");
              NonTerminal and_expr = new NonTerminal("and_expr");
              NonTerminal shift_expr = new NonTerminal("shift_expr");
              NonTerminal arith_expr = new NonTerminal("arith_expr");
              NonTerminal shift_op = new NonTerminal("shift_op");
              NonTerminal sum_op = new NonTerminal("sum_op");
              NonTerminal mul_op = new NonTerminal("mul_op");

              NonTerminal term = new NonTerminal("term");
              NonTerminal factor = new NonTerminal("factor");
              NonTerminal power = new NonTerminal("power");
              NonTerminal atom = new NonTerminal("atom");
              NonTerminal listmaker = new NonTerminal("listmaker");
              NonTerminal testlist_gexp = new NonTerminal("testlist_gexp");
              NonTerminal lambdef = new NonTerminal("lambdef");
              NonTerminal trailer = new NonTerminal("trailer");
              NonTerminal subscriptlist = new NonTerminal("subscriptlist");
              NonTerminal subscript = new NonTerminal("subscript");
              NonTerminal sliceop = new NonTerminal("sliceop");
              NonTerminal exprlist = new NonTerminal("exprlist");
              NonTerminal dictmaker = new NonTerminal("dictmaker");
              NonTerminal dict_elem = new NonTerminal("dict_elem");
              NonTerminal classdef = new NonTerminal("classdef");
              NonTerminal arglist = new NonTerminal("arglist");
              NonTerminal argument = new NonTerminal("argument");
              NonTerminal list_iter = new NonTerminal("list_iter");
              NonTerminal list_for = new NonTerminal("list_for");
              NonTerminal list_if = new NonTerminal("list_if");
              NonTerminal gen_iter = new NonTerminal("gen_iter");
              NonTerminal gen_for = new NonTerminal("gen_for");
              NonTerminal gen_if = new NonTerminal("gen_if");
              NonTerminal encoding_decl = new NonTerminal("encoding_decl");
              NonTerminal yield_expr = new NonTerminal("yield_expr");
              #endregion

              #region RULES
              // The commented rules before each statement are original grammar rules
              //  copied from the grammar file.
              //Set grammar root
              base.Root = file_input;
              //file_input: (NEWLINE | stmt)* ENDMARKER
              file_input.Rule = NEWLINE.Q() + stmt.Star();// +EOF; //EOF is added by default as a lookahead

              //single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
              single_input.Rule = NEWLINE | simple_stmt | compound_stmt + NEWLINE;
              //eval_input: testlist NEWLINE* ENDMARKER
              eval_input.Rule = NEWLINE.Q() + WithStar(testlist + NEWLINE); // +EOF;  //changed this

              //decorators: decorator+
              //decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
              decorator.Rule = "@" + dotted_name + WithQ("(" + arglist.Q() + ")") + NEWLINE;
              //funcdef: [decorators] 'def' NAME parameters ':' suite
              funcdef.Rule = decorator.Star() + "def" + NAME + parameters + ":" + suite;
              // parameters: '(' [varargslist] ')'
              parameters.Rule = "(" + varargslist.Q() + ")";

              /* varargslist: ((fpdef ['=' test] ',')*
              ('*' NAME [',' '**' NAME] | '**' NAME) |
                fpdef ['=' test] (',' fpdef ['=' test])* [','])  */
              fpdef_ext.Rule = fpdef + WithQ("=" + test);
            /*      varargslist.Expression = WithStar(fpdef_ext + comma) +
                    WithQ("*" + NAME + WithQ (comma + "**" + NAME) | "**" + NAME) |
                    fpdef_ext.Plus(comma) + commaQ; */  // ambiguous
              varargslist.Rule = vararg.Plus(comma) + commaQ;
              vararg.Rule = fpdef_ext | "*" + NAME | "**" + NAME; // added this to grammar
              // fpdef: NAME | '(' fplist ')'
              fpdef.Rule = NAME | "(" + fplist + ")";
              //fplist: fpdef (',' fpdef)* [',']
              fplist.Rule = fpdef.Plus(comma) + commaQ;

              //stmt: simple_stmt | compound_stmt
              stmt.Rule = simple_stmt | compound_stmt;
              //simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
              simple_stmt.Rule = small_stmt.Plus(semicolon) + semicolon.Q() + NEWLINE;
              /* small_stmt: (expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt |
             import_stmt | global_stmt | exec_stmt | assert_stmt)   */
              small_stmt.Rule = expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt |
                   import_stmt | global_stmt | exec_stmt | assert_stmt;
              /* expr_stmt: testlist (augassign (yield_expr|testlist) |
                     ('=' (yield_expr|testlist))*)    */
              //Note!: the following is a less strict expression, it allows augassign to appear multiple times
              //  in non-first position; the after-parse analysis should catch this
              expr_stmt.Rule = testlist + WithStar( (augassign|"=") + yield_or_testlist);
              yield_or_testlist.Rule = yield_expr | testlist;
              /* augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=') */
              augassign.Rule = Symbol("+=") | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" |
                  "<<=" | ">>=" | "**=" | "//=";
              //# For normal assignments, additional restrictions enforced by the interpreter
              /*  print_stmt: 'print' ( [ test (',' test)* [','] ] |
                      '>>' test [ (',' test)+ [','] ] )     */
              print_stmt.Rule = "print" + (Empty | testlist | ">>" + testlist);  //modified slightly using testlist
              //del_stmt: 'del' exprlist
              del_stmt.Rule = "del" + exprlist;
              //pass_stmt: 'pass'
              pass_stmt.Rule = "pass";
              //flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
              flow_stmt.Rule = break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt;
              //break_stmt: 'break'
              break_stmt.Rule = "break";
              // continue_stmt: 'continue'
              continue_stmt.Rule = "continue";
              // return_stmt: 'return' [testlist]
              return_stmt.Rule = "return" + testlist.Q();
              // yield_stmt: yield_expr
              yield_stmt.Rule = yield_expr;
              // raise_stmt: 'raise' [test [',' test [',' test]]]
              raise_stmt.Rule = "raise" + WithQ( test + WithQ("," + test + WithQ("," + test)));
              // import_stmt: import_name | import_from
              import_stmt.Rule = import_name | import_from;
              // import_name: 'import' dotted_as_names
              import_name.Rule = "import" + dotted_as_names;
              // import_from: ('from' ('.'* dotted_name | '.'+)
              //        'import' ('*' | '(' import_as_names ')' | import_as_names))
              // import_from.Expression = Symbol("from") + (dot.Star() + dotted_name | dot.Plus()) +   //ambiguious
              import_from.Rule = Symbol("from") + dot.Star() + (dotted_name | dot) +
                    "import" + (Symbol("*") | "(" + import_as_names + ")" | import_as_names);
              // import_as_name: NAME ['as' NAME]
              import_as_name.Rule = NAME + WithQ("as" + NAME);
              // dotted_as_name: dotted_name ['as' NAME]
              dotted_as_name.Rule = dotted_name + WithQ("as" + NAME);
              // import_as_names: import_as_name (',' import_as_name)* [',']
              import_as_names.Rule = import_as_name.Plus(comma) + commaQ;
              // dotted_as_names: dotted_as_name (',' dotted_as_name)*
              dotted_as_names.Rule = dotted_as_name.Plus(comma);
              // dotted_name: NAME ('.' NAME)*
              dotted_name.Rule = NAME.Plus(dot);
              // global_stmt: 'global' NAME (',' NAME)*
              global_stmt.Rule = "global" + NAME.Plus(comma);
              // exec_stmt: 'exec' expr ['in' test [',' test]]
              exec_stmt.Rule = "exec" + expr + WithQ("in" + test.Plus(comma));
              // assert_stmt: 'assert' test [',' test]
              assert_stmt.Rule = "assert" + test.Plus(comma);

              // compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef
              compound_stmt.Rule = if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef;
              // if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
              if_stmt.Rule = "if" + test + ":" + suite +
                    WithStar("elif" + test + ":" + suite) + else_clause.Q();
              else_clause.Rule = "else" + colon + suite;
              // while_stmt: 'while' test ':' suite ['else' ':' suite]
              while_stmt.Rule = "while" + test + ":" + suite + else_clause.Q();
              // for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
              for_stmt.Rule = "for" + exprlist + "in" + testlist + ":" + suite + else_clause.Q();
            /* try_stmt: ('try' ':' suite
               ((except_clause ':' suite)+
            ['else' ':' suite]
            ['finally' ':' suite] |
               'finally' ':' suite))   */
              try_stmt.Rule = "try" + colon + suite +
            (  (except_clause + ":" + suite)+ else_clause.Q() + finally_block.Q() | finally_block   );
              finally_block.Rule = "finally" + colon + suite;
              // with_stmt: 'with' test [ with_var ] ':' suite
              with_stmt.Rule = "with" + test + with_var.Q() + ":" + suite;
              // with_var: 'as' expr
              with_var.Rule = "as" + expr;
              // NB compile.c makes sure that the default except clause is last
              // except_clause: 'except' [test [('as' | ',') test]]
              except_clause.Rule = "except" + WithQ(test + WithQ( (Symbol("as") | ",") + test));
              // suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
              suite.Rule = simple_stmt | NEWLINE  + INDENT + stmt.Plus() + DEDENT;

              //# Backward compatibility cruft to support:
              //# [ x for x in lambda: True, lambda: False if x() ]
              //# even while also allowing:
              //# lambda x: 5 if x else 2
              //# (But not a mix of the two)

              // testlist_safe: old_test [(',' old_test)+ [',']]
              testlist_safe.Rule = old_test.Plus(comma) + commaQ;
              // old_test: or_test | old_lambdef
              old_test.Rule = or_test | old_lambdef;
              // old_lambdef: 'lambda' [varargslist] ':' old_test
              old_lambdef.Rule = "lambda" + varargslist.Q() + ":" + old_test;

              // test: or_test ['if' or_test 'else' test] | lambdef
              test.Rule = or_test + WithQ("if" + or_test + "else" + test) | lambdef;
              // or_test: and_test ('or' and_test)*
              or_test.Rule = and_test + WithStar("or" + and_test);
              // and_test: not_test ('and' not_test)*
              and_test.Rule = not_test + WithStar("and" + not_test);
              // not_test: 'not' not_test | comparison
              not_test.Rule = "not" + not_test | comparison;
              // comparison: expr (comp_op expr)*
              comparison.Rule = expr + WithStar(comp_op + expr);
              // comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
              comp_op.Rule = Symbol("<")|">"|"=="|">="|"<="|"<>"|"!="|"in"|
                           Symbol("not") + "in"|"is"|Symbol("is") + "not";
              // expr: xor_expr ('|' xor_expr)*
              expr.Rule = xor_expr.Plus(Symbol("|"));
              // xor_expr: and_expr ('^' and_expr)*
              xor_expr.Rule = and_expr.Plus(Symbol("^"));
              // and_expr: shift_expr ('&' shift_expr)*
              and_expr.Rule = shift_expr.Plus(Symbol("&"));
              // shift_expr: arith_expr (('<<'|'>>') arith_expr)*
              shift_expr.Rule = arith_expr.Plus(shift_op); //
              shift_op.Rule = Symbol("<<")|">>";
              // arith_expr: term (('+'|'-') term)*
              arith_expr.Rule = term.Plus(sum_op);
              sum_op.Rule = Symbol("+") | "-";
              // term: factor (('*'|'/'|'%'|'//') factor)*
              term.Rule = factor.Plus(mul_op);
              mul_op.Rule = Symbol("*")|"/"|"%"|"//";
              // factor: ('+'|'-'|'~') factor | power
              factor.Rule = (Symbol("+")|"-"|"~") + factor | power;
              // power: atom trailer* ['**' factor]
              power.Rule = atom + trailer.Star() + WithQ("**" + factor);
              /* atom: ('(' [yield_expr|testlist_gexp] ')' |
              '[' [listmaker] ']' |
              '{' [dictmaker] '}' |
              '`' testlist1 '`' |
              NAME | NUMBER | STRING+)  */
              atom.Rule = "(" + WithQ(yield_expr|testlist_gexp) + ")" |
             "[" + listmaker.Q() + "]" |
             "{" + dictmaker.Q() + "}" |
             "`" + testlist1 + "`" |
             NAME | NUMBER | STRING; //.Plus();  //removed "+" - seems strange at least
              // listmaker: test ( list_for | (',' test)* [','] )
              //  listmaker.Expression = test + ( list_for | WithStar("," + test) + commaQ ); // ambigouous
            //      listmaker.Expression = test + list_for.Q() | testlist;                             // modified version
              listmaker.Rule = test + list_for.Q() + testlist.Q() + commaQ;                             // modified version
              // testlist_gexp: test ( gen_for | (',' test)* [','] )
              //   testlist_gexp.Expression = test + ( gen_for | test.Star(comma) + commaQ ); // ambiguous
              testlist_gexp.Rule = test + gen_for | test.Plus(comma) + commaQ;          // modified version
              // lambdef: 'lambda' [varargslist] ':' test
              lambdef.Rule = "lambda" + varargslist.Q() + ":" + test;
              // trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
              trailer.Rule = "(" + arglist.Q() + ")" | "[" + subscriptlist + "]" | "." + NAME;
              // subscriptlist: subscript (',' subscript)* [',']
              subscriptlist.Rule = subscript.Plus(comma) + commaQ;
              // subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
              subscript.Rule = "..." | test | test.Q() + ":" + test.Q() + sliceop.Q();
              // sliceop: ':' [test]
              sliceop.Rule = ":" + test.Q();
              // exprlist: expr (',' expr)* [',']
              exprlist.Rule = expr.Plus(comma)  + commaQ;
              // testlist: test (',' test)* [',']
              testlist.Rule = test.Plus(comma) + commaQ;
              // dictmaker: test ':' test (',' test ':' test)* [',']
              dictmaker.Rule = dict_elem.Plus(comma) + commaQ;
              dict_elem.Rule = test + ":" + test;

              // classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
              classdef.Rule = "class" + NAME + WithQ("(" + testlist.Q() + ")") + ":" + suite;

              // arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)
              arglist.Rule = WithStar(argument + comma) +
               (argument + commaQ | "*" + test + WithQ(comma + "**" + test) | "**" + test);

              // argument: test [gen_for] | test '=' test  # Really [keyword '='] test
              argument.Rule = test + gen_for.Q() | test + "=" + test;  //# Really [keyword "="] test

              // list_iter: list_for | list_if
              list_iter.Rule = list_for | list_if;
              // list_for: 'for' exprlist 'in' testlist_safe [list_iter]
              list_for.Rule = "for" + exprlist + "in" + testlist_safe + list_iter.Q();
              // list_if: 'if' old_test [list_iter]
              list_if.Rule = "if" + old_test + list_iter.Q();

              // gen_iter: gen_for | gen_if
              gen_iter.Rule = gen_for | gen_if;
              // gen_for: 'for' exprlist 'in' or_test [gen_iter]
              gen_for.Rule = "for" + exprlist + "in" + or_test + gen_iter.Q();
              // gen_if: 'if' old_test [gen_iter]
              gen_if.Rule = "if" + old_test + gen_iter.Q();

              // testlist1: test (',' test)*
              testlist1.Rule = test.Plus(comma);

              // # not used in grammar, but may appear in "node" passed from Parser to Compiler
              // encoding_decl: NAME
              encoding_decl.Rule = NAME;

              // yield_expr: 'yield' [testlist]
              yield_expr.Rule = "yield" + testlist.Q();
              #endregion

              RegisterPunctuation( "(", ")", ",", ":" );

              TokenFilters.Add(new CodeOutlineFilter(true));

              id.AddKeywords("and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
                                  "assert", "else", "if", "pass", "yield", "break", "except", "import", "print",
                                  "class", "exec", "in", "raise", "continue", "finally", "is", "return",
                                  "def", "for", "lambda", "try");
        }