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 下调试成功。

posted @ 2011-11-21 09:48  beishuai  阅读(3535)  评论(1编辑  收藏  举报