System.NullReferenceException in BuildAst

May 17, 2013 at 1:24 PM
I've got very simple grammar adapted from "Writing a calculator in C# using Irony" sample (see below) and parsing works fine, however when I add
LanguageFlags = LanguageFlags.CreateAst;
to generate AST I get following error in Parser Output tab:
AstNodeType or AstNodeCreator is not set on non-terminals: Irony.Parsing.BnfTermList. Either set Term.AstConfig.NodeType, or provide default values in AstContext.
and an exception in Irony Grammar Explorer:
System.NullReferenceException: Object reference not set to an instance of an object.
   at Irony.Ast.AstBuilder.BuildAst(ParseTreeNode parseNode) in C:\Programming\Irony_2013_03_10\Irony_2013_03_10\Irony\Ast\AstBuilder.cs:line 97
   at Irony.Ast.AstBuilder.BuildAst(ParseTreeNode parseNode) in C:\Programming\Irony_2013_03_10\Irony_2013_03_10\Irony\Ast\AstBuilder.cs:line 86
   at Irony.Ast.AstBuilder.BuildAst(ParseTree parseTree) in C:\Programming\Irony_2013_03_10\Irony_2013_03_10\Irony\Ast\AstBuilder.cs:line 38
   at Irony.Parsing.Grammar.BuildAst(LanguageData language, ParseTree parseTree) in C:\Programming\Irony_2013_03_10\Irony_2013_03_10\Irony\Parsing\Grammar\Grammar.cs:line 499
   at Irony.Parsing.Parser.Parse(String sourceText, String fileName) in C:\Programming\Irony_2013_03_10\Irony_2013_03_10\Irony\Parsing\Parser\Parser.cs:line 88
   at Irony.GrammarExplorer.fmGrammarExplorer.ParseSample() in C:\Programming\Irony_2013_03_10\Irony_2013_03_10\Irony.GrammarExplorer\fmGrammarExplorer.cs:line 359
   at Irony.GrammarExplorer.fmGrammarExplorer.btnParse_Click(Object sender, EventArgs e) in C:\Programming\Irony_2013_03_10\Irony_2013_03_10\Irony.GrammarExplorer\fmGrammarExplorer.cs:line 507
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
My grammar is:
public class TestGrammar1 : Grammar
        public TestGrammar1 () : base(false)
            var number = new NumberLiteral("number", NumberOptions.AllowSign | NumberOptions.AllowStartEndDot);
            var fnname = new IdentifierTerminal("fnname");
            var colname = new StringLiteral("colname");
            colname.AddStartEnd("[", "]", StringOptions.None);

            var expression = new NonTerminal("expression");
            var binexpr = new NonTerminal("binexpr", typeof(BinaryOperationNode));
            var parexpr = new NonTerminal("parexpr");
            var fncall = new NonTerminal("fncall", typeof(FunctionCallNode));
            var binop = new NonTerminal("binop", "operator");

            expression.Rule = parexpr | binexpr | number | colname | fncall;
            parexpr.Rule = "(" + expression + ")";
            binexpr.Rule = expression + binop + expression;
            binop.Rule = ToTerm("+") | "-" | "/" | "*";
            fncall.Rule = fnname + "(" + expression + ")";
            this.Root = expression;


            RegisterOperators(1, "+", "-");
            RegisterOperators(2, "*", "/");
            MarkTransient(parexpr, expression, binop);
            LanguageFlags = LanguageFlags.CreateAst;
My test expression:
Can somebody please help me figure out what's wrong with my grammar?
May 18, 2013 at 4:11 AM
at first look, you are missing AST node type for colname terminal. Stop in debugger on exception and look around on data involved (which non-terminal/terminal is there). But this is my guess - colname. You have to provide AstNode implementation - a class that knows how to interpret the colname at runtime.
Let me know if you're stuck, I may be able to investigate in details later
May 18, 2013 at 5:52 PM
Hi Roman, thanks for your reply.

I've started by stripping my grammar to bare minimum (only numbers and operators) but had the same issue. During debugging I found that DefaultLiteralNodeType was null and found this discussion that explained what was going on. Overriding BuildAst() did the trick and I got the basic grammar working. I'll start adding more stuff to my grammar and see what happens. At least I've got slightly better understanding of how it all works now.