Three Address Code generation using Backpatching in LEX and YACC

65 Views Asked by At

Why does this code show segmentation fault?

generator.l

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

%%
[ \t]                       /* Skip whitespace */
[0-9]+                      { yylval.num = atoi(yytext); return NUMBER; }
"if"                        { return IF; }
"else"                      { return ELSE; }
"while"                     { return WHILE; }
[a-zA-Z][a-zA-Z0-9]*        { yylval.id = strdup(yytext); return IDENTIFIER; }
"+"                         { return PLUS; }
"-"                         { return MINUS; }
"*"                         { return TIMES; }
"/"                         { return DIVIDE; }
"="                         { return ASSIGN; }
"<"                         { return LESS; }
">"                         { return GREATER; }
"=="                        { return EQUAL; }
"!="                        { return NOT_EQUAL; }
"<="                        { return LESS_EQUAL; }
">="                        { return GREATER_EQUAL; }
"&&"                        { return AND; }
"||"                        { return OR; }
"!"                         { return NOT; }
"("                         { return LPAREN; }
")"                         { return RPAREN; }
";"                         { return SEMICOLON; }
\n                          { /* Newline */ }
.                           { return *yytext; }
%%

int yywrap() {
    return 1;
}

generator.y

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

#define MAX_CODE_LENGTH 100
#define MAX_IDENTIFIER_LENGTH 20

typedef struct {
    char op;
    char arg1[MAX_IDENTIFIER_LENGTH];
    char arg2[MAX_IDENTIFIER_LENGTH];
    char result[MAX_IDENTIFIER_LENGTH];
} Instruction;

Instruction code[MAX_CODE_LENGTH];
int code_index = 0;

int label_index = 0;

char* new_label() {
    char label[10];
    sprintf(label, "L%d", label_index++);
    return strdup(label);
}

void backpatch(int addr, char* label) {
    strcpy(code[addr].result, label);
}

void emit(char op, char* arg1, char* arg2, char* result) {
    code[code_index].op = op;
    strcpy(code[code_index].arg1, arg1);
    strcpy(code[code_index].arg2, arg2);
    strcpy(code[code_index].result, result);
    code_index++;
}

int yylex();
void yyerror(const char* s);

%}

%union {
    int num;
    char* id;
}

%token <num> NUMBER
%token <id> IDENTIFIER
%token IF ELSE WHILE
%token PLUS MINUS TIMES DIVIDE ASSIGN
%token LESS GREATER EQUAL NOT_EQUAL LESS_EQUAL GREATER_EQUAL
%token AND OR NOT
%token LPAREN RPAREN SEMICOLON

%left AND OR NOT
%left EQUAL NOT_EQUAL
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%left PLUS MINUS
%left TIMES DIVIDE

%type <num> expr bool_expr
%type <id> stmt

%start program

%%

program : stmt_list
        ;

stmt_list : stmt
          | stmt_list stmt
          ;

stmt : IDENTIFIER ASSIGN expr SEMICOLON
     {
         emit('=', $3, "", $1);
     }
     | IF LPAREN bool_expr RPAREN stmt
     {
         int index1 = code_index;
         int index2 = code_index + 1;
         backpatch(index1, new_label());
         emit('j', "", "", new_label());
         printf("L%d: if %s goto %s\n", index1, $3, code[index2].result);
     }
     | IF LPAREN bool_expr RPAREN stmt ELSE stmt
     {
         int index1 = code_index;
         int index2 = code_index + 1;
         int index3 = code_index + 2;
         backpatch(index1, new_label());
         emit('j', "", "", new_label());
         printf("L%d: if %s goto %s\n", index1, $3, code[index2].result);
         backpatch(index3, new_label());
         emit('j', "", "", new_label());
         printf("goto %s\n", code[index3].result);
     }
     | WHILE LPAREN bool_expr RPAREN stmt
     {
         int index1 = code_index;
         int index2 = code_index + 1;
         int index3 = code_index + 2;
         printf("L%d: ifFalse %s goto %s\n", index1, $3, code[index3].result);
         backpatch(index1, new_label());
         emit('j', "", "", new_label());
         printf("goto %s\n", code[index2].result);
         backpatch(index2, new_label());
         emit('j', "", "", new_label());
         printf("goto %s\n", code[index1].result);
         printf("%s:\n", code[index3].result);
     }
     ;

expr : IDENTIFIER
     {
         $$ = $1;
     }
     | NUMBER
     {
         $$ = $1;
     }
     | expr PLUS expr
     {
         char* t = new_label();
         emit('+', $1, $3, t);
         $$ = t;
     }
     | expr MINUS expr
     {
         char* t = new_label();
         emit('-', $1, $3, t);
         $$ = t;
     }
     | expr TIMES expr
     {
         char* t = new_label();
         emit('*', $1, $3, t);
         $$ = t;
     }
     | expr DIVIDE expr
     {
         char* t = new_label();
         emit('/', $1, $3, t);
         $$ = t;
     }
     ;

bool_expr : expr EQUAL expr
           {
               char* t = new_label();
               emit('=', $1, $3, t);
               $$ = t;
           }
           | expr NOT_EQUAL expr
           {
               char* t = new_label();
               emit('<>', $1, $3, t);
               $$ = t;
           }
           | expr LESS expr
           {
               char* t = new_label();
               emit('<', $1, $3, t);
               $$ = t;
           }
           | expr GREATER expr
           {
               char* t = new_label();
               emit('>', $1, $3, t);
               $$ = t;
           }
           | expr LESS_EQUAL expr
           {
               char* t = new_label();
               emit('<=', $1, $3, t);
               $$ = t;
           }
           | expr GREATER_EQUAL expr
           {
               char* t = new_label();
               emit('>=', $1, $3, t);
               $$ = t;
           }
           | bool_expr AND bool_expr
           {
               char* t = new_label();
               emit('&&', $1, $3, t);
               $$ = t;
           }
           | bool_expr OR bool_expr
           {
               char* t = new_label();
               emit('||', $1, $3, t);
               $$ = t;
           }
           | NOT bool_expr
           {
               char* t = new_label();
               emit('!', $2, "", t);
               $$ = t;
           }
           ;

%%

int main() {
    yyparse();
    printf("\nGenerated Three-Address Code:\n");
    for (int i = 0; i < code_index; i++) {
        printf("%d: %c %s %s %s\n", i, code[i].op, code[i].arg1, code[i].arg2, code[i].result);
    }
    return 0;
}

void yyerror(const char* s) {
    fprintf(stderr, "Error: %s\n", s);
    exit(1);
}

I am trying to generate three address code for if else while and arithmetic expression but it shows segmentation fault. I think its memory allocation problem but I don't know how to solve it. Also there is one shift reduce conflict that I can't handle. It's because of if expr and if expr else expr.

0

There are 0 best solutions below