学习yacc与lex--计算器实现练习

来源:互联网 发布:跑腿软件排名 编辑:程序博客网 时间:2024/05/24 03:26

cal.l

%{

 

#include<string.h>

#include "y.tab.h"

extern int yylval;

%}

numbers ([0-9])+

plus "+"

minus "-"

times "*"

divide "/"

lp "("

rp ")"

delim [ \r]

bs {delim}*

%%

{numbers} {sscanf(yytext, "%d", &yylval); return INTEGER;}

{plus} {return PLUS;}

{minus} {return MINUS;}

{times} {return TIMES;}

{divide} {return DIVIDE;}

{lp} {return LP;}

{rp} {return RP;}

{bs}       ;

"\n"            return CR;

. {printf("Error");exit(1);}

%%

 

lex cal.l

 

cal.y

%{

#include <stdio.h>

#include "lex.yy.c"

#define YYSTYPE int

int yyparse(void);

%}

%token INTEGER PLUS MINUS TIMES DIVIDE LP RP CR

%%

command2 : exp  CR {printf("Result = %d\n",$1);}

 

exp: exp PLUS term {$$ = $1 + $3;}

    |exp MINUS term {$$ = $1 - $3;}

    |term {$$ = $1;}

    ;

term : term TIMES factor {$$ = $1 * $3;}

    |term DIVIDE factor {$$ = $1/$3;}

    |factor {$$ = $1;}

    ;

factor : INTEGER {$$ = $1;}

    | LP exp RP {$$ = $2;}

    ;

%%

int main(int argc, char* argv[])

{

    ++argv, --argc;  /* Skip over program name. */

    if (argc > 0) {

printf("if \n");

        yyin = fopen(argv[0], "r");

    } else {

printf("else \n");

        yyin = stdin;

    }

printf("going to return yyparse() \n");

    return yyparse();

}

void yyerror(char* s)

{

    fprintf(stderr,"%s",s);

}

int yywrap()

{

    return 1;

}

 

 

yacc -d cal.y

生成了

y.tab.c

 

编译

g++ -o tcal y.tab.c

y.tab.c: In function ‘int yyparse()’:

y.tab.c:1318:35: error: ‘yyerror’ was not declared in this scope

       yyerror (YY_("syntax error"));

                                   ^

y.tab.c:1462:35: error: ‘yyerror’ was not declared in this scope

   yyerror (YY_("memory exhausted"));

                                   ^

 

注释掉报错的地方

 

重新编译

g++ -o tcal y.tab.c

 

 

./tcal

else

going to return yyparse()

1+2*3-5

Result = 2

 

 

修改测试

尝试增加一个^符号用来计算平方

3^ = 9

4^ = 16

 

 

    | factor SQUARE {$$ = $1 * $1;}

g++ -o tcal y.tab.c

In file included from cal.y:3:0:

cal.l: In function ‘int yylex()’:

cal.l:27:9: error: ‘SQUARE’ was not declared in this scope

 {sq}      {return SQUARE;}

         ^~~~~~

y.tab.c: In function ‘int yyparse()’:

y.tab.c:1326:35: error: ‘yyerror’ was not declared in this scope

       yyerror (YY_("syntax error"));

                                   ^

y.tab.c:1470:35: error: ‘yyerror’ was not declared in this scope

   yyerror (YY_("memory exhausted"));

                                   ^

 

由于yacc   cal.y 没有生成h文件,而文件中有曾经

采用yacc -d cal.y生成的h文件,就导致一直使用没有更新的h文件,和刻舟求剑一样

 

所以,需要使用yacc -d cal.y进行生成

 

 

 

cal.l

%{

 

#include<string.h>

#include "y.tab.h"

extern int yylval;

%}

numbers ([0-9])+

plus "+"

minus "-"

times "*"

divide "/"

lp "("

rp ")"

square "\^"

delim [ \r]

bs {delim}*

%%

{numbers} {sscanf(yytext, "%d", &yylval); return INTEGER;}

{plus} {return PLUS;}

{minus} {return MINUS;}

{times} {return TIMES;}

{divide} {return DIVIDE;}

{lp} {return LP;}

{rp} {return RP;}

{square}      {return SQUARE;}

{bs}       ;

"\n"            return CR;

. {printf("Error");exit(1);}

%%

 

由于^在正则表达式里有特殊意义,所以这里进行转义操作

 

lex cal.l

 

cal.y

%{

#include <stdio.h>

#include "lex.yy.c"

#define YYSTYPE int

int yyparse(void);

%}

%token INTEGER PLUS MINUS TIMES DIVIDE LP RP SQUARE CR

%%

command2 : exp  CR {printf("Result = %d\n",$1);}

 

exp: exp PLUS term {$$ = $1 + $3;}

    |exp MINUS term {$$ = $1 - $3;}

    |term {$$ = $1;}

    ;

term : term TIMES factor {$$ = $1 * $3;}

    |term DIVIDE factor {$$ = $1/$3;}

    |factor {$$ = $1;}

    ;

factor : factor SQUARE {$$ = $1 * $1;}

    | INTEGER {$$ = $1;}

    | LP exp RP {$$ = $2;}

    ;

%%

int main(int argc, char* argv[])

{

    ++argv, --argc;  /* Skip over program name. */

    if (argc > 0) {

printf("if \n");

        yyin = fopen(argv[0], "r");

    } else {

printf("else \n");

        yyin = stdin;

    }

printf("going to return yyparse() \n");

    return yyparse();

}

void yyerror(char* s)

{

    fprintf(stderr,"%s",s);

}

int yywrap()

{

    return 1;

}

 

g++ -o cal y.tab.c

 

注释修改编译报错

 

./cal

else

going to return yyparse()

1+2^

Result = 5

 

 

./cal

else

going to return yyparse()

1+2*3^+4

Result = 23

 

 

./cal

else

going to return yyparse()

1+3^^

Result = 82

 


0 1