#region License Information /* HeuristicLab * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using Irony.Interpreter; using Irony.Interpreter.Ast; using Irony.Parsing; namespace HeuristicLab.BenchmarkGenerator { public class ExpressionGrammar : InterpretedLanguageGrammar { public ExpressionGrammar() : this(caseSensitive: false) { } public ExpressionGrammar(bool caseSensitive) : base(caseSensitive) { var comma = ToTerm(","); // Define terminals var number = new NumberLiteral("Number") { DefaultIntTypes = new[] { TypeCode.Double }, // DefaultIntTypes = new[] { TypeCode.Int32, TypeCode.Int64 }, DefaultFloatType = TypeCode.Double }; var identifier = new IdentifierTerminal("Identifier"); // Define non-terminals var term = new NonTerminal("Term"); var binExpr = new NonTerminal("BinExpr", typeof(BinaryOperationNode)); var binOp = new NonTerminal("BinOp", "operator"); var unExpr = new NonTerminal("UnExpr", typeof(UnaryOperationNode)); var unOp = new NonTerminal("UnOp", "operator"); var expr = new NonTerminal("Expr"); var argList = new NonTerminal("ArgList", typeof(ExpressionListNode)); var functionCall = new NonTerminal("FunctionCall", typeof(FunctionCallNode)); var parExpr = new NonTerminal("ParExpr"); var statement = new NonTerminal("Statement"); var assignmentStmt = new NonTerminal("AssignmentStmt", typeof(AssignmentNode)); var assignmentOp = new NonTerminal("AssignmentOp", "assignment operator"); var program = new NonTerminal("Program", typeof(StatementListNode)); // BNF rules expr.Rule = term | unExpr | binExpr; term.Rule = number | parExpr | identifier | functionCall; parExpr.Rule = "(" + expr + ")"; unExpr.Rule = unOp + term; unOp.Rule = ToTerm("+") | "-"; binExpr.Rule = expr + binOp + expr; binOp.Rule = ToTerm("+") | "-" | "*" | "/" | "^"; // add, sub, mul, div, pow argList.Rule = MakeStarRule(argList, comma, expr); functionCall.Rule = identifier + PreferShiftHere() + "(" + argList + ")"; assignmentStmt.Rule = identifier + assignmentOp + expr; assignmentOp.Rule = ToTerm("="); statement.Rule = assignmentStmt | expr | Empty; program.Rule = MakePlusRule(program, NewLine, statement); this.Root = program; // Caption templates functionCall.NodeCaptionTemplate = "call #{0}(...)"; // Operators precedence RegisterOperators(1, "+", "-"); RegisterOperators(2, "*", "/"); RegisterOperators(3, Associativity.Right, "^"); // Punctuation and braces MarkPunctuation("(", ")", "[", "]"); RegisterBracePair("(", ")"); RegisterBracePair("[", "]"); // Mark transient because these don't have corresponding AST nodes MarkTransient(term, expr, statement, binOp, unOp, assignmentOp, parExpr); // Language flags LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.CreateAst; } public override LanguageRuntime CreateRuntime(LanguageData data) { return new CustomLanguageRuntime(data); } } }