Search code examples
cgrammarbisonyacclex

YACC grammar for WHILE loop and statements wouldn't work


I am trying to generate intermediate code of the following grammar for while loop and general statements, but I keep encountering syntax error. Though earlier, the grammar for statements and expressions worked, but after adding the production for while loop this program doesn't work.

this is my lex.l file

%{
    #include "y.tab.h"
%}


NUMBER      [0-9]       
ALPHABET    [a-zA-Z]

%%

[\t];
{NUMBER}+   { strcpy(yylval.str, yytext); return ID; }
{ALPHABET}  { strcpy(yylval.str, yytext); return ID; }
"while"     { return WHILE; }
"do"        { return DO; }
"<"     { yylval.symbol=yytext[0]; return OP; }
">"     { yylval.symbol=yytext[0]; return OP; }
"!="        { yylval.symbol=yytext[0]; return OP; }
"=="        { yylval.symbol=yytext[0]; return OP; }
[\n];
.       { return yytext[0]; }

%%

And this is my yacc.y file

%{
    #include <stdio.h>
    #include <string.h>


    char result_gen();
    char quadruple_entry(char a[], char b, char c[]);
    char quadruple_entry_assign(char a[], char b, char c[]);
    char quadruple_entry_loop();
    char quadruple_entry_do();
    void three_address_code();

    int q_index = 0;
    char result[3] = {'t','0','\0'};
    char result2[3] = {'L','0','\0'};
    char temp[3];
    char temp2[3];

    struct QuadrupleStructure {
        char arg1[10];
        char op;
        char arg2[10];
        char rslt[3];
    }quadruple[25];

    
 
%}

%union {
    char str[10];
    char symbol;
}

%token WHILE DO
%token <str> ID
%token <symbol> OP
%type  <str> expr 

%right '='
%left '+' '-'
%left '/' '*'


%%
wstmt   :   WHILE { quadruple_entry_loop(); } stmt  DO { quadruple_entry_do(); }
    ;

stmt    :   ID '=' expr  { quadruple_entry_assign($1, '=', $3); }
    |   ID OP ID { quadruple_entry($1,$2,$3); }
    ;


expr    :   expr '+' expr { quadruple_entry($1, '+', $3); strcpy($$,temp); }

    |   expr '-' expr { quadruple_entry($1, '-', $3); strcpy($$,temp); }

    |   expr '/' expr { quadruple_entry($1, '/', $3); strcpy($$,temp); }

    |   expr '*' expr { quadruple_entry($1, '*', $3); strcpy($$,temp); }

    |   '(' expr ')'  { strcpy($$,$2); }

    |   ID        { strcpy($$,$1); }
    ;

%%




char result_gen() {
    strcpy(temp,result);
    result[1]++;
}


char quadruple_entry(char a[], char b, char c[]) {
    result_gen();

    strcpy(quadruple[q_index].arg1, a);
    quadruple[q_index].op = b;
    strcpy(quadruple[q_index].arg2, c);
    strcpy(quadruple[q_index].rslt, temp);

    q_index++;
}

char quadruple_entry_assign(char a[], char b, char c[]) {
    char tempLocal[3] = {' ',' ','\0'};
    strcpy(quadruple[q_index].arg1, a);
    quadruple[q_index].op = b;
    strcpy(quadruple[q_index].arg2, c);
    strcpy(quadruple[q_index].rslt, tempLocal);

    q_index++;
}

char quadruple_entry_loop() {
    char tempLocal[3];
    strcpy(tempLocal, result2);

    char tempLocal2[] = " if ";
    char tempLocal3 = ' ';
    char tempLocal4[] = " ";
    
    strcpy(quadruple[q_index].rslt, tempLocal);
    strcpy(quadruple[q_index].arg1, tempLocal4);
    quadruple[q_index].op = tempLocal3;
    strcpy(quadruple[q_index].arg2, tempLocal2);
 
    q_index++;  
}

char quadruple_entry_do() {
    char tempLocal[4];
    strcpy(tempLocal, result2);
    tempLocal[3] = ':';
    strcpy(quadruple[q_index].arg1,tempLocal);

    char tempLocal2[] = " ";
    char tempLocal3 = ' ';

    quadruple[q_index].op = tempLocal3;
    strcpy(quadruple[q_index].arg2, tempLocal2);

    q_index++;
    result2[1]++;
    
    char tempLocal4[4];
    strcpy(tempLocal4, result2);
    tempLocal4[3] = ':';
    strcpy(quadruple[q_index].arg1,tempLocal4);

    char tempLocal5[] = " ";
    char tempLocal6 = ' ';

    quadruple[q_index].op = tempLocal6;
    strcpy(quadruple[q_index].arg2, tempLocal5);

    q_index++;
    result2[1]++;
}
     

void three_address_code() {
    int i;
    for(i=0 ; i<q_index ; i++) 
    printf("\n%s := %s %c %s", quadruple[i].rslt, quadruple[i].arg1, quadruple[i].op, quadruple[i].arg2);
}

void yyerror(char *s){
    printf("Errror %s",s);
}

int yywrap() {
    return 1;
}

int main() {
    yyparse();
    three_address_code();
    return 0;
} 

Input:

i=2*5-10
while i<5 do 

Output:

Errror syntax error

If someone can figure out where the grammar is wrong, or if my code is wrong, it'd be very helpful.


Solution

  • Your start symbol is wstmt, so the program accepts a single while statement as an input. If you need to accept a sequence of statements, you need a symbol that expands into a sequence of statements as your starting symbol.

    In addition, your lexer doesn't swallow spaces, so any program that has spaces has an error.