System.NullReferenceException in BuildAst

May 17, 2013 at 2: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;

            MarkPunctuation("(",")");

            RegisterOperators(1, "+", "-");
            RegisterOperators(2, "*", "/");
            AddOperatorReportGroup("operator");
            
            MarkTransient(parexpr, expression, binop);
            LanguageFlags = LanguageFlags.CreateAst;
        }
    }
My test expression:
sum([a])
Can somebody please help me figure out what's wrong with my grammar?
Thanks!
Coordinator
May 18, 2013 at 5: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
Roman
May 18, 2013 at 6: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.

Thanks!