Search code examples
ccompiler-constructionbisonflex-lexer

I am having syntax error in Flex/Bison for a C- program


I was doing my project for my compilers lessons, I finally finished it and it compilers but I keep getting a syntax error, and I don't know why! I tried using differences sources to see what I can find but nothing really helped. I even tried ChatGPT, so I came here to ask for advice and see what I am doing wrong from people that might know.

lab1.fl

%{
    #include "lab1.tab.h"
    int line = 1; //what line are we on in the code
    char filename[20];
    
    int comment = 0;
    
    int yywrap(void) {
    return 1;
    }
    
%}

ID      [a-zA-Z_][a-zA-Z0-9_]*
NUM     [0-9]+

%%



"\n" {return 0;}

"//"(.)*"\n" {}
"/*" { comment=1; printf("multiline comment\n");}
"*/" {comment=0;}



"int"                  { if (!comment) return INT; }
"void"                 { if (!comment) return VOID; }
"if"                    { if (!comment) return IF; }
"else"                  { if (!comment) return ELSE; }
"while"                 { if (!comment) return WHILE; }
"return"                { if (!comment) return RETURN; }

{ID}                    { yylval.strval = strdup(yytext); if (!comment) return ID; }
{NUM}                   { if (!comment) return NUM; }

"=="                    { if (!comment) return EQ; }
"!="                    { if (!comment) return NE; }
"<="                    { if (!comment) return LE; }
">="                    { if (!comment) return GE; }
"<"                     { if (!comment) return LT; }
">"                     { if (!comment) return GT; }

"+"                     { if (!comment) return ADD; }
"-"                     { if (!comment) return SUB; }
"*"                     { if (!comment) return MUL; }
"/"                     { if (!comment) return DIV; }

"("                     { if (!comment) return LPAREN; }
")"                     { if (!comment) return RPAREN; }
"["                     { if (!comment) return LBRACKET; }
"]"                     { if (!comment) return RBRACKET; }
"{"                     { if (!comment) return LBRACE; }
"}"                     { if (!comment) return RBRACE; }
","                     { if (!comment) return COMMA; }
";"                     { if (!comment) return SEMICOLON; }
"="                     { if (!comment) return ASSIGN; }
[\t| \r | \f | \v]      {}
<<EOF>>                 {return 0;}
%%

int main (int argc, char *argv[]){
    if (argc==2)
        yyin = fopen(argv[1], "rt");
    else
    {
        printf("No file-Exit\n");
        exit(1);
    }
    
    strcpy(filename,argv[1]);
    yylex();
    yyparse();
    fclose(yyin);
}

lab1.y

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

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

#define YYSTYPE_IS_DECLARED
#define YYSTYPE_IS_TRIVIAL 1

typedef struct {
    int numval;      // For NUM
    char *strval;    // For ID
} YYSTYPE;

#include "lab1.tab.h"
%}

%token INT VOID IF ELSE WHILE RETURN
%token <strval> ID 
%token <numval> NUM
%token EQ NE LT LE GT GE ADD SUB MUL DIV
%token LPAREN RPAREN LBRACKET RBRACKET LBRACE RBRACE COMMA SEMICOLON ASSIGN

%union {
  char *strval;  // Define the type of the semantic value
}

%type <strval> type_specifier
%type <strval> var
%type <strval> call
%type <strval> args
%type <strval> arg_list

%nonassoc LOWER_THAN_ELSE  
%left ADD SUB              
%left MUL DIV              
%nonassoc EQ NE            
%nonassoc LT LE GT GE      

%start program

%%

program: {printf("Program \n declaration_list\n");} declaration_list

declaration_list: declaration_list declaration {printf("declaration_list\n");}
                | declaration {printf("declaration ");}
                ;
declaration: var_declaration {printf("var declaration\n");}
                | fun_declaration {printf("fun declaration\n");}
                
var_declaration: type_specifier ID SEMICOLON {printf("variable_declaration(INT)");} 
                | type_specifier ID ASSIGN NUM SEMICOLON {printf("type_specifier(INT)\n"); printf("variable_declaration\n");}

type_specifier: INT {printf("type_specifier(INT)\n");}
                | VOID {printf("type_specifier(VOID)\n");}

fun_declaration: type_specifier ID LPAREN params RPAREN compound_stmt {printf("fun_definition");}

params: param_list
                | VOID {printf("params(VOID)\n");}

param_list: param_list COMMA param {printf("tparams list\n");} |
                param {printf("params list");}

param: type_specifier ID {printf("params(%s)\n",$2);} | type_specifier ID LBRACE RBRACE {printf("params{$s [])\n",$2);}

compound_stmt: LPAREN local_declarations statement_list RPAREN {printf("compound_stmt\n");}

local_declarations: local_declarations var_declaration {printf("local declaration\n");} | /* empty */

statement_list: statement_list statement {printf("statement list\n");} | /* empty */

statement: expression_stmt {printf("expression statement\n");} 
                | compound_stmt {printf("compound statement\n");} 
                | selection_stmt {printf("selection statement\n");}
                | iteration_stmt {printf("iteration statement\n");}
                | return_stmt {printf("return statement\n");}

expression_stmt: expression SEMICOLON | SEMICOLON

selection_stmt: IF LPAREN expression RPAREN statement %prec LOWER_THAN_ELSE | IF LPAREN expression RPAREN statement ELSE statement

iteration_stmt: WHILE LPAREN  expression RPAREN statement 

return_stmt: RETURN SEMICOLON | RETURN expression SEMICOLON

expression: var ASSIGN expression {printf("expression \n");}| simple_expression {printf("simple expression\n");}

var: ID {printf("var(%s)\n",$1);} | ID expression {printf("var(%s)\n",$1);}

simple_expression: additive_expression relop additive_expression {printf("additive expression\n");} | additive_expression {printf("additive expression\n");}

relop: EQ | NE | LE | GE | LT | GT

additive_expression: additive_expression addop term  | term

addop: ADD | SUB

term: term mulop factor {printf("term\n");} | factor {printf("term\n");}

mulop: MUL | DIV

factor: var | call | NUM

call: ID LPAREN args RPAREN

args: arg_list {printf("args list\n");} | /* empty */ {$$ = NULL;}

arg_list:  arg_list COMMA expression | expression {$$ = NULL;} | /* empty */ {$$ = NULL;}


%%

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

I use an input.txt file to run the program but even a blank program doesn't work even if I only insert a int a; for example into it, still nothing

I was expecting a syntax tree from my program but I only get the declaration_list and everything else doesn't work and I get a syntax error.

EDIT: I found the issue being that it doesn't return the tokens to the parser for some reason, I am still trying to figure out the issue, if anyone can help!


Solution

  • I finally figured out the issue with the tokens, I was using both yylex() and yyparse() but I found out that the parser also does yylex by itself so I removed it and it finally worked.