probleme with this grammar

Apr 5, 2012 at 12:37 PM

 I have a sample grammar, and when I add the method SkipWhitespace(ISourceStream source) I detect an exception "Root AstNode is null, cannot evaluate script. Create Ast tree first"

 

public class MohanedEvaluatorGrammar : InterpretedLanguageGrammar
    {
        public MohanedEvaluatorGrammar()
            : 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.";
            CommentTerminal SingleLineComment = new CommentTerminal("SingleLineComment", "//", "\r", "\n", "\u2085", "\u2028", "\u2029");
            CommentTerminal DelimitedComment = new CommentTerminal("DelimitedComment", "/*", "*/");
            NonGrammarTerminals.Add(SingleLineComment);
            NonGrammarTerminals.Add(DelimitedComment);
            //Temporarily, treat preprocessor instructions like comments
            CommentTerminal ppInstruction = new CommentTerminal("ppInstruction", "#", "\n");
            NonGrammarTerminals.Add(ppInstruction);


            // 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 identifierArray = new IdentifierTerminal("identifierArray");
            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(",");

            //symbol
            KeyTerm begin = ToTerm("begin");
            KeyTerm end = ToTerm("end");
            KeyTerm iif = ToTerm("if");
            KeyTerm eelse = ToTerm("else");


            //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 TernaryIfExpr = new NonTerminal("TernaryIf", typeof(IfNode));
            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 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");
            var exprRandom = new NonTerminal("exprRandom", typeof(RandomNode));
            var blockIfElse = new NonTerminal("blockIfElse", typeof(BlockIfElseNode));
            var listStatement = new NonTerminal("listStatement", typeof(StatementListNode));
            var createInstance = new NonTerminal("createInstance", typeof(CreateInstanceNode));
            var exprSet = new NonTerminal("exprSet", typeof(ExprSetNode));
            var set = new NonTerminal("set", typeof(SetNode));
            var whileClass = new NonTerminal("whileClass", typeof(WhileClassNode));
            var Change = new NonTerminal("Change", typeof(ChangeNode));
            var exprClass = new NonTerminal("exprClass");
            var term1 = new NonTerminal("term1", typeof(TermNode));
            var logicExpr = new NonTerminal("logicExpr", typeof(logicExprNode));
            var generalExpr = new NonTerminal("generalExpr");
            var blockForany = new NonTerminal("blockForany", typeof(BlockForanyNode));



            // 3. BNF rules
            Expr.Rule = Term | UnExpr | BinExpr | PrefixIncDec | PostfixIncDec | TernaryIfExpr | exprRandom | exprSet | blockIfElse;
            exprClass.Rule = createInstance | set | Change | whileClass | term1 | logicExpr | blockForany;
            blockForany.Rule = ToTerm("for") + "any" + identifier + identifier  + "do"  + listStatement  + "end";
            generalExpr.Rule = exprClass | Expr;
            set.Rule = ToTerm("set") + "the" + identifier + "of" + identifier + identifier + "to" + Expr;
            exprSet.Rule = ToTerm("set") + identifier + "to" + Expr;
            term1.Rule = ToTerm("the") + identifier + "of" + identifier + identifier + BinOp + Expr; //+ Expr;
            logicExpr.Rule = generalExpr + identifier + generalExpr;
            createInstance.Rule = ToTerm("create") + "instance" + identifier + "of" + identifier;
            whileClass.Rule = ToTerm("while") + generalExpr  + listStatement  + "endwhile";
            Change.Rule = ToTerm("change") + "the" + identifier + "of" + identifier + identifier + "to" + identifier + "of" + identifier + identifier + BinOp + Expr;
            //if_statement.Rule = ToTerm("if") + generalExpr + begin + listStatement + end
              //  | ToTerm("if") + generalExpr + begin + listStatement + end + "else"  + begin + listStatement + end;
            //else_clause_opt.Rule = Empty | PreferShiftHere() + "else" + NewLine + "begin" + NewLine + AssignmentStmt + NewLine + "end";

            blockIfElse.Rule = ToTerm("if") + generalExpr + begin + listStatement + end + "else" + begin + listStatement + end;
            //blockIf.Rule = ToTerm("if") + generalExpr + begin + listStatement + end;
            exprRandom.Rule = ToTerm("random") + "(" + ")";
            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("++") | "--";
            MemberAccess.Rule = Expr + PreferShiftHere() + "." + identifier;
            AssignmentStmt.Rule = ObjectRef + AssignmentOp + Expr;
            AssignmentOp.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/=";
            Statement.Rule = AssignmentStmt | Expr | Empty | exprClass;
            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 + "]";
            TernaryIfExpr.Rule = Expr + "?" + Expr + ":" + Expr;
            listStatement.Rule = MakePlusRule(listStatement,null, Statement);
            Program.Rule = listStatement;

            this.Root = Program;       // Set grammar root

            // 4. Operators precedence
            RegisterOperators(10, "?");
            RegisterOperators(15, "&", "&&", "|", "||");
            RegisterOperators(20, "==", "<", "<=", ">", ">=", "!=");
            RegisterOperators(30, "+", "-");
            RegisterOperators(40, "*", "/");
            RegisterOperators(50, Associativity.Right, "**");
            // 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("(", ")", "?", ":", "[", "]", "begin", "end");
            RegisterBracePair("(", ")");
            RegisterBracePair("[", "]");
            MarkTransient(Term, Expr, generalExpr, exprClass, Statement, BinOp, UnOp, IncDecOp, AssignmentOp, ParExpr, ObjectRef, Program);

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

            //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 LanguageRuntime CreateRuntime(LanguageData language)
        {
            return new ExpressionEvaluatorRuntime(language);
        }

        #region Running in Grammar Explorer
        private static MohanedEvaluator _evaluator;
        public override string RunSample(RunSampleArgs args)
        {
            if (_evaluator == null)
            {
                _evaluator = new MohanedEvaluator(this);
                _evaluator.Globals.Add("null", _evaluator.Runtime.NoneValue);
                _evaluator.Globals.Add("true", true);
                _evaluator.Globals.Add("false", false);

            }
            _evaluator.ClearOutput();
            //for (int i = 0; i < 1000; i++)  //for perf measurements, to execute 1000 times
            _evaluator.Evaluate(args.ParsedSample);
            return _evaluator.GetOutput();
        }
        #endregion

        public override void SkipWhitespace(ISourceStream source)
        {
            while (!source.EOF())
            {
                var ch = source.PreviewChar;
                switch (ch)
                {
                    case ' ':
                    case '\t':
                    case '\n':
                    case '\v':
                    case '\u2085':
                    case '\u2028':
                    case '\u2029':
                        source.PreviewPosition++;
                        break;
                    default:
                        //Check unicode class Zs
                        UnicodeCategory chCat = char.GetUnicodeCategory(ch);
                        if (chCat == UnicodeCategory.SpaceSeparator) //it is whitespace, continue moving
                            continue;//while loop 
                        //Otherwize return
                        return;
                }//switch
            }//while
        }
        

    }//class
Coordinator
Apr 5, 2012 at 10:51 PM

What is MonahedEvaluator? I guess it's another your class. Hard to say what's the problem, just step through in debugger and see if AstBuilder gets invoked, and if any AST nodes are actually created.