I am trying to use flex and bison to create a compiler for a simple language called "FUNC". but it gives me a segmentation fault and after spending hours on it, i still haven't been able to fix it. would really appreciate if you guys could help. thanks!
Flex FIle "func.lex"
%{
#include "tokens.h"
//#include "y.tab.h"
%}
DIGIT [0-9]
IDENT [a-zA-Z][A-Za-z0-9]*
%%
"function" {return FUNCTION;}
"returns" {return RETURNS;}
"begin" {return BEGIN;}
"end" {return END;}
"read" {return READ;}
"write" {return WRITE;}
"if" {return IF;}
"then" {return THEN;}
"else" {return ELSE;}
"variables" {return VARIABLES;}
"while" {return WHILE;}
"loop" {return LOOP;}
"Less" {return LESS;}
"LessEq" {return LESSEQ;}
"Eq" {return EQ;}
"NEq" {return NEQ;}
"(" {return LB;}
")" {return RB;}
"Plus" {return PLUS;}
"Times" {return TIMES;}
"Minus" {return MINUS;}
"Divide" {return DIVIDE;}
"," {return COMMA;}
":=" {return ASSIGN;}
";" {return SEMI;}
{DIGIT}+ {return NUMBER;}
{IDENT} {return NAME;}
<<EOF>> {return EOF;}
[ \t\n]+ /* eat up whitespace */
%%
int yywrap() { return EOF; }
Yacc File "func.y"
%{
//#include "tokens.h"
#include <stdio.h>
#include <stdlib.h>
extern FILE * yyin;
extern char * yytext;
extern int yylex(void);
extern int yyparse();
void yyerror( const char *s);
int yylex(void);
int symb;
%}
/*****************bison declarations**********************/
%union //defining all possible semantic data types (strings and digits)
{
int NUMBER;
char * NAME;
_Bool COND; //return value of conditional expressions. one of our $$ can have value 0 or 1
}
%start program
%type <NUMBER> NUMBER
%type <NAME> NAME
%token FUNCTION RETURNS VARIABLES BEGIN END COMMA SEMI ASSIGN
READ WRITE
IF THEN ELSE
WHILE LOOP
LB RB
LESS LESSEQ EQ NEQ
PLUS MINUS TIMES DIVIDE
NAME NUMBER //same case as that used in "operations" below (same as FUNC syntax)
%%
//grammar rules
program: funcs
; //<program> ::= <funcs>
funcs: func ";" //<funcs> ::= <func>; [<funcs>]
|func ";" funcs
;
func: FUNCTION NAME "("")" BEGIN commands END FUNCTION /*<func> ::= function <name>([<args>])[returns <name>] [variables <args>] begin <commands> end function*/
|FUNCTION NAME "(" args ")" BEGIN commands END FUNCTION
|FUNCTION NAME "(" args ")" RETURNS NAME BEGIN commands END FUNCTION
|FUNCTION NAME "("")" RETURNS NAME BEGIN commands END FUNCTION
|FUNCTION NAME "("")" BEGIN commands VARIABLES args END FUNCTION
|FUNCTION NAME "(" args ")" BEGIN commands VARIABLES args END FUNCTION
|FUNCTION NAME "("")" RETURNS NAME BEGIN commands VARIABLES args END FUNCTION
|FUNCTION NAME "(" args ")" RETURNS NAME BEGIN commands VARIABLES args END FUNCTION
;
args: NAME //<args> ::= <name> [,<args>]
|NAME "," args
;
commands: command ";" //<commands> ::= <command>; [<commands>]
|command ";" commands
;
command: assign //<command> ::= <assign> | <if> | <while> | read <name> | write <expr>
|if
|while
|read
|write
;
assign: NAME ":=" expr {$<NAME>$=$1=$<NUMBER>3;} //<assign> ::= <name> := <expr>
//assign: NAME ASSIGN expr {$1=$3;}
;
if: IF condexpr THEN commands END IF //<if> ::= if <condexpr> then <commands> [else <commands>] end if
|IF condexpr THEN commands ELSE commands END IF
;
while: WHILE condexpr LOOP commands END LOOP
; //<for> ::= while <condexpr> loop <commands> end loop
read: READ NUMBER
|READ NAME
;
write: WRITE expr
;
condexpr: bop "(" expr "," expr ")"
; //<condexpr> ::= <bop> ( <exprs> )
bop: LESS //<bop> ::= Less | LessEq | Eq | NEq
|LESSEQ
|EQ
|NEQ
;
Less: LESS "(" NUMBER "," NUMBER ")" {if($<NUMBER>3<$<NUMBER>5)$<COND>$=1;} ;
LessEq: LESSEQ "(" NUMBER "," NUMBER ")" {if($<NUMBER>3<=$<NUMBER>5)$<COND>$=1;} ;
Eq: EQ "(" NUMBER "," NUMBER ")" {if($<NUMBER>3=$<NUMBER>5)$<COND>$=1;} ;
NEq: NEQ "(" NUMBER "," NUMBER ")" {if($<NUMBER>3!=$<NUMBER>5)$<COND>$=1;} ;
exprs: expr //<expr> [,<exprs>]
|expr "," exprs
;
expr: NAME
|NUMBER
|NAME "(" exprs ")" //<name>[( <exprs> )] | <number>
;
/***************idk if we need this. dunno which file to describe these operations in ***********************/
Plus: PLUS "(" NUMBER "," NUMBER ")" {$<NUMBER>$=$3+$5; } ; //S1=plus $2=( $3=expr $4= $5=expr $6=)
Minus: MINUS "(" NUMBER "," NUMBER ")" {$<NUMBER>$=$3-$5; } ;
Times: TIMES "(" NUMBER "," NUMBER ")" {$<NUMBER>$=$3*$5; } ;
Divide: DIVIDE "(" NUMBER "," NUMBER ")" {$<NUMBER>$=$3/$5; } ;
%%
//c code
/*
int main(int c, char * * argv) {
if ((yyin = fopen(argv[1], "r")) == NULL) {
printf("can't open %s\n", argv[1]);
exit(0);
}
symb = yylex();
yyparse();
// program(1);
fclose(yyin);
}
*/
int main (char * * argv)
{
if ((yyin = fopen(argv[1], "r")) == NULL) {
printf("can't open %s\n", argv[1]);
exit(0);
}
yylex();
}
void yyerror(const char *s)
{
extern int yylineno; // defined and maintained in lex.c
extern char *yytext; // defined and maintained in lex.c
/*std::cerr << "ERROR: " << s << " at symbol \"" << yytext;
std::cerr << "\" on line " << yylineno << std::endl;
exit(1);*/
printf("parse error Message: ", s);
fflush(1);
exit(-1);
}
/*int yyerror(char *s)
{
return yyerror(string(s));
}*/