1

I have the following if statement that parses correctly:

ifStatement
    : 'IF' expression 'THEN' statementBlock 
        (options {greedy=true;} 
            : 'ELSE' statementBlock)?

    ;

Now, I want to parse this into an AST. This is how I did it:

ifStatement
    : 'IF'^ expression 'THEN'! statementBlock 
        (options {greedy=true;} 
            : 'ELSE'! statementBlock)?

    ;

Added ! and ^, as -> building instruction didn't seem to work.

My result is an AST with 3 children: 1 is the conditional, 2 and 3 are the statement blocks. The else part is optional: if there is no else, node 3 is missing.

The problem is that the statement blocks are always empty. How to fix that?

Palec
  • 12,743
  • 8
  • 69
  • 138
pantelis
  • 113
  • 10
  • Sorry, what exactly is the question? What result did you want, and what different result did you get? What are you hoping we will do for you? – Gareth McCaughan Mar 27 '11 at 22:48
  • sorry for not being clear but, my code does not return a parent node with 3 nodes. if i have not an else statement then 2. Generally, my parent node need to have 1 children, the expression, 2nd children the first statement, and 3rd the else statement – pantelis Mar 27 '11 at 23:38
  • So you *want* to get an AST with three children (antecedent, consequent, alternative) but you're actually getting either (antecedent, consequent, alternative) or (antecedent, consequent) depending on whether or not the `ELSE` clause was present in the input, and you are looking for a way to make the AST get built so that it has the same structure either way? – Gareth McCaughan Mar 28 '11 at 00:38
  • my tree actually returns (antecedent, null, null), or (antecedent, null) – pantelis Mar 28 '11 at 07:50

1 Answers1

0

The following is basically how I implemented it. Note that 'IF', 'THEN', and 'ELSE' are declared in the 'tokens' section

ifStatement
:   IF expression THEN ifStat=statementBlock 
    (   ELSE elseStat=statementBlock  ->  ^(IF expression $ifStat $elseStat)
    |                                 ->  ^(IF expression $ifStat)
    )
;

[edit] Or you could be more explicit which should also work

ifStatement
:   IF expression THEN ifStat=statementBlock ELSE elseStat=statementBlock  ->  ^(IF expression $ifStat $elseStat)
|   IF expression THEN ifStat=statementBlock                               ->  ^(IF expression $ifStat)
;
Matthew Sowders
  • 1,640
  • 1
  • 19
  • 32
  • yeah but else needs to be optional. – pantelis Mar 28 '11 at 07:51
  • ok it seems to work but im getting a warning "Decision can match input such as "'ELSE'" using multiple alternatives: 1, 2 As a result, alternative(s) 2 were disabled for that input" – pantelis Mar 28 '11 at 08:15
  • In this rule, the ELSE is optional. You will notice a sub-rule, the part inside the parenthesis. The first part of the sub-rule will match only if it begins with an ELSE. Otherwise, it matches the other IF production. You may have some other rule matching an "ELSE" which is causing your error. I do not have your entire grammar so I cannot tell. – Matthew Sowders Mar 28 '11 at 20:19