Root AST node is null, cannot evaluate. -- cannot find solution

Sep 19, 2013 at 10:53 AM
Edited Sep 19, 2013 at 11:22 AM
Hi,

This is my first attempt to write a grammar but I have to admit, this is much harder than I thought.

The objective of the grammar is to be generate an HTML layout based on the grammar + script (as external text file) + data (in XML format).

Before going that far, I simply wanted to be able to evaluate an "IF expression".

Parsing seems to be OK, however when I try to interpret it, I receive the "Root AST node is null, cannot evaluate" message.

Here is the code (in VB.NET, which is mandatory for me, unfortunately).
Imports Irony
Imports Irony.Ast
Imports Irony.Parsing
Imports Irony.Parsing.Grammar

Public Class IF_EXPR_Evaluator
    Inherits AstNode

    Public Name As String
    Public Argument As AstNode

    Public Overrides Sub Init(context As Irony.Parsing.ParsingContext, treeNode As Irony.Parsing.ParseTreeNode)
        MyBase.Init(context, treeNode)
        Name = treeNode.ChildNodes(0).FindTokenAndGetText()
        Argument = AddChild("Arg", treeNode.ChildNodes(1))
        AsString = Name
    End Sub

    Public Overrides Sub Evaluate(context As Irony.Interpreter.EvaluationContext, mode As Irony.Ast.AstMode)
        Argument.Evaluate(context, AstMode.Read)
        Dim input As String = Convert.ToString(context.Data(0))
        Dim result As Double
        Select Case Name.ToUpper()
            Case "EXISTS"
                'TODO
            Case "IS_NULL"
                'TODO
            Case "IS_EMPTY"
                'TODO
        End Select
        context.Data.Replace(1, result)
    End Sub
End Class

Public Class Test_Grammar
    Inherits Irony.Parsing.Grammar

    Public Sub New()

        Me.GrammarComments = "This is my first grammar"

        ' -- Types of "variables" -- 

        Dim StringLiteral As StringLiteral = TerminalFactory.CreateCSharpString("StringLiteral")
        Dim Number As NumberLiteral = TerminalFactory.CreateCSharpNumber("Number")
        Number.DefaultIntTypes = New TypeCode() {TypeCode.Int32, TypeCode.Int64}

        ' -- Comments -- 
        Dim DelimitedComment As New CommentTerminal("DelimitedComment", "/*", "*/")
        NonGrammarTerminals.Add(DelimitedComment)
        Dim COMMENT_OPT = New NonTerminal("COMMENT_OPT")
        Dim COMMENTS = New NonTerminal("COMMENTS")

        COMMENT_OPT.Rule = DelimitedComment Or Empty

        COMMENTS.Rule = MakePlusRule(COMMENTS, COMMENT_OPT)

        ' -- Symbols -- 

        Dim LSBr As KeyTerm = ToTerm("[")
        Dim RSBr As KeyTerm = ToTerm("]")

        ' -- Variables -- 

        Dim variable = New IdentifierTerminal("Identifier")
        Dim BLOCK = New NonTerminal("BLOCK")
        Dim BLOCKS = New NonTerminal("BLOCKS")
        Dim IF_STMT = New NonTerminal("IF_STMT")
        Dim IF_STMTS = New NonTerminal("IF_STMT")
        Dim IF_EXPR = New NonTerminal("IF_EXPR", GetType(IF_EXPR_Evaluator))
        Dim IF_EXPR_COND = New NonTerminal("IF_EXPR_COND")
        Dim identifier_if_expr As IdentifierTerminal = TerminalFactory.CreateCSharpIdentifier("identifier_if_expr")
        Dim ELSE_STMT = New NonTerminal("ELSE_STMT")

        Dim TAB_CONTENT = New NonTerminal("TAB_CONTENT")
        Dim TAB = New NonTerminal("TAB")
        Dim TABS = New NonTerminal("TAB")
        Dim LAYOUT = New NonTerminal("LAYOUT")
        Dim EXPR_KEYWORD = New NonTerminal("EXPR_KEYWORD")

        ' -- BLOCK -- 

        BLOCK.Rule = Empty Or NewLinePlus Or COMMENTS Or BLOCKS Or IF_STMTS
        BLOCKS.Rule = MakePlusRule(BLOCKS, BLOCK)

        ' -- IF_STMT -- 

        IF_STMT.Rule = "if" + IF_EXPR + NewLine + BLOCK + ELSE_STMT + "end_if" + NewLine
        IF_STMTS.Rule = MakePlusRule(IF_STMTS, IF_STMT)

        ' -- IF_EXPR -- 

        IF_EXPR.Rule = identifier_if_expr + "(" + IF_EXPR_COND + ")"
        IF_EXPR_COND.Rule = StringLiteral Or StringLiteral + "," + Number

        ' -- ELSE_STMT -- 

        ELSE_STMT.Rule = Empty Or "else" + NewLine + BLOCKS

        ' -- TAB = définition du contenu d'un tab -- 

        TAB.Rule = "tab(" + StringLiteral + ")" + TAB_CONTENT + "end_tab"
        TABS.Rule = MakePlusRule(TABS, TAB)

        ' -- TAB_CONTENT -- 

        TAB_CONTENT.Rule = Empty Or COMMENTS Or BLOCKS

        ' -- LAYOUT = ensemble de tout ce qui peut être défini -- 

        LAYOUT.Rule = Empty Or COMMENTS Or NewLinePlus Or TABS

        Me.Root = LAYOUT
        Me.LanguageFlags = Parsing.LanguageFlags.CreateAst Or Parsing.LanguageFlags.CanRunSample
    End Sub
End Class
The invocation code is:
Dim script As String = "tab(""tab_name"")" + vbCrLf + _
                                    "if exists(""t_data/data_1"")" + vbCrLf + _
                                    "end_if" + vbCrLf + _
                                "end_tab"


        Dim grammar As Irony.Parsing.Grammar = New Test_Grammar()
        Dim parser As Irony.Parsing.Parser = New Irony.Parsing.Parser(grammar)
        Dim parseTree As Irony.Parsing.ParseTree = parser.Parse(script)

        Dim interpret As ScriptInterpreter = New ScriptInterpreter(grammar)
        interpret.Evaluate(parseTree)
Any help will be appreciated.

Thank you
Coordinator
Sep 19, 2013 at 5:35 PM
First, did you try this in Grammar Explorer? that's the first thing you must do. I'm pretty sure it will show you a bunch of grammar errors. For one thing, your root is LAYOUT nonterminal, and it has no AST node specified. So no surprise here. Try it in GE
Sep 20, 2013 at 8:22 AM
I tried with GE and indeed this says the very same as you: there is no AST node specified. How do I specify one?
Coordinator
Sep 20, 2013 at 9:20 AM
you have some other nonterminals that have node specified, ex: IF_EXPR - it is the second parameter for NonTerminal constructor