LEX和YACC的使用(例子)
1、简单C语言的词法分析程序;
%{
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
%}
digit [0-9]
letter [A-Za-z]
other_char [!-@\[-~]
id ({letter}|[_])({letter}|{digit}|[_])*
string {({letter}|{digit}|{other_char})+}
int_num {digit}+
%%
[ |\t|\n]+
"auto"|"double"|"int"|"struct"|"break"|"else"|"long"|"switch"|"case"|"enum"|"register"|"typedef"|"char"|"extern"|"return"|"union"|"const"|"float"|"short"|"unsigned"|"continue"|"for"|"signed"|"void"|"default"|"goto"|"sizeof"|"do"|"if"|"static"|"while"|"main" {Upper(yytext,yyleng);printf("%s,NULL\n",yytext);}
\"([!-~])*\" {printf("CONST_string,%s\n",yytext);}
-?{int_num}[.]{int_num}?([E][+|-]?{int_num})? {printf("CONST_real,%s\n",yytext);}
"0x"?{int_num} {printf("CONST_int,%s\n",yytext);}
","|";"|"("|")"|"{"|"}"|"["|"]"|"->"|"."|"!"|"~"|"++"|"--"|"*"|"&"|"sizeof"|"/"|"%"|"+"|"-"|">"|"<"|">="|"<="|"=="|"!="|"&"|"^"|"|"|"&"|"||"|"+="|"-="|"*="|"/="|"%="|">>="|"<<="|"&="|"^="|"|="|"=" {printf("%s,NULL\n",yytext);}
{id} {printf("ID,%s\n",yytext);}
{digit}({letter})+ {printf("error1:%s\n",yytext);}
%%
#include <ctype.h>
Upper(char *s,int l)
{
int i;
for(i=0;i<l;i++)
{
s[i]=toupper(s[i]);
}
}
yywrap()
{
return 1;
}
注意:要得到输出信息,需要自行添加main函数,lex默认的main函数没有输出的。main函数的写法与C语言的类似,要定义
输入流指针yyin(如:yyin=(FILE*)fopen("text.txt","rt") )。
2、算术表达式的分析程序:
Lex程序:
%{
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define false 0
#define ture 1
#include "myYacc.tab.h"
extern int lexverbose;
extern int linecount;
%}
digit [0-9]
letter [a-zA-Z]
%%
{digit}+\.{digit}* {
yylval.real=(float)atof(yytext);
if(lexverbose)
printf("real:%g\n",yylval.real);
return(number);
}
\+ {
yylval.chr=yytext[0];
if(lexverbose)
printf("opterator:%c\n",yylval.chr);
return('+');
}
\- {
yylval.chr=yytext[0];
if(lexverbose)
printf("oprator:%c\n",yylval.chr);
return('-');
}
\* {
yylval.chr=yytext[0];
if(lexverbose)
printf("oprator:%c\n",yylval.chr);
return('*');
}
\/ {
yylval.chr=yytext[0];
if(lexverbose)
printf("oprator:%c\n",yylval.chr);
return('/');
}
"(" {
yylval.chr=yytext[0];
if(lexverbose)
printf("separator:%c\n",yylval.chr);
return('(');
}
")" {
yylval.chr=yytext[0];
if(lexverbose)
printf("separtor:%c\n",yylval.chr);
return(')');
}
; {
return(';');
}
\n {
printf("line %d\n",linecount);
/* linecount++; */
return('\n');
}
[ \t]+ {
printf("lexical analyzer error\n");
}
quit {
printf("Bye!\n");
exit(0);
}
%%
int yywrap()
{
return(1);
}
Yacc程序;
%{
#include <ctype.h>
#include<stdio.h>
#define MSDOS
int linecount;
extern int yylex();
extern int yyerror();
%}
%union{
char chr;
char *str;
int integer;
float real;
double dbl;
}
%token number
%type <real> expr number
%left '+' '-'
%left '*' '/'
%right uminus
%%
lines: lines expr'\n'
{
printf("line %d:%g\n",linecount++,$2);
}
|lines'\n'
{
linecount++;
}
|
;
expr: expr'+'expr
{
$$=$1+$3;
}
|expr '-' expr
{
$$=$1-$3;
}
|expr '*' expr
{
$$=$1*$3;
}
| expr '/' expr
{
$$=$1/$3;
}
| '(' expr ')'
{
$$=$2;
}
| '-' expr %prec uminus
{
$$=-$2;
}
| number
;
%%
int yyerror(s)
char *s;
{
fprintf(stderr,"syntactic error:%s\n",s);
return 0;
}
C的主程序:
#include <stdlib.h>
#include <stdio.h>
int lexverbose=0;
extern int yyparse();
int main(int argc, char* argv[])
{
extern FILE *yyin;
printf("Compiling...!\n");
if((yyin=fopen("exprTest.txt","rt"))==NULL){
perror("can not open file test.txt\n") ;
exit(1);
}
if (yyparse()==1){
fprintf(stderr,"parser error\n");
exit(1);
}
printf("yyparse() completed successfully!\n");
return 0;
}
执行时,将lex和yacc编译生成的C程序与最后的c语言主程序一起添加到一个空的C的工程中,再用GCC编译即可。
以上实例在DEV C++ 4.9.9.2 下调试成功。