Ирония - SampleExpressionEvaluator 1.0 - Где определяется символ "iff"? - PullRequest
0 голосов
/ 12 октября 2019

Я использую Grammar Explorer, предоставляемый в репозитории Irony. Я пытаюсь понять, как все работает. Я смущен. Я не могу найти, где символ iff определен в SampleExpressionEvaluator 1.0 Sample - "testlif.txt"

iif(1 > 0, "true", 1/0) + ", " + (1 > 0 ? "true" : 1/0) # expected: true, true

, если я изменю iff на blah Iполучить Error: Unknown symbol 'blah'. At (4:1)., что заставляет меня предположить, что iff определено где-то, я просто не могу понять, где.

вот определение грамматики

[Language("ExpressionEvaluator", "1.0", "Multi-line expression evaluator")]
  public class ExpressionEvaluatorGrammar : InterpretedLanguageGrammar {
    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;
    }

Я ищу, чтобы разобратьсуществующий проприетарный язык строковых выражений. Этот образец, кажется, наиболее актуален, но этот образец меня озадачивает.

Пример строкового литерала будет Hello I am Feeling {IF(boolMoodIsGood = True, "Good","Bad")} Если boolMoodIsGood имеет значение true, результат будет Hello I am Feeling Good иначе Hello I am Feeling Bad

но на самом деле мне не нужно оценивать выражение, мне просто нужно разобрать его и получить дерево выражений.

...