public ExpressionEvaluatorGrammar() : base(caseSensitive: false)
        {
            this.GrammarComments =
      @"Irony expression evaluator. Case-insensitive. Supports big integers, float data types, variables, assignments,
arithmetic operations, augmented assignments (+=, -=), inc/dec (++,--), strings with embedded expressions; 
bool operations &,&&, |, ||; ternary '?:' operator.";
            // 1. Terminals
            var number = new NumberLiteral("number");
            //Let's allow big integers (with unlimited number of digits):
            number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt };
            var identifier = new IdentifierTerminal("identifier");
            var comment = new CommentTerminal("comment", "#", "\n", "\r");
            //comment must be added to NonGrammarTerminals list; it is not used directly in grammar rules,
            // so we add it to this list to let Scanner know that it is also a valid terminal. 
            base.NonGrammarTerminals.Add(comment);
            var comma = ToTerm(",");

            //String literal with embedded expressions  ------------------------------------------------------------------
            var stringLit = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate);
            stringLit.AddStartEnd("'", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate);
            stringLit.AstConfig.NodeType = typeof(StringTemplateNode);
            var Expr = new NonTerminal("Expr"); //declare it here to use in template definition 
            var templateSettings = new StringTemplateSettings(); //by default set to Ruby-style settings 
            templateSettings.ExpressionRoot = Expr; //this defines how to evaluate expressions inside template
            this.SnippetRoots.Add(Expr);
            stringLit.AstConfig.Data = templateSettings;
            //--------------------------------------------------------------------------------------------------------

            // 2. Non-terminals
            var Term = new NonTerminal("Term");
            var BinExpr = new NonTerminal("BinExpr", typeof(BinaryOperationNode));
            var ParExpr = new NonTerminal("ParExpr");
            var UnExpr = new NonTerminal("UnExpr", typeof(UnaryOperationNode));
            var TernaryIfExpr = new NonTerminal("TernaryIf", typeof(IfNode));
            var ArgList = new NonTerminal("ArgList", typeof(ExpressionListNode));
            var FunctionCall = new NonTerminal("FunctionCall", typeof(FunctionCallNode));
            var MemberAccess = new NonTerminal("MemberAccess", typeof(MemberAccessNode));
            var IndexedAccess = new NonTerminal("IndexedAccess", typeof(IndexedAccessNode));
            var ObjectRef = new NonTerminal("ObjectRef"); // foo, foo.bar or f['bar']
            var UnOp = new NonTerminal("UnOp");
            var BinOp = new NonTerminal("BinOp", "operator");
            var PrefixIncDec = new NonTerminal("PrefixIncDec", typeof(IncDecNode));
            var PostfixIncDec = new NonTerminal("PostfixIncDec", typeof(IncDecNode));
            var IncDecOp = new NonTerminal("IncDecOp");
            var AssignmentStmt = new NonTerminal("AssignmentStmt", typeof(AssignmentNode));
            var AssignmentOp = new NonTerminal("AssignmentOp", "assignment operator");
            var Statement = new NonTerminal("Statement");
            var Program = new NonTerminal("Program", typeof(StatementListNode));

            // 3. BNF rules
            Expr.Rule = Term | UnExpr | BinExpr | PrefixIncDec | PostfixIncDec | TernaryIfExpr;
            Term.Rule = number | ParExpr | stringLit | FunctionCall | identifier | MemberAccess | IndexedAccess;
            ParExpr.Rule = "(" + Expr + ")";
            UnExpr.Rule = UnOp + Term + ReduceHere();
            UnOp.Rule = ToTerm("+") | "-" | "!";
            BinExpr.Rule = Expr + BinOp + Expr;
            BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**" | "==" | "<" | "<=" | ">" | ">=" | "!=" | "&&" | "||" | "&" | "|";
            PrefixIncDec.Rule = IncDecOp + identifier;
            PostfixIncDec.Rule = identifier + PreferShiftHere() + IncDecOp;
            IncDecOp.Rule = ToTerm("++") | "--";
            TernaryIfExpr.Rule = Expr + "?" + Expr + ":" + Expr;
            MemberAccess.Rule = Expr + PreferShiftHere() + "." + identifier;
            AssignmentStmt.Rule = ObjectRef + AssignmentOp + Expr;
            AssignmentOp.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/=";
            Statement.Rule = AssignmentStmt | Expr | Empty;
            ArgList.Rule = MakeStarRule(ArgList, comma, Expr);
            FunctionCall.Rule = Expr + PreferShiftHere() + "(" + ArgList + ")";
            FunctionCall.NodeCaptionTemplate = "call #{0}(...)";
            ObjectRef.Rule = identifier | MemberAccess | IndexedAccess;
            IndexedAccess.Rule = Expr + PreferShiftHere() + "[" + Expr + "]";

            Program.Rule = MakePlusRule(Program, NewLine, Statement);

            this.Root = Program;       // Set grammar root

            // 4. Operators precedence
            RegisterOperators(10, "?");
            RegisterOperators(15, "&", "&&", "|", "||");
            RegisterOperators(20, "==", "<", "<=", ">", ">=", "!=");
            RegisterOperators(30, "+", "-");
            RegisterOperators(40, "*", "/");
            RegisterOperators(50, Associativity.Right, "**");
            RegisterOperators(60, "!");
            // For precedence to work, we need to take care of one more thing: BinOp. 
            //For BinOp which is or-combination of binary operators, we need to either 
            // 1) mark it transient or 2) set flag TermFlags.InheritPrecedence
            // We use first option, making it Transient.  

            // 5. Punctuation and transient terms
            MarkPunctuation("(", ")", "?", ":", "[", "]");
            RegisterBracePair("(", ")");
            RegisterBracePair("[", "]");
            MarkTransient(Term, Expr, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr, ObjectRef);

            // 7. Syntax error reporting
            MarkNotReported("++", "--");
            AddToNoReportGroup("(", "++", "--");
            AddToNoReportGroup(NewLine);
            AddOperatorReportGroup("operator");
            AddTermsReportGroup("assignment operator", "=", "+=", "-=", "*=", "/=");

            //8. Console
            ConsoleTitle = "Irony Expression Evaluator";
            ConsoleGreeting =
      @"Irony Expression Evaluator 

  Supports variable assignments, arithmetic operators (+, -, *, /),
    augmented assignments (+=, -=, etc), prefix/postfix operators ++,--, string operations. 
  Supports big integer arithmetics, string operations.
  Supports strings with embedded expressions : ""name: #{name}""

Press Ctrl-C to exit the program at any time.
";
            ConsolePrompt = "?";
            ConsolePromptMoreInput = "?";

            //9. Language flags. 
            // Automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source
            this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt;
        }
 public override void Init(ParsingContext context, ParseTreeNode treeNode)
 {
     base.Init(context, treeNode);
     _template         = treeNode.Token.ValueString;
     _tokenText        = treeNode.Token.Text;
     _templateSettings = treeNode.Term.AstNodeConfig as StringTemplateSettings;
     ParseSegments(context);
     AsString = "\"" + _template + "\" (templated string)";
 }
        public void StringFromTemplates_calls_defined_functions()
        {
            var settings = new StringTemplateSettings(false)
                           .Replace('0', () => "Aaa")
                           .Replace('1', () => "Bbb");

            var fromTemplate = _randomizer.StringFromTemplate("00,11", settings);

            Assert.AreEqual("AaaAaa,BbbBbb", fromTemplate);
        }
        public void StringFromTemplate_does_not_replace_removed_chars()
        {
            var settings = new StringTemplateSettings()
                           .DoNotReplace("#?*aAnN");

            const string template     = "#?*aAnN";
            var          fromTemplate = _randomizer.StringFromTemplate(template, settings);

            Assert.AreEqual(template, fromTemplate);
        }
        public void StringFromTemplate_replaces_other_chars()
        {
            var settings = new StringTemplateSettings(false)
                           .Replace('.', Chars.Alpha)
                           .Replace('0', Chars.Numeric);

            var fromTemplate = _randomizer.StringFromTemplate("...,000,Hello", settings);

            var parts = fromTemplate.Split(',');

            ContainsNothingBut(parts[0], "abcdefghijklmnopqrstuvwzyxABCDEFGHIJKLMNOPQRSTUVWZYX");
            ContainsNothingBut(parts[1], "0123456789");
            Assert.AreEqual("Hello", parts[2]);
        }
        public void StringFromTemplate_can_return_all_characters()
        {
            var settings = new StringTemplateSettings(false)
                           .Replace('0', Chars.Numeric);

            var fromTemplate = _randomizer.StringFromTemplate(new string('0', 1000), settings);

            HashSet <char> chars = new HashSet <char>(new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' });

            var invalid = fromTemplate.Where(c => !chars.Contains(c)).Distinct().OrderBy(c => c).ToArray();

            Console.WriteLine(fromTemplate);

            Assert.AreEqual(0, invalid.Length, $"Invalid chars found: {string.Join(",", invalid)}");
        }
Exemple #7
0
        public override void Init(Irony.Ast.AstContext context, ParseTreeNode parseNode)
        {
            if (!parseNode.FindTokenAndGetText().StartsWith("$"))
            {
                parseNode.AstNode = new LiteralValueNode();
                ((LiteralValueNode)parseNode.AstNode).Init(context, parseNode);
                return;
            }

            base.Init(context, parseNode);
            template         = parseNode.Token.ValueString;
            tokenText        = parseNode.Token.Text;
            templateSettings = parseNode.Term.AstConfig.Data as StringTemplateSettings;
            ParseSegments(context);
            AsString = "\"" + template + "\" (templated string)";
        }
Exemple #8
0
        public ExpressionEvaluatorGrammar() : base(caseSensitive: false)
        {
            this.GrammarComments =
                @"Irony expression evaluator. Case-insensitive. Supports big integers, float data types, variables, assignments,
arithmetic operations, augmented assignments (+=, -=), inc/dec (++,--), strings with embedded expressions; 
bool operations &,&&, |, ||; ternary '?:' operator.";
            // 1. Terminals
            var number = new NumberLiteral("number");

            //Let's allow big integers (with unlimited number of digits):
            number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt };
            var identifier = new IdentifierTerminal("identifier");
            var comment    = new CommentTerminal("comment", "#", "\n", "\r");

            //comment must be added to NonGrammarTerminals list; it is not used directly in grammar rules,
            // so we add it to this list to let Scanner know that it is also a valid terminal.
            base.NonGrammarTerminals.Add(comment);
            var comma = ToTerm(",");

            //String literal with embedded expressions  ------------------------------------------------------------------
            var stringLit = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate);

            stringLit.AddStartEnd("'", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate);
            stringLit.AstNodeType = typeof(StringTemplateNode);
            var Expr             = new NonTerminal("Expr");      //declare it here to use in template definition
            var templateSettings = new StringTemplateSettings(); //by default set to Ruby-style settings

            templateSettings.ExpressionRoot = Expr;              //this defines how to evaluate expressions inside template
            this.SnippetRoots.Add(Expr);
            stringLit.AstData = templateSettings;
            //--------------------------------------------------------------------------------------------------------

            // 2. Non-terminals
            var Term           = new NonTerminal("Term");
            var BinExpr        = new NonTerminal("BinExpr", typeof(BinaryOperationNode));
            var ParExpr        = new NonTerminal("ParExpr");
            var UnExpr         = new NonTerminal("UnExpr", typeof(UnaryOperationNode));
            var TernaryIfExpr  = new NonTerminal("TernaryIf", typeof(IfNode));
            var ArgList        = new NonTerminal("ArgList", typeof(ExpressionListNode));
            var FunctionCall   = new NonTerminal("FunctionCall", typeof(FunctionCallNode));
            var MemberAccess   = new NonTerminal("MemberAccess", typeof(MemberAccessNode));
            var IndexedAccess  = new NonTerminal("IndexedAccess", typeof(IndexedAccessNode));
            var ObjectRef      = new NonTerminal("ObjectRef"); // foo, foo.bar or f['bar']
            var UnOp           = new NonTerminal("UnOp");
            var BinOp          = new NonTerminal("BinOp", "operator");
            var PrefixIncDec   = new NonTerminal("PrefixIncDec", typeof(IncDecNode));
            var PostfixIncDec  = new NonTerminal("PostfixIncDec", typeof(IncDecNode));
            var IncDecOp       = new NonTerminal("IncDecOp");
            var AssignmentStmt = new NonTerminal("AssignmentStmt", typeof(AssignmentNode));
            var AssignmentOp   = new NonTerminal("AssignmentOp", "assignment operator");
            var Statement      = new NonTerminal("Statement");
            var Program        = new NonTerminal("Program", typeof(StatementListNode));

            // 3. BNF rules
            Expr.Rule           = Term | UnExpr | BinExpr | PrefixIncDec | PostfixIncDec | TernaryIfExpr;
            Term.Rule           = number | ParExpr | stringLit | FunctionCall | identifier | MemberAccess | IndexedAccess;
            ParExpr.Rule        = "(" + Expr + ")";
            UnExpr.Rule         = UnOp + Term + ReduceHere();
            UnOp.Rule           = ToTerm("+") | "-";
            BinExpr.Rule        = Expr + BinOp + Expr;
            BinOp.Rule          = ToTerm("+") | "-" | "*" | "/" | "**" | "==" | "<" | "<=" | ">" | ">=" | "!=" | "&&" | "||" | "&" | "|";
            PrefixIncDec.Rule   = IncDecOp + identifier;
            PostfixIncDec.Rule  = identifier + PreferShiftHere() + IncDecOp;
            IncDecOp.Rule       = ToTerm("++") | "--";
            TernaryIfExpr.Rule  = Expr + "?" + Expr + ":" + Expr;
            MemberAccess.Rule   = Expr + PreferShiftHere() + "." + identifier;
            AssignmentStmt.Rule = ObjectRef + AssignmentOp + Expr;
            AssignmentOp.Rule   = ToTerm("=") | "+=" | "-=" | "*=" | "/=";
            Statement.Rule      = AssignmentStmt | Expr | Empty;
            ArgList.Rule        = MakeStarRule(ArgList, comma, Expr);
            FunctionCall.Rule   = Expr + PreferShiftHere() + "(" + ArgList + ")";
            FunctionCall.NodeCaptionTemplate = "call #{0}(...)";
            ObjectRef.Rule     = identifier | MemberAccess | IndexedAccess;
            IndexedAccess.Rule = Expr + PreferShiftHere() + "[" + Expr + "]";

            Program.Rule = MakePlusRule(Program, NewLine, Statement);

            this.Root = Program; // Set grammar root

            // 4. Operators precedence
            RegisterOperators(10, "?");
            RegisterOperators(15, "&", "&&", "|", "||");
            RegisterOperators(20, "==", "<", "<=", ">", ">=", "!=");
            RegisterOperators(30, "+", "-");
            RegisterOperators(40, "*", "/");
            RegisterOperators(50, Associativity.Right, "**");

            // 5. Punctuation and transient terms
            MarkPunctuation("(", ")", "?", ":", "[", "]");
            RegisterBracePair("(", ")");
            RegisterBracePair("[", "]");
            MarkTransient(Term, Expr, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr, ObjectRef);

            // 7. Syntax error reporting
            MarkNotReported("++", "--");
            AddToNoReportGroup("(", "++", "--");
            AddToNoReportGroup(NewLine);
            AddOperatorReportGroup("operator");
            AddTermsReportGroup("assignment operator", "=", "+=", "-=", "*=", "/=");

            //8. Console
            ConsoleTitle    = "Irony Expression Evaluator";
            ConsoleGreeting =
                @"Irony Expression Evaluator 

  Supports variable assignments, arithmetic operators (+, -, *, /),
    augmented assignments (+=, -=, etc), prefix/postfix operators ++,--, string operations. 
  Supports big integer arithmetics, string operations.
  Supports strings with embedded expressions : ""name: #{name}""

Press Ctrl-C to exit the program at any time.
";
            ConsolePrompt          = "?";
            ConsolePromptMoreInput = "?";

            //9. Language flags.
            // Automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source
            this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt;
        }
Exemple #9
0
        public ExpressionEvaluatorGrammar() : base(false) //false means case insensitive
        {
            this.GrammarComments = @"
Simple expression evaluator. Case-insensitive. Supports big integers and float data types, variables, assignments,
arithmetic operations, augmented assignments (+=, -=), inc/dec (++,--).
Strings with embedded expressions - temporarily added to test this functionality.";
            // 1. Terminals
            var number = new NumberLiteral("number");

            //Let's allow big integers (with unlimited number of digits):
            number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt };
            var identifier = new IdentifierTerminal("identifier");
            var comment    = new CommentTerminal("comment", "#", "\n", "\r");

            //comment must be added to NonGrammarTerminals list; it is not used directly in grammar rules,
            // so we add it to this list to let Scanner know that it is also a valid terminal.
            base.NonGrammarTerminals.Add(comment);

            //String literal with embedded expressions  ------------------------------------------------------------------
            var stringLit        = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate);
            var Expr             = new NonTerminal("Expr");      //declare it here to use in template definition
            var templateSettings = new StringTemplateSettings(); //by default set to Ruby-style settings

            templateSettings.ExpressionRoot = Expr;              //this defines how to evaluate expressions inside template
            this.SnippetRoots.Add(Expr);
            stringLit.AstNodeConfig = templateSettings;
            //--------------------------------------------------------------------------------------------------------

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

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

            this.Root = Program; // Set grammar root

            // 4. Operators precedence
            RegisterOperators(1, "+", "-");
            RegisterOperators(2, "*", "/");
            // 3 is reserved for unary operators
            RegisterOperators(4, Associativity.Right, "**");

            // 5. Punctuation and transient terms
            MarkPunctuation("(", ")");
            RegisterBracePair("(", ")");
            MarkTransient(Term, Expr, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr);
            // The following makes error messages a little cleaner (try evaluating expr 'x y' with and without this line to see the difference)
            MarkNotReported("++", "--");

            //7. Language flags.
            // Automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source
            //this.LanguageFlags = LanguageFlags.CreateAst | LanguageFlags.NewLineBeforeEOF | LanguageFlags.CanRunSample;
            this.LanguageFlags = LanguageFlags.CreateAst | LanguageFlags.CanRunSample;

            //6. Console
            ConsoleTitle    = "Irony Expression Evaluator";
            ConsoleGreeting =
                @"Irony Sample Console for Expression Evaluator 

  Supports variable assignments, arithmetic operators (+, -, *, /),
  augmented assignments (+=, -=, etc), prefix/postfix operators ++,--, string operations. 
  Supports big integer arithmetics, string operations.
  Supports strings with embedded expressions : ""name: #{name}""

Press Ctrl-C to exit the program at any time.
";
            ConsolePrompt          = "?";
            ConsolePromptMoreInput = "?";
        }
    public ExpressionEvaluatorGrammar() : base(false) { //false means case insensitive
      this.GrammarComments =@"
Simple expression evaluator. Case-insensitive. Supports big integers and float data types, variables, assignments,
arithmetic operations, augmented assignments (+=, -=), inc/dec (++,--).
Strings with embedded expressions - temporarily added to test this functionality." ;
      // 1. Terminals
      var number = new NumberLiteral("number");
      //Let's allow big integers (with unlimited number of digits):
      number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt };
      var identifier = new IdentifierTerminal("identifier");
      var comment = new CommentTerminal("comment", "#", "\n", "\r"); 
      //comment must be added to NonGrammarTerminals list; it is not used directly in grammar rules,
      // so we add it to this list to let Scanner know that it is also a valid terminal. 
      base.NonGrammarTerminals.Add(comment);

      //String literal with embedded expressions  ------------------------------------------------------------------
      var stringLit = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); 
      var Expr = new NonTerminal("Expr"); //declare it here to use in template definition 
      var templateSettings = new StringTemplateSettings(); //by default set to Ruby-style settings 
      templateSettings.ExpressionRoot = Expr; //this defines how to evaluate expressions inside template
      this.SnippetRoots.Add(Expr);
      stringLit.AstNodeConfig = templateSettings;
      //--------------------------------------------------------------------------------------------------------

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

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

      this.Root = Program;       // Set grammar root

      // 4. Operators precedence
      RegisterOperators(1, "+", "-");
      RegisterOperators(2, "*", "/");
      // 3 is reserved for unary operators
      RegisterOperators(4, Associativity.Right, "**");

      // 5. Punctuation and transient terms
      MarkPunctuation("(", ")");
      RegisterBracePair("(", ")");
      MarkTransient(Term, Expr, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr);
      // The following makes error messages a little cleaner (try evaluating expr 'x y' with and without this line to see the difference)
      MarkNotReported("++", "--"); 

      //7. Language flags. 
      // Automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source
      //this.LanguageFlags = LanguageFlags.CreateAst | LanguageFlags.NewLineBeforeEOF | LanguageFlags.CanRunSample; 
      this.LanguageFlags = LanguageFlags.CreateAst | LanguageFlags.CanRunSample; 

      //6. Console
      ConsoleTitle = "Irony Expression Evaluator";
      ConsoleGreeting =
@"Irony Sample Console for Expression Evaluator 

  Supports variable assignments, arithmetic operators (+, -, *, /),
  augmented assignments (+=, -=, etc), prefix/postfix operators ++,--, string operations. 
  Supports big integer arithmetics, string operations.
  Supports strings with embedded expressions : ""name: #{name}""

Press Ctrl-C to exit the program at any time.
";
      ConsolePrompt = "?";
      ConsolePromptMoreInput = "?"; 
    }
        public LabGrammar() : base(false)
        {
            var numberLiteral = new NumberLiteral("number")
            {
                DefaultIntTypes = new TypeCode[1] {
                    TypeCode.Double
                }
            };
            var identifierTerminal = new IdentifierTerminal("identifier");

            NonGrammarTerminals.Add(new CommentTerminal("comment", "#", "\n", "\r"));
            KeyTerm term          = ToTerm(",");
            var     stringLiteral =
                new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate);

            stringLiteral.AddStartEnd("'", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate);
            stringLiteral.AstConfig.NodeType = typeof(StringTemplateNode);
            var nonTerminal1     = new NonTerminal("Expr");
            var templateSettings = new StringTemplateSettings {
                ExpressionRoot = nonTerminal1
            };

            SnippetRoots.Add(nonTerminal1);
            stringLiteral.AstConfig.Data = templateSettings;
            var nonTerminal2     = new NonTerminal("Term");
            var nonTerminal3     = new NonTerminal("BinExpr", typeof(BinaryOperationNode));
            var nonTerminal4     = new NonTerminal("ParExpr");
            var nonTerminal5     = new NonTerminal("UnExpr", typeof(UnaryOperationNode));
            var nonTerminal6     = new NonTerminal("TernaryIf", typeof(IfNode));
            var listNonTerminal1 = new NonTerminal("ArgList", typeof(ExpressionListNode));
            var nonTerminal7     = new NonTerminal("FunctionCall", typeof(FunctionCallNode));
            var nonTerminal8     = new NonTerminal("MemberAccess", typeof(MemberAccessNode));
            var nonTerminal9     = new NonTerminal("IndexedAccess", typeof(IndexedAccessNode));
            var nonTerminal10    = new NonTerminal("ObjectRef");
            var nonTerminal11    = new NonTerminal("UnOp");
            var nonTerminal12    = new NonTerminal("BinOp", "operator");
            var nonTerminal13    = new NonTerminal("PrefixIncDec", typeof(IncDecNode));
            var nonTerminal14    = new NonTerminal("PostfixIncDec", typeof(IncDecNode));
            var nonTerminal15    = new NonTerminal("IncDecOp");
            var nonTerminal16    = new NonTerminal("AssignmentStmt", typeof(AssignmentNode));
            var nonTerminal17    = new NonTerminal("AssignmentOp", "assignment operator");
            var nonTerminal18    = new NonTerminal("Statement");
            var listNonTerminal2 = new NonTerminal("Program", typeof(StatementListNode));

            nonTerminal1.Rule =
                nonTerminal2 | nonTerminal5 |
                nonTerminal3 | nonTerminal13 |
                nonTerminal14 | nonTerminal6;
            nonTerminal2.Rule =
                numberLiteral | nonTerminal4 |
                stringLiteral | nonTerminal7 |
                identifierTerminal | nonTerminal8 | nonTerminal9;
            nonTerminal4.Rule = "(" + nonTerminal1 + ")";
            nonTerminal5.Rule = nonTerminal11 + nonTerminal2 +
                                ReduceHere();
            nonTerminal11.Rule = ToTerm("+") | "-" | "!";
            nonTerminal3.Rule  = nonTerminal1 + nonTerminal12 + nonTerminal1;
            nonTerminal12.Rule =
                ToTerm("+") |
                "-" | "*" |
                "/" | "**" | "==" | "<" | "<=" |
                ">" | ">=" | "!=" | "&&" | "||" | "&" | "|";
            nonTerminal13.Rule = nonTerminal15 + identifierTerminal;
            nonTerminal14.Rule = identifierTerminal + PreferShiftHere() +
                                 nonTerminal15;
            nonTerminal15.Rule = ToTerm("++") | "--";
            nonTerminal6.Rule  =
                nonTerminal1 + "?" + nonTerminal1 + ":" +
                nonTerminal1;
            nonTerminal8.Rule =
                nonTerminal1 + PreferShiftHere() + "." +
                identifierTerminal;
            nonTerminal16.Rule = nonTerminal10 + nonTerminal17 + nonTerminal1;
            nonTerminal17.Rule = ToTerm("=") | "+=" | "-=" | "*=" |
                                 "/=";
            nonTerminal18.Rule    = nonTerminal16 | nonTerminal1 | Empty;
            listNonTerminal1.Rule = MakeStarRule(listNonTerminal1, term, nonTerminal1);
            nonTerminal7.Rule     =
                nonTerminal1 + PreferShiftHere() + "(" +
                listNonTerminal1 + ")";
            nonTerminal7.NodeCaptionTemplate = "call #{0}(...)";
            nonTerminal10.Rule = identifierTerminal | nonTerminal8 |
                                 nonTerminal9;
            nonTerminal9.Rule =
                nonTerminal1 + PreferShiftHere() + "[" +
                nonTerminal1 + "]";
            listNonTerminal2.Rule =
                MakePlusRule(listNonTerminal2, NewLine, nonTerminal18);
            Root = listNonTerminal2;
            RegisterOperators(10, "?");
            RegisterOperators(15, "&", "&&", "|", "||");
            RegisterOperators(20, "==", "<", "<=", ">", ">=", "!=");
            RegisterOperators(30, "+", "-");
            RegisterOperators(40, "*", "/");
            RegisterOperators(50, Associativity.Right, "**");
            RegisterOperators(60, "!");
            MarkPunctuation("(", ")", "?", ":", "[", "]");
            RegisterBracePair("(", ")");
            RegisterBracePair("[", "]");
            MarkTransient(nonTerminal2, nonTerminal1, nonTerminal18, nonTerminal12, nonTerminal11, nonTerminal15,
                          nonTerminal17, nonTerminal4, nonTerminal10);
            MarkNotReported("++", "--");
            AddToNoReportGroup("(", "++", "--");
            AddToNoReportGroup(NewLine);
            AddOperatorReportGroup("operator");
            AddTermsReportGroup("assignment operator", "=", "+=", "-=", "*=", "/=");

            LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt;
        }
Exemple #12
0
        public CalcGrammar() : base(true)
        {
            var comment      = new CommentTerminal("comment", "//", "\n", "\r");
            var blockComment = new CommentTerminal("blockComment", "/*", "*/");

            NonGrammarTerminals.Add(comment);
            NonGrammarTerminals.Add(blockComment);

            NonTerminal start                   = new NonTerminal("start", typeof(StatementListNode));
            NonTerminal block                   = new NonTerminal("block");
            NonTerminal instructions            = new NonTerminal("instructions", typeof(BlockNode));
            NonTerminal instruction             = new NonTerminal("instruction");
            NonTerminal embeddedInstruction     = new NonTerminal("embeddedInstruction");
            NonTerminal ifClause                = new NonTerminal("ifClause", typeof(IfNode));
            NonTerminal ifElseClause            = new NonTerminal("ifElseClause", typeof(IfNode));
            NonTerminal forClause               = new NonTerminal("forClause", typeof(ForNode));
            NonTerminal forInitClause           = new NonTerminal("forInit", typeof(StatementListNode));
            NonTerminal forConditionClause      = new NonTerminal("forCondition");
            NonTerminal forIterClause           = new NonTerminal("forIter", typeof(StatementListNode));
            NonTerminal foreachClause           = new NonTerminal("foreachClause", typeof(ForeachNode));
            NonTerminal foreachVarDecl          = new NonTerminal("foreachVarDecl");
            NonTerminal whileClause             = new NonTerminal("whileClause", typeof(WhileNode));
            NonTerminal doWhileClause           = new NonTerminal("doWhileClause", typeof(DoWhileNode));
            NonTerminal returnClause            = new NonTerminal("returnClause", typeof(ReturnNode));
            NonTerminal emptyReturnClause       = new NonTerminal("emptyReturnClause", typeof(ReturnNode));
            NonTerminal breakClause             = new NonTerminal("breakClause", typeof(BreakNode));
            NonTerminal continueClause          = new NonTerminal("continueClause", typeof(ContinueNode));
            NonTerminal usingClause             = new NonTerminal("usingClause", typeof(UsingNode));
            NonTerminal usingNamespace          = new NonTerminal("namespace", typeof(UsingNamespaceNode));
            NonTerminal tryClause               = new NonTerminal("tryClause", typeof(TryNode));
            NonTerminal catchClause             = new NonTerminal("catchClause", typeof(CatchNode));
            NonTerminal finallyClause           = new NonTerminal("finallyClause");
            NonTerminal throwClause             = new NonTerminal("throwClause", typeof(ThrowNode));
            NonTerminal assignment              = new NonTerminal("assignment", typeof(AssignmentNode));
            NonTerminal assignmentOp            = new NonTerminal("assignmentOp", "assignment operator");
            NonTerminal varDeclaration          = new NonTerminal("varDeclaration", typeof(VarDeclarationNode));
            NonTerminal varDeclarationAndAssign = new NonTerminal("varDeclaration", typeof(VarDeclarationNode));
            NonTerminal functionDef             = new NonTerminal("functionDef", typeof(FunctionDefNode));
            NonTerminal functionBody            = new NonTerminal("functionBody", typeof(StatementListNode));
            NonTerminal lambdaBody              = new NonTerminal("lambdaBody", typeof(StatementListNode));
            NonTerminal inlineFunctionDef       = new NonTerminal("inlineFunctionDef", typeof(LambdaNode));
            NonTerminal externFunctionDef       = new NonTerminal("externFunctionDef", typeof(ExternFunctionNode));
            NonTerminal paramList               = new NonTerminal("paramList", typeof(ParamListNode));
            NonTerminal param                   = new NonTerminal("param", typeof(ParamNode));
            NonTerminal lambdaParamList         = new NonTerminal("lambdaParamList", typeof(ParamListNode));
            NonTerminal singleLambdaParamList   = new NonTerminal("lambdaParamList", typeof(ParamListNode));
            NonTerminal lambdaParam             = new NonTerminal("lambdaParam", typeof(ParamNode));
            NonTerminal paramsOrEmpty           = new NonTerminal("paramsOrEmpty");
            NonTerminal arrayDef                = new NonTerminal("arrayDef");
            NonTerminal arrayDefList            = new NonTerminal("arrayDefList", typeof(ArrayDefNode));
            NonTerminal arrayDefListItem        = new NonTerminal("arrayDefListItem");
            NonTerminal namedArrayItem          = new NonTerminal("namedArrayItem", typeof(NamedArrayItemNode));
            NonTerminal expr                   = new NonTerminal("expr");
            NonTerminal prefixExpr             = new NonTerminal("prefixExpr", typeof(IncDecNode));
            NonTerminal postfixExpr            = new NonTerminal("postfixExpr", typeof(IncDecNode));
            NonTerminal binExpr                = new NonTerminal("binExpr", typeof(BinaryOperationNode));
            NonTerminal unExpr                 = new NonTerminal("unExpr", typeof(UnaryExpressionNode));
            NonTerminal var                    = new NonTerminal("var");
            NonTerminal objRef                 = new NonTerminal("objRef");
            NonTerminal memberAccess           = new NonTerminal("memberAccess", typeof(MemberAccessNode));
            NonTerminal ternaryIf              = new NonTerminal("ternaryIf", typeof(IfNode));
            NonTerminal coalescence            = new NonTerminal("coalescence", typeof(CoalescenceNode));
            NonTerminal functionCall           = new NonTerminal("functionCall", typeof(FunctionCallNode));
            NonTerminal varList                = new NonTerminal("varList", typeof(ExpressionListNode));
            NonTerminal array                  = new NonTerminal("array");
            NonTerminal singleDimArray         = new NonTerminal("singleDimArray", typeof(IndexedAccessNode));
            NonTerminal rangeArrayDef          = new NonTerminal("rangeArrayDef", typeof(RangeArrayDefNode));
            NonTerminal rangeInclusiveArrayDef = new NonTerminal("rangeInclusiveArrayDef", typeof(RangeArrayDefNode));
            NonTerminal typeInfo               = new NonTerminal("typeInfo");
            NonTerminal typeInfoOrEmpty        = new NonTerminal("typeInfoOrEmpty");

            IdentifierTerminal name    = new IdentifierTerminal("name", IdOptions.IsNotKeyword);
            IdentifierTerminal newName = new IdentifierTerminal("newName", IdOptions.IsNotKeyword);
            NumberLiteral      number  = new NumberLiteral("number", NumberOptions.AllowUnderscore);

            StringLiteral _string = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes);

            StringLiteral _char = new StringLiteral("Char", "'", StringOptions.IsChar | StringOptions.AllowsAllEscapes);

            NonTerminal boolVal  = new NonTerminal("boolVal", typeof(BoolValNode));
            NonTerminal nullVal  = new NonTerminal("nullVal", typeof(NullValueNode));
            NonTerminal thisVal  = new NonTerminal("thisVal", typeof(ThisNode));
            NonTerminal binOp    = new NonTerminal("binOp", "operator");
            NonTerminal unaryOp  = new NonTerminal("unaryOp", "operator");
            NonTerminal incDecOp = new NonTerminal("incDecOp", "operator");

            NonTerminal emptyInstruction = new NonTerminal("emptyInstruction", typeof(EmptyNode));

            start.Rule        = MakeStarRule(start, instruction);
            block.Rule        = "{" + instructions + "}";
            instructions.Rule = MakeStarRule(instructions, instruction);
            instruction.Rule  = block
                                | embeddedInstruction + ";"
                                | ifClause
                                | ifElseClause
                                | functionDef
                                | externFunctionDef + ";"
                                | returnClause + ";"
                                | emptyReturnClause
                                | breakClause
                                | continueClause
                                | forClause
                                | foreachClause
                                | whileClause
                                | doWhileClause
                                | usingClause
                                | varDeclaration + ";"
                                | emptyInstruction
                                | tryClause
                                | throwClause + ";";
            emptyInstruction.Rule    = ToTerm(";");
            instruction.ErrorRule    = SyntaxError + ";";
            embeddedInstruction.Rule = functionCall | postfixExpr | prefixExpr | assignment | varDeclarationAndAssign;
            ifElseClause.Rule        = ToTerm("if") + "(" + expr + ")" + instruction
                                       + PreferShiftHere() + "else" + instruction;
            ifClause.Rule           = ToTerm("if") + "(" + expr + ")" + instruction;
            forClause.Rule          = ToTerm("for") + "(" + forInitClause + ";" + forConditionClause + ";" + forIterClause + ")" + instruction;
            forInitClause.Rule      = MakeStarRule(forInitClause, ToTerm(","), embeddedInstruction);
            forConditionClause.Rule = Empty | expr;
            forIterClause.Rule      = MakeStarRule(forIterClause, ToTerm(","), embeddedInstruction);
            foreachClause.Rule      = ToTerm("foreach") + "(" + foreachVarDecl + "in" + expr + ")" + instruction;
            foreachVarDecl.Rule     = varDeclaration | name;
            whileClause.Rule        = ToTerm("while") + "(" + expr + ")" + instruction;
            doWhileClause.Rule      = ToTerm("do") + instruction + ToTerm("while") + "(" + expr + ")" + ToTerm(";");
            returnClause.Rule       = "return" + expr;
            emptyReturnClause.Rule  = ToTerm("return") + ";";
            breakClause.Rule        = ToTerm("break") + ";";
            continueClause.Rule     = ToTerm("continue") + ";";

            tryClause.Rule = "try" + block + (catchClause + finallyClause | finallyClause | catchClause);

            catchClause.Rule   = "catch" + ("(" + name + ")").Q() + block;
            finallyClause.Rule = "finally" + block;

            throwClause.Rule = "throw" + expr;

            usingClause.Rule = ToTerm("using") + usingNamespace + ";";

            usingNamespace.Rule = (name + "." + usingNamespace) | name;

            varDeclaration.Rule          = "var" + name + typeInfoOrEmpty;
            varDeclarationAndAssign.Rule = "var" + name + typeInfoOrEmpty + "=" + expr;

            assignment.Rule   = objRef + assignmentOp + expr;
            assignmentOp.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/=" | "%=" | "|=" | "^=" | "&=" | "<<=" | ">>=" | "**=";
            objRef.Rule       = name | array | memberAccess;
            memberAccess.Rule = var + PreferShiftHere() + "." + name;

            functionDef.Rule = "function" + name + "(" + paramList + ")" + ToTerm("extension").Q() + functionBody;
            functionDef.NodeCaptionTemplate = "function #{0}(...)";
            inlineFunctionDef.Rule          = (ToTerm("function") + "(" + paramList + ")" + functionBody)
                                              | ("(" + lambdaParamList + ")" + ToTerm("=>") + expr)
                                              | (singleLambdaParamList + "=>" + expr);
            externFunctionDef.Rule = ToTerm("extern") + "function" + name + "(" + paramList + ")" + ToTerm("extension").Q();
            inlineFunctionDef.NodeCaptionTemplate = "function(...)";
            functionBody.Rule = block | returnClause;

            paramList.Rule             = MakeStarRule(paramList, ToTerm(","), param);
            lambdaParamList.Rule       = MakeStarRule(lambdaParamList, ToTerm(","), lambdaParam);
            singleLambdaParamList.Rule = lambdaParam;

            lambdaParam.Rule   = name + ReduceIf("=>", "+", "-", "*", "/", "%", "**", "&", "&&", "|", "||", "^", "==", "<=", ">=", "<", ">", "!=", "<<", ">>", ";", "(", "??");
            param.Rule         = paramsOrEmpty + name + typeInfoOrEmpty;
            paramsOrEmpty.Rule = ToTerm("params") | Empty;

            arrayDef.Rule         = "{" + arrayDefList + "}";
            arrayDefList.Rule     = MakeStarRule(arrayDefList, ToTerm(","), arrayDefListItem);
            arrayDefListItem.Rule = namedArrayItem | expr;
            namedArrayItem.Rule   = (name + ReduceHere() | _string) + "=" + expr;

            rangeArrayDef.Rule = expr + PreferShiftHere() + ".." + expr + ((PreferShiftHere() + ":" + expr) | Empty);

            rangeInclusiveArrayDef.Rule = expr + PreferShiftHere() + "..." + expr + ((PreferShiftHere() + ":" + expr) | Empty);

            expr.Rule = prefixExpr | postfixExpr | ternaryIf
                        | inlineFunctionDef
                        | var | unExpr | binExpr
                        | arrayDef
                        | rangeArrayDef
                        | rangeInclusiveArrayDef
                        | assignment
                        | coalescence;

            coalescence.Rule = expr + "??" + expr;

            binExpr.Rule = expr + binOp + expr;
            binOp.Rule   = ToTerm("&&") | "||" | "&" | "|" | "^"
                           | ToTerm("==") | "<=" | ">=" | "<" | ">" | "!="
                           | ToTerm("+") | "-"
                           | ToTerm("*") | "/" | "%" | "**"
                           | ToTerm("<<") | ">>";
            prefixExpr.Rule  = incDecOp + objRef + ReduceHere();
            postfixExpr.Rule = objRef + PreferShiftHere() + incDecOp;
            unExpr.Rule      = unaryOp + expr + ReduceHere();

            var.Rule = objRef
                       | number
                       | boolVal
                       | nullVal
                       | thisVal
                       | _string
                       | _char
                       | functionCall + ReduceHere()
                       | ("(" + expr + ")");

            ternaryIf.Rule    = expr + "?" + expr + ":" + expr;
            functionCall.Rule = var + PreferShiftHere() + "(" + varList + ")";
            functionCall.NodeCaptionTemplate = "call #{0}(...)";
            varList.Rule = MakeStarRule(varList, ToTerm(","), expr);

            array.Rule          = singleDimArray;
            singleDimArray.Rule = var + PreferShiftHere() + "[" + expr + "]";

            boolVal.Rule = ToTerm("true") | "false";
            nullVal.Rule = ToTerm("null");
            thisVal.Rule = ToTerm("this");

            typeInfoOrEmpty.Rule = ":" + typeInfo | Empty;
            typeInfo.Rule        = ToTerm("string")
                                   | "function"
                                   | "number"
                                   | "bool"
                                   | "table"
                                   | "char";


            unaryOp.Rule  = ToTerm("-") | "!" | "~";
            incDecOp.Rule = ToTerm("++") | "--";

            MarkPunctuation("(", ")", "?", ":", "[", "]", ";", "{", "}", ".", ",", "@", "=>", "??",
                            "return", "if", "else", "for", "while", "break", "continue",
                            "using", "do", "var", "foreach", "in",
                            "try", "catch", "finally", "throw", "extern");
            RegisterBracePair("(", ")");
            RegisterBracePair("[", "]");
            RegisterBracePair("{", "}");

            RegisterOperators(10, "?");
            RegisterOperators(15, "&&", "||", "&", "|", "^");
            RegisterOperators(20, "==", "<", "<=", ">", ">=", "!=");
            RegisterOperators(25, "<<", ">>");
            RegisterOperators(30, "+", "-");
            RegisterOperators(40, "*", "/", "%", "**");
            RegisterOperators(60, "!", "~");
            RegisterOperators(70, "++", "--", "??");
            MarkTransient(var, expr, binOp, unaryOp, block, instruction, embeddedInstruction, objRef, array, arrayDef, assignmentOp, arrayDefListItem, incDecOp, functionBody, lambdaBody, foreachVarDecl, paramsOrEmpty, typeInfoOrEmpty);

            AddTermsReportGroup("assignment", "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>=");
            AddTermsReportGroup("statement", "if", "while", "for", "return", "break", "continue", "using", "do", "try", "throw", "foreach");
            AddTermsReportGroup("variable declaration", "var");
            AddTermsReportGroup("function declaration", "function", "extern");
            AddTermsReportGroup("constant", number, _string, _char);
            AddTermsReportGroup("constant", "null", "false", "true", "this", "@");
            AddTermsReportGroup("unary operator", "+", "-", "!");
            AddTermsReportGroup("operator", "+", "-", "*", "/", "%", "**", "&", "&&", "|", "||", "^", "?", "==", "<=", "<", ">=", ">", "!=", "<<", ">>", "??", "..");
            AddToNoReportGroup("(", "[", "{", ".", ",", "++", "--");

            MarkReservedWords("if", "else", "return", "function", "while",
                              "for", "null", "false", "true", "this", "break", "continue",
                              "using", "do", "var", "foreach", "in", "params",
                              "try", "catch", "finally", "throw", "extern");

            number.DefaultFloatType = TypeCode.Double;
            number.DefaultIntTypes  = new TypeCode[] { TypeCode.Int64 };
            number.AddPrefix("0x", NumberOptions.Hex);
            number.AddPrefix("0b", NumberOptions.Binary);
            number.AddSuffix("d", TypeCode.Double);
            number.AddSuffix("l", TypeCode.Int64);
            number.AddSuffix("m", TypeCode.Decimal);

            _string.AddPrefix("@", StringOptions.NoEscapes);
            _string.AddPrefix("$", StringOptions.IsTemplate | StringOptions.AllowsAllEscapes);

            var stringTemplateSettings = new StringTemplateSettings();

            stringTemplateSettings.StartTag       = "{";
            stringTemplateSettings.EndTag         = "}";
            stringTemplateSettings.ExpressionRoot = expr;
            this.SnippetRoots.Add(expr);
            _string.AstConfig.NodeType = typeof(StringTemplateNode);
            _string.AstConfig.Data     = stringTemplateSettings;

            this.Root = start;

            this.LanguageFlags = LanguageFlags.CreateAst;
        }