Please assist: if/else condition problem with lex/yacc

Pakt <paktsardines@gmail.com>
Mon, 17 May 2010 10:02:02 -0700 (PDT)

          From comp.compilers

Related articles
Please assist: if/else condition problem with lex/yacc paktsardines@gmail.com (Pakt) (2010-05-17)
Re: Please assist: if/else condition problem with lex/yacc kevinlynx@gmail.com (Kevin Lynx) (2010-05-20)
Re: Please assist: if/else condition problem with lex/yacc cfc@shell01.TheWorld.com (Chris F Clark) (2010-05-21)
Re: Please assist: if/else condition problem with lex/yacc paktsardines@gmail.com (Pakt) (2010-05-24)
Re: Please assist: if/else condition problem with lex/yacc gone_pecan@nowhere.net (Bruce C. Baker) (2010-05-26)
Re: Please assist: if/else condition problem with lex/yacc gneuner2@comcast.net (George Neuner) (2010-05-26)
Re: Please assist: if/else condition problem with lex/yacc gneuner2@comcast.net (George Neuner) (2010-05-27)
[1 later articles]
| List of all articles for this month |

From: Pakt <paktsardines@gmail.com>
Newsgroups: comp.compilers
Date: Mon, 17 May 2010 10:02:02 -0700 (PDT)
Organization: Compilers Central
Keywords: interpreter, question, comment
Posted-Date: 19 May 2010 00:45:00 EDT

Hi,


The following situation has been doing my head in for too long and I
would be grateful if someone could ease my suffering and point out
what I'm doing wrong. My suspicion is that it's embarassingly
obvious, but I'm a lex/yacc newbie and have found little information
on implementing conditional statements (Even after reading Appel's
Modern Compiler Implementation in C)


To illustrate, I have reduced the problem to a _very_ simple
interpreter which accepts only numbers, if/else blocks, "eq"
expressions and print statements. As in:


if (1 eq 1) {
        print ("same");
}
else {
        print ("different");
}




However, when the above is fed to the below, it prints:
"same"
"different"


Obviously it should only be printing "same", but I don't understand
how/why execution also enters the else block.




My [f]lex file looks like this:
%{
#include <stdio.h>
#include "spl.tab.h"
%}
%%
[-?0-9]+ yylval=atoi(yytext); return NUMBER;
if return TOK_IF;
else return TOK_ELSE;
eq yylval=(int) strdup(yytext);return TOK_EQ;
ne yylval=(int) strdup(yytext);return TOK_NEQ;
print return TOK_PRINT;
\".*\" yylval=(int) strdup(yytext);return STRING;
\( return LPAREN;
\) return RPAREN;
\{ return LBRACE;
\} return RBRACE;
\; return SEMICOLON;
[ \t]+ /* ignore whitespace */;
%%


And the yacc [/bison] file like this:


%{
#include <stdio.h>
#include <string.h>
#define true 1
#define false 0


void yyerror(const char *str)
{
                fprintf(stderr,"error: %s\n",str);
}


int yywrap()
{
                return 1;
}


main()
{
                yyparse();
}


%}


%token NUMBER TOK_IF TOK_ELSE TOK_EQ TOK_PRINT LPAREN RPAREN LBRACE
RBRACE SEMICOLON STRING TOK_NEQ
%%
commands:
        | commands command SEMICOLON
        ;
command:
        print |
        if_else_block
        ;
print:
          TOK_PRINT LPAREN STRING RPAREN {
                  printf("%s\n",$3);
          }
          ;


if_else_block:
          TOK_IF expression LBRACE commands RBRACE TOK_ELSE LBRACE commands
RBRACE {
                  if ($2 == true) {
                          $$=$4;
                  }
                  else {
                          $$=$8;
                  }
          }
          ;
expression:
            NUMBER {$$ = $1;} |
            expression TOK_EQ expression {($1==$3)?($$=true):($
$=false);} |
            expression TOK_NEQ expression {($1!=$3)?($$=true):($
$=false);} |
            LPAREN expression RPAREN {$$=$2;}
            ;
%%




Sorry for dumping my code on you lot, but I'm really losing hair over
this one.


Thanks heaps for any assistance.


Pakt.
[Your program is doing exactly what you told it to do, which in this
case is to evaluate each statement as it's parsed. Having been
through this too many times to count, my advice is to compile the
program into an AST, then interpret the AST. This makes it easy to
solve your particular problem, since you can interpret only the desired
branch of the if/else, and next week when you want to add loops, the
AST makes that easy, too. I put a little calculator into "flex &
bison" with an AST interpreter, and it works well enough that one
example is to compute square roots by iterative Newton's method. -John]


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.