`
konsise
  • 浏览: 10791 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

Lex&Yacc(4) flex与Yacc结合的例子

阅读更多
最近这一周的临时任务实在是重,好几个晚上都很晚才回去。
自己的Javacc开发任务也有所耽搁,下个周也不轻松。所以只好抽晚上程序跑数的时间来更新一下。
Lex是词法解析程序,擅长用正则表达式去匹配词组;而Yacc擅长于对复杂语法的分析,两者结合起来能使代码高效且维护更简单。
下面我们用lex与Yacc写一个计算器的例子,这个例子很经典,到处都可以找到,我的例子来自于《lex与yacc 第二版》第三章的第一个例子ch03-01.l和ch03-01.y。
yc03.y
%token NUMBER  //终结符标记。
    %type  exp term  //非终结符标记,多个标记之间使用空格分开

    %%

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

    exp : exp '+' term {$$ = $1 + $3;}   //$N表示第N个表达式的值;$$表示冒号:左边的表达式
        | exp '-' term {$$ = $1 - $3;}   //$N所代表的引用值,为yylval的值,该值默认为int类型。
        | term {$$ = $1;}
        ;

    term : term '*' factor {$$ = $1 * $3;}
         | term '/' factor 
           {
              if($3==0)
                  yyerror("divide by zero");
              else
                  $$ = $1/$3;
            }
     | factor {$$ = $1;}
     ;

   factor : NUMBER {$$ = $1; printf("NUMBER \n");}
        | '(' exp ')' {$$ = $2;}
        ;

使用下面的命令来编译yacc程序:
yacc -oyc03.c -d yc03.y   【这里使用:-d参数,是为了方便生成.h文件,以便flex程序引用】
gcc  -c ./yc03.c    【编译.c文件】
%{
#include "yc03.h"        //这里引用yacc生成的.h文件
extern int yylval;       //使用yacc中的yylval变量,将lex中得到的值传递给yacc
%}

%%
[0-9]+        { yylval = atoi(yytext); return NUMBER; }  //yytext为满足当前表达式的字符串,return NUMBER表示向Yacc返回NUMBER终结符标记
[ \t]        ;
\n        return 0;        /* logical EOF */
.        { return yytext[0]; }
%%
int main(){
        yylex();
        return(0);
}

使用下面的命令来编译flex程序:
flex -ofl03.c fl03.l
gcc -c ./fl03.c
使用下面的命令来连接flex和yacc生成的.o文件
gcc -o fl03 fl03.o yc03.o -ly -lfl
上面的例子只是讲述了lex与Yacc的结合,能简单解决部分算术运算,且只支持整数。要想支持整数,则需要将yylval的类型重新定义为double类型。而且,上面的例子还没有考虑到带符号的表达式和乘方等,后者可以引入C的math.c进行计算。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics