
简介
最近想玩下编译,那么在这之前先了解了下脚手架,其中包括了lex和yacc,下面简单介绍下lex和yacc。
lex
Lex是LEXical compiler的缩写,是Unix环境下非常著名的工具,主要功能是生成一个词法分析器(scanner)的C源码,描述规则采用正则表达式(regular expression)。
yacc
yacc(Yet Another Compiler Compiler),是一个经典的生成语法分析器的工具。是Unix/Linux上一个用来生成编译器的编译器(编译器代码生成器)。yacc生成的编译器主要是用C语言写成的语法解析器(Parser),需要与词法解析器Lex一起使用,再把两部份产生出来的C程序一并编译。yacc本来只在Unix系统上才有,但现时已普遍移植往Windows及其他平台。
好了,今天打算先用这两个简单的做个计算器,只是简单的实现一下四则运算而已,一则了解下工具lex和yacc,二则练练手。
准备工作
环境:Mac OS
- 安装lex:
brew install flex
- 安装yacc:
brew install byacc
PS:其中 flex
是 lex
的改进版本, byacc
是伯克利分校的 yacc
,用法同 yacc
。
实现
首先建立个文件夹,名为 calcu
。接下来写 lex
文件,后缀名是 .l
,这里命名为 calc.l
。
1 %{
2 #include <stdio.h>
3 #include "y.tab.h"
4
5 int
6 yywrap(void)
7 {
8 return 1;
9 }
10 %}
11
12 %%
13
14 "+" return ADD;
15 "-" return SUB;
16 "*" return MUL;
17 "/" return DIV;
18 "\n" return CR;
19 ([1-9][0-9]*)|0|([0-9]+\.[0-9]*) {
20 double temp;
21 sscanf(yytext, "%lf", &temp);
22 yylval.double_value = temp;
23 return DOUBLE_LITERAL;
24 }
25 [ \t];
26 . {
27 fprintf(stderr, "lexical error.\n");
28 exit(1);
29 }
30 %%
接下来是 yacc
文件的编写,后缀名为 .y
,这里命名为 calc.y
,具体代码如下:
1 %{
2 #include <stdio.h>
3 #include <stdlib.h>
4 #define YYDEBUG 1
5 %}
6 %union {
7 int int_value;
8 double double_value;
9 }
10 %token <double_value> DOUBLE_LITERAL
11 %token ADD SUB MUL DIV CR
12 %type <double_value> expression term primary_expression
13 %%
14 line_list
15 : line
16 | line_list line
17 ;
18 line
19 : expression CR
20 {
21 printf(">>%lf\n", $1);
22 }
23 expression
24 : term
25 | expression ADD term
26 {
27 $$ = $1 + $3;
28 }
29 | expression SUB term
30 {
31 $$ = $1 - $3;
32 }
33 ;
34 term
35 : primary_expression
36 | term MUL primary_expression
37 {
38 $$ = $1 * $3;
39 }
40 | term DIV primary_expression
41 {
42 $$ = $1 / $3;
43 }
44 ;
45 primary_expression
46 : DOUBLE_LITERAL
47 ;
48 %%
49 int
50 yyerror(char const *str)
51 {
52 extern char *yytext;
53 fprintf(stderr, "parser error near %s\n", yytext);
54 return 0;
55 }
56
57 int main(void)
58 {
59 extern int yyparse(void);
60 extern FILE *yyin;
61
62 yyin = stdin;
63 if (yyparse()) {
64 fprintf(stderr, "Error ! Error ! Error !\n");
65 exit(1);
66 }
67 }
代码解析
忙(懒)而未写,有待补充
运行
yacc -dv calc.y
会生成 yacc
的两个文件,分别是 y.tab.c
和 y.tab.h
。
lex calc.l
会生成 lex.yy.c
文件。其中 y.tab.c
包含 yacc
生成的语法分析器的代码, lex.yy.c
是词法分析器的代码,为了将 calc.y
中定义的记号以及联合体传给 lex.yy.c
,yacc会生成 y.tab.h
的头文件。
cc -o calc y.tab.c lex.yy.c
生成可执行文件calc。
然后运行
./calc
然后就可以使用计算器咯~
参考资料
Related Posts
- hadoop家族介绍
- 极客风的ppt制作软件-nodeppt使用指南
- 1分钟制作简单chrome扩展应用
我来评几句
登录后评论已发表评论数()