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)}"); }
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)"; }
public ExpressionEvaluatorGrammar() : base(caseSensitive: false) { this.GrammarComments = @"Irony expression evaluator. Case-insensitive. Supports big integers, float data types, variables, assignments, arithmetic operations, augmented assignments (+=, -=), inc/dec (++,--), strings with embedded expressions; bool operations &,&&, |, ||; ternary '?:' operator."; // 1. Terminals var number = new NumberLiteral("number"); //Let's allow big integers (with unlimited number of digits): number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt }; var identifier = new IdentifierTerminal("identifier"); var comment = new CommentTerminal("comment", "#", "\n", "\r"); //comment must be added to NonGrammarTerminals list; it is not used directly in grammar rules, // so we add it to this list to let Scanner know that it is also a valid terminal. base.NonGrammarTerminals.Add(comment); var comma = ToTerm(","); //String literal with embedded expressions ------------------------------------------------------------------ var stringLit = new StringLiteral("string", "\"", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLit.AddStartEnd("'", StringOptions.AllowsAllEscapes | StringOptions.IsTemplate); stringLit.AstNodeType = typeof(StringTemplateNode); var Expr = new NonTerminal("Expr"); //declare it here to use in template definition var templateSettings = new StringTemplateSettings(); //by default set to Ruby-style settings templateSettings.ExpressionRoot = Expr; //this defines how to evaluate expressions inside template this.SnippetRoots.Add(Expr); stringLit.AstData = templateSettings; //-------------------------------------------------------------------------------------------------------- // 2. Non-terminals var Term = new NonTerminal("Term"); var BinExpr = new NonTerminal("BinExpr", typeof(BinaryOperationNode)); var ParExpr = new NonTerminal("ParExpr"); var UnExpr = new NonTerminal("UnExpr", typeof(UnaryOperationNode)); var TernaryIfExpr = new NonTerminal("TernaryIf", typeof(IfNode)); var ArgList = new NonTerminal("ArgList", typeof(ExpressionListNode)); var FunctionCall = new NonTerminal("FunctionCall", typeof(FunctionCallNode)); var MemberAccess = new NonTerminal("MemberAccess", typeof(MemberAccessNode)); var IndexedAccess = new NonTerminal("IndexedAccess", typeof(IndexedAccessNode)); var ObjectRef = new NonTerminal("ObjectRef"); // foo, foo.bar or f['bar'] var UnOp = new NonTerminal("UnOp"); var BinOp = new NonTerminal("BinOp", "operator"); var PrefixIncDec = new NonTerminal("PrefixIncDec", typeof(IncDecNode)); var PostfixIncDec = new NonTerminal("PostfixIncDec", typeof(IncDecNode)); var IncDecOp = new NonTerminal("IncDecOp"); var AssignmentStmt = new NonTerminal("AssignmentStmt", typeof(AssignmentNode)); var AssignmentOp = new NonTerminal("AssignmentOp", "assignment operator"); var Statement = new NonTerminal("Statement"); var Program = new NonTerminal("Program", typeof(StatementListNode)); // 3. BNF rules Expr.Rule = Term | UnExpr | BinExpr | PrefixIncDec | PostfixIncDec | TernaryIfExpr; Term.Rule = number | ParExpr | stringLit | FunctionCall | identifier | MemberAccess | IndexedAccess; ParExpr.Rule = "(" + Expr + ")"; UnExpr.Rule = UnOp + Term + ReduceHere(); UnOp.Rule = ToTerm("+") | "-"; BinExpr.Rule = Expr + BinOp + Expr; BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**" | "==" | "<" | "<=" | ">" | ">=" | "!=" | "&&" | "||" | "&" | "|"; PrefixIncDec.Rule = IncDecOp + identifier; PostfixIncDec.Rule = identifier + PreferShiftHere() + IncDecOp; IncDecOp.Rule = ToTerm("++") | "--"; TernaryIfExpr.Rule = Expr + "?" + Expr + ":" + Expr; MemberAccess.Rule = Expr + PreferShiftHere() + "." + identifier; AssignmentStmt.Rule = ObjectRef + AssignmentOp + Expr; AssignmentOp.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/="; Statement.Rule = AssignmentStmt | Expr | Empty; ArgList.Rule = MakeStarRule(ArgList, comma, Expr); FunctionCall.Rule = Expr + PreferShiftHere() + "(" + ArgList + ")"; FunctionCall.NodeCaptionTemplate = "call #{0}(...)"; ObjectRef.Rule = identifier | MemberAccess | IndexedAccess; IndexedAccess.Rule = Expr + PreferShiftHere() + "[" + Expr + "]"; Program.Rule = MakePlusRule(Program, NewLine, Statement); this.Root = Program; // Set grammar root // 4. Operators precedence RegisterOperators(10, "?"); RegisterOperators(15, "&", "&&", "|", "||"); RegisterOperators(20, "==", "<", "<=", ">", ">=", "!="); RegisterOperators(30, "+", "-"); RegisterOperators(40, "*", "/"); RegisterOperators(50, Associativity.Right, "**"); // 5. Punctuation and transient terms MarkPunctuation("(", ")", "?", ":", "[", "]"); RegisterBracePair("(", ")"); RegisterBracePair("[", "]"); MarkTransient(Term, Expr, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr, ObjectRef); // 7. Syntax error reporting MarkNotReported("++", "--"); AddToNoReportGroup("(", "++", "--"); AddToNoReportGroup(NewLine); AddOperatorReportGroup("operator"); AddTermsReportGroup("assignment operator", "=", "+=", "-=", "*=", "/="); //8. Console ConsoleTitle = "Irony Expression Evaluator"; ConsoleGreeting = @"Irony Expression Evaluator Supports variable assignments, arithmetic operators (+, -, *, /), augmented assignments (+=, -=, etc), prefix/postfix operators ++,--, string operations. Supports big integer arithmetics, string operations. Supports strings with embedded expressions : ""name: #{name}"" Press Ctrl-C to exit the program at any time. "; ConsolePrompt = "?"; ConsolePromptMoreInput = "?"; //9. Language flags. // Automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst | LanguageFlags.SupportsBigInt; }
public 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; }
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; }