Search code examples
cparsingtokenyacclex

How to parse if /else statements with yacc


I m trying to create a .y file to design basic programming language where terminal values are just true and false. However, I have a trouble to define a rule for if statement. Syntax of if statement is like;

a=TRUE
if TRUE: print(a)

and my BNF is like;

statement : assignment | ifstatement | print
ifstatement : IF expression COLON statement                {if($2==true){$$ = $4;}}

where IF is token of keyword if and COLON for ':'. But when I compile my files, I got the following error;

$4 of ‘ifstatement’ has no declared type ifstatement : IF expression COLON statement {if($2==true){$$ = $4;}}

So, my question is what could be the rule that I should use for if else statements other than {if($2==true){$$ = $4;}} ?


Solution

  • The problem bison is complaining about is that you are assigning to $$, which is the semantic value of ifstatement, but you haven't told bison what the type of ifstatement is. Just as in C, if you have a variable, you need to declare it's type.

    This presumes that you have told bison that not all grammar symbols have the same type. In other words, you have a %union declaration which specifies tag names for all the different types you are using. Then you need to declare the types of all tokens and non-terminals which have values using %token and %type declarations.

    Your action if($2==true){$$ = $4;} requires that $$ (ifexpression), $2 (expression) and $4 (statement) all have declared types. If bison only complains about one of those, then you know how to declare types because the other two have been declared. Otherwise, if you have many such errors, then you should review the relevant section in the bison manual. You might want to also read the entire chapter on semantic values.

    However, none of the above addresses the real problem with that action, which has to do with your approach to interpreting the program code. An if statement is expected to only evaluate its true branch if the condition is, in fact, true. But observe that the value of $4 has already been computed before your action has been executed, regardless of whether the condition happens to be true. All that the action does is forward the already-computed value of the statement into the value of the ifstatement. Also, note that $$ is not assigned anything if the condition is false. So its value is either that of $4 or it is uninitialised, and in the latter case attempting to use its value will be undefined behaviour.

    This is why any non-trivial language cannot be evaluated during the parse. Conditional blocks can only be evaluated after the conditional statement has been parsed, so their evaluation needs to be deferred. And repeated blocks -- for and while statements, for example -- must be evaluated many times although they are only parsed once.