Lex與Yacc的結合

來源:互聯網
上載者:User

Lex與Yacc的結合


用Lex與Yacc結合起來使用可以很方便的產生一個新語言的編譯器,不過現在很多國內的圖書裡面對它們的介紹是分開的,單獨的介紹也是比較含糊,不是很清晰。把他們如何結合的介紹更是少的可憐。我用他們做了一個能識別整型數值的加、減、乘、除的編譯器。把我的心得寫在下面,供大家參考。

首先,我就不介紹Lex的文法規則了,因為在一些書上這些是重點介紹的內容,我先把Lex的來源程式寫在下面,然後講解。
%{
#define NUMBER 257
#define PLUS 258
#define SUB 259
#define CHEN 260
#define DIV 261
#define LKUO 262
#define YKUO 263
#include <stdio.h>
#include <stdlib.h>
extern int  yylval;
%}
number  [0-9]+
%%
{number}    {yylval=atoi(yytext);printf("%s",yytext);return NUMBER;}
"+"            {printf("%s",yytext);return PLUS;}
"-"            {printf("%s",yytext);return SUB;}
"*"            {printf("%s",yytext);return CHEN;}
"/"            {printf("%s",yytext);return DIV;}
"("        {printf("%s",yytext);return  LKUO;}
")"        {printf("%s",yytext);return  YKUO;}
%%

其中
#define NUMBER 257
#define PLUS 258
#define SUB 259
#define CHEN 260
#define DIV 261
#define LKUO 262
#define YKUO 263
是在Yacc中使用的記號,該記號必須先在YACC中定義,然後,在LEX中使用,YACC告訴LEX需要使用的符號,使用YACC  –d  檔案.y來產生一個yytab.h的檔案,在該檔案中內容就是上面的一系列#define 。。。。
extern int  yylval; 告訴LEX要引用外部的變數yylval。
%%
{number}    {yylval=atoi(yytext);printf("%s",yytext);return NUMBER;}
"+"            {printf("%s",yytext);return PLUS;}
"-"            {printf("%s",yytext);return SUB;}
"*"            {printf("%s",yytext);return CHEN;}
"/"            {printf("%s",yytext);return DIV;}
"("        {printf("%s",yytext);return  LKUO;}
")"        {printf("%s",yytext);return  YKUO;}
%%
這一部分就不解釋了。
下面是*.y檔案了
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define YYSTYPE int
    %}
%token NUMBER
%token PLUS
%token SUB
%token PLUS
%token CHEN
%token DIV
%token LKUO
%token YKUO
%left  PLUS SUB
%left  CHEN   DIV
%%
com: exp  {printf("=%d/n",$1);};
exp:  exp  PLUS fac {$$=$1+$3;}
         |exp  SUB fac {$$=$1-$3;}
         |fac{$$=$1;};
fac:fac  CHEN term {$$=$1*$3;}
      |fac  DIV term {$$=$1/$3;}
       |term  {$$=$1;};
term:LKUO exp YKUO  {$$=$1;}
         | NUMBER   {$$=$1;};
%%
extern int yylex();
int yyparse();
main()
{
return yyparse();
}
yyerror()
{printf("sytax error");}
其中#define YYSTYPE  int是定義記錄記號的值棧的類型為int,當然你也可以定義其他的類型。
我們命名第一個檔案為sample.l,用命令pclex  sample.l 處理,產生sample.c檔案。
然後我們命名第二個檔案為sample1.y,用命令pcyacc  -v  -d  sample1.y
產生sample1.c、yytab.h、yy.lrt(YACC的分析表檔案)。

用vc++或者tc編譯一個工程,這個工程包含這兩個檔案*.c檔案,其中在tc中編譯這個工程的時候,sample1.c為primary  file(該選項在tc中的compile項中設定),產生一個可執行檔檔案。如niu1.exe,然後編輯一個niu.txt檔案,niu.txt檔案就是需要識別的數學運算式。如下面的例子:
niu.txt  內容如下
5-2+3*22/2+2-3
用niu1<niu.txt執行結果如:

比如niu.txt的內容如下:

用一個錯誤的文法試試
如果niu.txt的內容如下:
5-3+2+ / 4*2+4   紅色代表文法有錯誤的地方運行結果如下

我以sytax error代表語法錯誤。

該編譯器還有許多不完善的地方,不過它已經勾勒出了,LEX與YACC結合使用的一個架構,如果你感興趣的話,可以逐步的完善它。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.