I am new to compiler and making my own compiler for subset of c language.

flex code:

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

%option warn noyywrap noinput nounput yylineno

%%
"else"      {return ELSE;}
"if"        {return IF;}
"int"       {return INT;}
"return"    {return RETURN;}
"void"      {return VOID;}
"while"     {return WHILE;}
"+"         {return ADD;}
"-"         {return SUB;}
"*"         {return MUL;}
"/"         {return DIV;}
"<"         {return LT;}
"<="        {return LTE;}
">"         {return GT;}
">="        {return GTE;}
"=="        {return EQ;}
"!="        {return NEQ;}
"="         {return ASSIGN;}
";"         {return SEMI;}
","         {return COMMA;}
"("         {return ROUND_OPEN;}
")"         {return ROUND_CLOSE;}
"["         {return SQUARE_OPEN;}
"]"         {return SQUARE_CLOSE;}
"{"         {return CURLY_OPEN;}
"}"         {return CURLY_CLOSE;}
[a-zA-z]+   {return ID;}
[0-9]+      {yylval.intVal=atoi(yytext);return NUM;}
"//".*      /* discard comments */
[ \t\n\b]+  { if (yytext[0] == '\n') ++yylineno; } /* discard whitespace */
%%

Bison code:

%{
extern int yylex();
void yyerror(char* err, ...);
%}
%union{
    int intVal;
};

%token ELSE, IF, RETURN, VOID, INT
%token WHILE
%token ADD, SUB, MUL, DIV
%token LT, LTE, GT, GTE, EQ, NEQ
%token ASSIGN
%token SEMI, COMMA
%token ROUND_OPEN, ROUND_CLOSE, SQUARE_OPEN, SQUARE_CLOSE, CURLY_OPEN, CURLY_CLOSE
%token ID, NUM

%type <int> S 
%type <int>expr
%type <int> term
%type <int> factor 


%%
S: expr'\n' {$<intVal>$=$<intVal>1;printf("%d",$<intVal>$);}
expr: expr ADD term {$<intVal>$=$<intVal>1+$<intVal>2;};
expr: term {$<intVal>$=$<intVal>1};
term: term MUL factor {$<intVal>$=$<intVal>1*$<intVal>2};
term: factor {$<intVal>$=$<intVal>1};
factor:NUM {$<intVal>$=yylval.intVal};

%%

void yyerror(char* err, ...)
{
    fprintf(stderr, "%s\n", err);
}

there is a main file for calling yyparse. I am just programming an arithmetic calculator first but it is giving me parse error please help.

有帮助吗?

解决方案

I'll just list all things I think are incorrect - once you fix them maybe it will start working:

%type <int> S 
%type <int> expr
%type <int> term
%type <int> factor 

should be:

%type <intVal> S 
%type <intVal> expr
%type <intVal> term
%type <intVal> factor 

You define here which field of union should be used for each of [non]terminals. Then that:

S: expr'\n' {$<intVal>$=$<intVal>1;printf("%d",$<intVal>$);}

Bison in no way are aware of '\n' char - it only receives tokens from Flex lexer. Since you aren't sending new line token to parser it is not aware of it. And it surely wouldn't be '\n'.

Instead use:

// in bison "header"
%token EOL // End of Line

// in flex definitions
"\n"          { ++yylineno; return EOL; }
[ \t\r\f\v]+  /* remove blanks */

// again in bison
S: expr EOL { $$ = $1; printf("%d",$$); }

You don't need to choose field of union manually - that what's %type <intVal> S is for.

Why split productions into separate lines? You could just do:

S: expr EOL { $$ = $1; printf("%d",$$); }
 ;

expr: expr ADD term { $$ = $1 + $2;}
    | term          { $$ = $1; }
    ;

term: term MUL factor { $$ = $1 * $2; }
    | factor          { $$ = $1; }
    ;

factor: NUM { $$ = $1; }
      ;

Once written in that shortened way it was also obvious that you made a mistakes like:

term: term MUL factor {$<intVal>$=$<intVal>1*$<intVal>2};

instead of:

term: term MUL factor {$<intVal>$=$<intVal>1*$<intVal>2;}

where }; is invalid syntax as opposed to ;} - this is after all a normal C code, bison only inserts yylval.fieldName every time you use $$ or $1 etc - right field is chosen by %type <fieldName> tokenName definition.

Those were just the errors I saw immediately. Remove them and then we'll see if it still won't work.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top