网上的很多程序,对初次接触Bison和Flex的人而言,都有点复杂,看最简单的例子更好些:
我稍微修改一下,说说自己的理解,也作为一个备忘:
Flex程序:
1 [root@lex total]# cat lexer.l 2 %{ 3 4 #include "y.tab.h" 5 #include <stdio.h> 6 7 8 #undef YY_INPUT 9 #define YY_INPUT(b,r,s) readInputForLexer(b,&r,s) 10 11 %} 12 13 DIGIT [0-9] 14 %% 15 16 \+ { printf("got plus\n"); return FUNCTION_PLUS; } 17 \- { printf("got minus\n"); return FUNCTION_MINUS; } 18 {DIGIT}* { printf("got number\n"); return NUMBER; } 19 %% 20 21 22 void yyerror(char* s) { 23 printf("error %s \n",s); 24 } 25 26 int yywrap() { 27 return -1; 28 } 29 [root@lex total]#
这个程序说明了数字、加号、减号的识别规则
同时,为了让yylex()可以读入字符串而不是读入文件,覆盖了 YY_INPUT。
Bison(Yacc)程序:
1 [root@lex total]# cat parser.y 2 %{ 3 #include <stdio.h> 4 extern void yyerror(char* s); 5 extern int yylex(); 6 extern int readInputForLexer(char* buffer,int *numBytesRead,int maxBytesToRead); 7 %} 8 9 %token FUNCTION_PLUS FUNCTION_MINUS NUMBER 10 11 %% 12 13 expression: 14 NUMBER FUNCTION_PLUS NUMBER { printf("got plus expression! Yay!\n"); } 15 | 16 NUMBER FUNCTION_MINUS NUMBER { printf("got minus expression! Yay!\n");} 17 ; 18 %% 19 [root@lex total]#
这个程序说明了两个表达式: 加法(NUMBER FUNCTION_PLUS NUMBER) 和 减法(NUMBER FUNCTION_MINUS NUMBER)。
主程序:
1 [root@lex total]# cat myparser.c 2 #include <stdio.h> 3 #include <string.h> 4 5 int yyparse(); 6 int readInputForLexer( char *buffer, int *numBytesRead, int maxBytesToRead ); 7 8 static int globalReadOffset; 9 // Text to read: 10 static const char *globalInputText = "23 - 5"; 11 12 int main() { 13 globalReadOffset = 0; 14 yyparse(); 15 return 0; 16 } 17 18 int readInputForLexer( char *buffer, int *numBytesRead, int maxBytesToRead ) { 19 int numBytesToRead = maxBytesToRead; 20 int bytesRemaining = strlen(globalInputText)-globalReadOffset; 21 int i; 22 if ( numBytesToRead > bytesRemaining ) { numBytesToRead = bytesRemaining; } 23 for ( i = 0; i < numBytesToRead; i++ ) { 24 buffer[i] = globalInputText[globalReadOffset+i]; 25 } 26 *numBytesRead = numBytesToRead; 27 globalReadOffset += numBytesToRead; 28 return 0; 29 } 30 [root@lex total]#
在主程序中,为了能够让 yylex读取字符串,声明了 readInputForlexer函数。
根据YACC的约定,yyparse()会去调用 yylex()。而yylex()调用 readInputForLexer,一次一次地返回给yyparse。
编译和执行:
yacc -d parser.y lex lexer.l gcc -o myparser *.c
./myparser
执行结果:
[root@lex total]# ./myparser got number got minus got number got minus expression! Yay! [root@lex total]#