how to add to ExpressionEvaluatorGrammar IF (...) MULTIPLE_STATEMENT ELSE MULTIPLE_STATEMENT

Jun 29, 2014 at 6:34 AM
Please I need a help,
ExpressionEvaluatorGrammar works wonderfull, but I need to add IF (...) MULTIPLE_STATEMENT ELSE MULTIPLE_STATEMENT

somebody help me please.
Coordinator
Jun 30, 2014 at 5:40 PM
Well, define the non-terminal for your IF statement, and then AST node that implements evaluation. If statements inside IF are each on its own line, then looking at mini-python grammar would help. If they are on one line - then what's the delimiter? add the delimiter into the mix. Follow the patterns in the samples. Advice - don't bother with AST node and evaluation at the beginning, just implement parsing part first; then once it parses correctly, implement evaluation.
Jun 30, 2014 at 8:14 PM
thank you rivantsov,
Parsing working ok, but I want to Evaluate now and I have the following exception:

Attempt to evaluate NULL AST node. The AST node for term 'if' was not created during parsing.

this is the script:
        a = 2
        if (a == 2) 
            a = 3
        b = a * 2
this is how I did it:

var IfExpr = new NonTerminal("IfExpression", typeof(IfNode));

Expr.Rule = Term | UnExpr | BinExpr | PrefixIncDec | PostfixIncDec | TernaryIfExpr | IfExpr;

IfExpr.Rule = ToTerm("if") + ParExpr + Statement | ToTerm("if") + ParExpr + Statement + PreferShiftHere() + ToTerm("else") + Statement;

I'm using the same code in ExpressionEvaluatorGrammar

It seems problem is in IFNode when Init the Test = AddChild("Test", nodes[0]); var child = (AstNode)childParseNode.AstNode; this part is null

how I can fix this?

thank you.
Coordinator
Jun 30, 2014 at 9:21 PM
I think the problem is that you IF AST node does not handle missing else clause - which is what you have in your sample. Modify it accordingly
Jul 1, 2014 at 4:51 PM
I believe I can do all I need to my language, but...when I try to create Ast nodes I have issues. Please help.
this is my grammar, very simple: (basically I've just copy from Writing Calculator blog sample)

var number = TerminalFactory.CreateCSharpNumber("number");
        var identifier = TerminalFactory.CreateCSharpIdentifier("identifier");
        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");
        var program = new NonTerminal("program", typeof (StatementListNode));

        expression.Rule = parexpr | binexpr | number | fncall;
        parexpr.Rule = "(" + expression + ")";
        binexpr.Rule = expression + binop + expression;
        binop.Rule = ToTerm("+") | "-" | "/" | "*" | "%";
        fncall.Rule = identifier + "(" + expression + ")";

        MarkPunctuation("(", ")");
        RegisterOperators(1, "+", "-");
        RegisterOperators(2, "*", "/", "%");


        MarkTransient(parexpr, expression);

        this.Root = expression;
        this.LanguageFlags = LanguageFlags.NewLineBeforeEOF | LanguageFlags.SupportsBigInt | LanguageFlags.CreateAst;
and I'm receiving an error in Line 97 in AstBuilder, Object reference not set to an instance of an object.

what I'm doing wrong ?

thank you so much.
Coordinator
Jul 5, 2014 at 8:35 PM
add binOp to MarkTransient call
Jul 8, 2014 at 4:08 AM
thank you, so far so good, Irony is indeed powerful :)
I need to create something like RETURN command, I don't have ideas how to do it.
The behavior must be everything after RETURN command cannot be evaluated. any ideas?

thank you.
Coordinator
Jul 9, 2014 at 7:33 PM
you have to build an AST node that directly manipulates the 'call stack' and performs the return. The return is associated with container function (you return not from immediate parent AST node context but from the function/method). So you have to walk the stack popping all frames until you find function decl/body (it most likely the immediate parent, but still), and pop it from stack and do other necessary things (push result into value stack) so interpreter can continue after function call in the caller.
Jul 25, 2014 at 3:58 PM
this is how I did, and it's working perfectly If Then Else (in case somebody needs this)

ifStatement.Rule = ToTerm("if") + ParExpr + "then" + NewLine + statements + NewLine + "endif" |
            //else
            ToTerm("if") + ParExpr + "then" + NewLine + statements + NewLine +
            "else" + NewLine + statements + "endif";
Irony Rocks!!!!