lex和Yacc详解

合集下载

Lex和Yacc从入门到精通(PDF)

Lex和Yacc从入门到精通(PDF)

Lex和Yacc从入门到精通熊春雷Abstract在开发程序的过程中经常会遇到文本解析的问题,例如:解析C语言源程序,编写 脚本引擎等等,解决这种文本解析的方法有很多,一种方法就是自己手动用C或者 C++直接编写解析程序,这对于简单格式的文本信息来说,不会是什么问题,但是 对于稍微复杂一点的文本信息的解析来说,手工编写解析器将会是一件漫长痛苦 而容易出错的事情。

本系列文档就是专门用来由浅入深的介绍两个有名的Unix工 具Lex和Yacc,并会一步一步的详细解释如何用这两个工具来实现我们想要的任何 功能的解析程序,为了方便理解和应用,我会在该系列的文章中尽可能的采用具 体可行的实例来加以阐释,而且这种实例都是尽可能的和具体的系统平台无关的 ,因此我采用命令行程序作为我们的解析程序的最终结果。

1、环境配置篇开发Lex和Yacc程序最需要的程序就是lex和yacc了,如果你是Unix或者Linux系统,则 系统自带了这两个工具,无需安装,不过值得说明的是GNU/Linux下面的Lex是flex, 而Yacc则是bison。

另外需要的就是一个C/C++语言编译器,由于我们采用的是GNU的 lex和yacc,所以,理所当然的我们就使用GNU的编译器了,如果是Unix或者Linux系统 ,那么编译器应该已经安装了。

在这里我重点讨论的是Windows系统环境下的Lex和 Yacc程序的开发,至于为什么选择Windows系统作为开发平台,则是为了尽可能的让初 学者容易入门。

1.1.必备工具言归正传,首先列举Windows平台下面Lex和Yacc开发环境所需要安装的程序:1.Lex(flex.exe)和Yacc(bison.exe)环境2.C/C++编译器1.2.flex和bison值得说明的是,flex.exe和bison.exe是UnxUtils包中的文件,已经将许多 Unix/Linux平台的程序都移植到了Windows平台,可以直接到UnxUtils网站下载,下载解压缩之后在系统的PATH环境变量中增加UnxUtils所有的exe文件所在的目录,使 得DOS命令行可以直接搜索到flex.exe和bison.exe,除此之外还需要从网络上下载 bison需要的bison.simple和bison.hairy两个文件,并且还要分别设置环境变量 BISON_HAIRY指向bison.hairy,BISON_SIMPLE指向bison.simple。

Lex和Yacc在软PLC开发系统中的应用

Lex和Yacc在软PLC开发系统中的应用
p r adt g t f o P CSdv l me t y t T el g a e ob o idiIs u t nL t I) hc at n re o f L ’ e e p n s m. h n ug e mp e t ci i ( w i i a Sl o s e a t c l sn r o s L hs
asna n l e wi e e f ac( e a ohr o ir o ir id c se e ae. hnP C y t a a zr t t l o Y c Y t n te c mp e —c mpe) i u sdi t p r T e L x y hhhp l l s s n h p
中 图 分 类 号 :P 7 T23 文 献标 识码 : A
Ap l a i n o x a d Ya c i o t p i t fLe n c n S fPLC g De eo m e tS se c o v l p n y tm
L h a g,W ANG n —ha g,MA o g b IS u n Yo g z n Xi n — o
p o r m’ c mpl g i su i i t . w o a tm aia y d v lp a tk n a a z rwi e h l fL x a d r g a S o i s t d e f s y Ho t u o t l e eo o e n l e t t ep o e n i n d r l c y h h
维普资讯

控 制 与检 测 ・
组 床与自 化 合机 动 加工技 术
文 章 编 号 :0 1— 2 5 20 )9— 0 0— 5 10 2 6 (0 6 0 0 3 0
Lx Y c 在软 P C开发 系统中 的应 用 e 和 ac L

应用Lex与Yacc实现设备描述分析

应用Lex与Yacc实现设备描述分析

于 17 9 5年研制开发的一个编译程 序 , 能够 自动生成词
法分析程序和语 法分 析程序 的工具 。
1 1 L x和 Y c . e a c的 基 本 原 理
1 11 L x . . e
信接 口对 H R A T智能仪表进行配置 。每个厂家生产不 同类 型的仪 表 , 种 型号 的仪 表 都具 有不 同的特性 。 各
0 引 言
H R A T现 场 总 线 协 议 被 广 泛 地 应 用 于 压 力 、 度 温
1 基本 原理
Lx和 Y c e ac是美 国 贝 尔实 验 室 的 L s ek和 Jh sn ono
和流量等智能仪表之 中。仪表在实际应用前要进行 配
置 , 态 软 件 可 以在 台 式 电 脑 或 者 掌 上 电脑 上 通 过 通 组
实现 分析设 备 描述 , 立多 种设 备的运 行数 据 , H R 建 使 A T现 场总线 协议 的组 态软 件 能够 配置 多 种设 备 。讨 论 了 Lx和 Y c e ac的词法 分 析 和语 法 分析技 术及设 备 描述语 言 , 功开 发 了能够分 析 H R 协 议设 备描 述 的组态 软件 , 成 AT 实现 了 H R A T设备 的互 操作 。
关键 词 :设 备描 述 H R A T协议 变送 器 文献 标志码 :B
中 图分类号 :T 2 6+ 1 P1 .
Ab ta t:Th e ie d s rpin o xen lc aa trsiso sr c e d vc ec t fe tra h r ce t fHART ed e uime th lste h s o ue p r t l kn so ed e i— i o i c i f l q p n ep h o tc mp tro e aeal i d ff l q p i u me t I r e o i lme titr p r bl yo h o tc mp tr。b sn e iae o l fL xa d Ya c。a ayi fd vc e c pin a d n . n od rt mp e n ne o ea it fteh s o ue i y u igd dc td toso e n c n lsso e ied s r to i n etb ih n fo eain aao h q ime taei lme td.r1 s a o e ie a ec n g r d b o g rto ot r eb s d o sa ls me to p rt a d t f ee up n r mpe ne ol t I u 。v r usd vc sc n b o f u e yc n u ain s f 1 i i i f wa a e n HART rtc 1 T e tc n lge flxc la ay i d s na n yi fL x a d Ya c a l a e ie d srp in ln u g r ic se p oo o. h e h oo iso e ia n ssa y tx a a sso e c swels d vc e c to a g a e ae ds u s d。 l n l n i tec n g r to f r eta s n lz h o i f u ain s t o wa t na ay eHART d vc ec pin i de eo d s c esul h eitrpea it fHART d vc si lme ・ h c e ie d s r t s v lp u c sfly,t ne o r bl yo i o e i e iei mp e n td. e K e wo d y r s: De ie d s rpin vc ec to i HART rtc l T a s t r po o o rn mit e

LEX和YACC的使用(例子)

LEX和YACC的使用(例子)

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"|"go \"([!-~])*\" {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函数没有输出的。

Lex与Yacc学习(七)之环境配置另一种方式

Lex与Yacc学习(七)之环境配置另一种方式

Lex与Yacc学习(七)之环境配置另⼀种⽅式必备⼯具flex与bison安装运⾏flex-2.5.4a-1.exe 和 bison-2.4.1-setup.exe ⽂件安装⾄D:\Software Files\GnuWin32下,然后按配置环境变量:将路径 D:\Software Files\GnuWin32\bin 复制于Path中。

Cygin安装配置运⾏cyg_win_setup.exe⽂件安装⾄D:\cygwin下,然后配置环境变量:将路径D:\cygwin\bin复制于Path中;注意:在D:\cygwin\bin⽂件夹下,有g++.exe ⼤⼩为1KB 与g++ 3.exe ⼤⼩为95KB ,我们需要把95KB的 g++ 3.exe命名为 g++.exe ,1 KB的g++可删除,或者命名为g++3.exe;同理,有gcc.exe ⼤⼩为1KB 与gcc 3.exe ⼤⼩为95KB ,我们需要把95KB的 gcc 3.exe命名为 gcc.exe ,1 KB的gcc可删除,或者命名为gcc 3.exe 。

必要⽂件复制我们发现D:\cygwin\bin下⾯并没有flex.exe 与bison.exe,因此,(1)将安装好的D:\Software Files\GnuWin32\bin下的flex.exe 与bison.exe复制到D:\cygwin\bin下⾯;(2)再将D:\Software Files\GnuWin32的share⽂件夹复制到D:\cygwin下⾯;(3)将D:\Software Files\GnuWin32\lib下的libfl.a 和 liby.a 复制到D:\cygwin\lib下⾯;检测配置是否成功打开D:\cygwin下的Cygwin.bat 或者系统的cmd,按照以下⽅式检验:环境搭建结束!。

YACC

YACC

yacc(Yet Another Compiler Compiler),是一个经典的生成语法分析器的工具。

是Unix/Linux上一个用来生成编译器的编译器(编译器代码生成器)。

yacc生成的编译器主要是用C语言写成的语法解析器(Parser),需要与词法解析器Lex一起使用,再把两部份产生出来的C程序一并编译。

yacc本来只在Unix系统上才有,但现时已普遍移植往Windows 及其他平台。

分析程序生成器(parser generator)是一个指定某个格式中的一种语言的语法作为它的输入,并为该种语言产生分析过程以作为它的输出的程序。

在历史上,分析程序生成器被称作编译-编译程序( compiler- compiler ),这是由于按照规律可将所有的编译步骤作为包含在分析程序中的动作来执行。

现在的观点是将分析程序仅考虑为编译处理的一个部分,所以这个术语也就有些过时了。

合并 LALR(1) 分析算法是一种常用的分析生成器,它被称作 Yacc( yet another compiler- compiler )。

给出 Yacc 的概貌来,将使用Yacc为 TINY 语言开发一个分析程序。

作为 Yacc 对说明文件中的 %token NUMBER 声明的对应。

Yacc 坚持定义所有的符号记号本身,而不是从别的地方引入一个定义。

但是却有可能通过在记号声明中的记号名之后书写一个值来指定将赋给记号的数字值。

yacc的输入是巴科斯范式(BNF)表达的语法规则以及语法规约的处理代码,Yacc输出的是基于表驱动的编译器,包含输入的语法规约的处理代码部分。

yacc是开发编译器的一个有用的工具,采用LALR(1)语法分析方法。

Yacc最初由AT&T的Steven C. Johnson为Unix操作系统开发,后来一些兼容的程序如Berkeley Yacc,GNU bison,MKS yacc和Abraxas yacc陆续出现。

LEX和YACC入门

LEX和YACC入门
用 %% 符号隔开。第一部分和最后一个部分是宿主语言代 码。中间是由一系列规则构成,
LEX 将这些规则翻译为词法分析器。每一个规则依次包含一 个正则表达式以及该正则表达式得到匹配时要运行的一些代 码。
任何没有得到匹配的文本则简单地拷贝到标准输出。
2020/5/13
6
三、LEX程序设计
LEX正规表达式(1)
expression: value '+' value { System.out.println("Matched a '+' expression.\n"); }
2020/5/13
23
四、YACC程序设计
类似于 LEX, YACC 也有 一套变量和函数可供用户 来进行功能扩展。
YYSTYPE 定义了用来将 值从 lexer 拷贝到解析器 或者 YACC 的 yylval ( 另一个 YACC 变量)的 类型。默认的类型是 int 。 由于字符串可以从
的值。
2020/5/13
26
四、LEX与YACC结合
2020/5/13
27
public static void main(String args[]) {
int n = 1;
mylexer lexer = new mylexer();
if (lexer.yycreate(null)) {
n = lexer.yylex();
}
System.out.println("word count = "+lexer.wordCount);
两个百分号标记指出了 LEX程序中这一段的结束和三段中第二段 的开始。
10

从lexyacc说到编译器(二):flex的使用

从lexyacc说到编译器(二):flex的使用

从lexyacc说到编译器(二):flex的使用二、flex的使用看了第一篇的关于正则表达式的说明后,下面我们就来通过它,使用flex这个词法分析工具来构造我们的编译器的词法分析器.关于lex的教程应该是很多,这里我就简单地介绍一下,然后着重后面的lex和yacc的配合使用以及其技巧.所以,如果你不看了后还是不太明白lex或者yacc的使用,请你自己上网去查查,这方面的教程是很多的.我知道的一篇常见的就是Yacc 与 Lex 快速入门Lex 与 Yacc 介绍它的作者就是Ashish Bansal.Flex就是fast lex的意思.而lex就是Lexical Analyzar的意思.flex 可以在cygwin或者gnupro中找到.它是unix的一个工具,属于GNU 组织产品.网上也可以找到单独可以在windows下用的版本.我们一般把我们的词法扫描程序要扫描的一些单词(token)用正则表达式写好,然后作为lex的输入文件,输入命令flex xxx.l(xxx.l就是输入文件),lex经过处理后,就能得到一个名字叫lex.yy.c的C源代码.这个C源代码文件,就是我们的词法扫描程序.通常lex为我们生成的词法分析器的C源代码都是十分复杂而且庞大的,我们一般根本不会去查看里面的代码(放心好了,flex这个东西不会出错的)下面让我们看看几个我已经使用过的几个lex输入文件.这是一个前段时间我为GBA上的一个RPG游戏写的脚本引擎所使用的lex输入文件(部分)例2.1%{/* need this for the call to atof() below */#include <stdio.h>#include <stdlib.h>#include <math.h>#include "globals.h"%}digit [0-9]number ("-"|"+")?{digit}+hexnumber "0x"({digit}|[a-fA-F])+letter [a-zA-Z]identifier ({letter}|_)({number}|{letter}|_)* newline [\n]whitespace [ \t]+string \"[^"]*\"comment "#"[^#]*"#"%%{string} { return VM_STRING; } "Logo" { return VMIN_LOGO; } "FaceIn" { return VMIN_FACEIN; } "FaceOut" { return VMIN_FACEOUT; } "LoadTile" { return VMIN_LOAD_TILE; } "CreateRole" { return VMIN_CREATE_ROLE; } "ReleaseRole" { return VMIN_RELEASE_ROLE;} "CreateMap" { return VMIN_CREATE_MAP; } "ReleaseMAP" { return VMIN_RELEASE_MAP;} "ShowBitmap" { return VMIN_SHOWBITMAP; } "CreateDialog" { return VMIN_CREATE_DIALOG; }"ReleaseDialog" { return VMIN_RELEASE_DIALOG;}"Fight" { return VMIN_FIGHT; }"Delay" { return VMIN_DELAY; }"PressA" { return VMIN_PRESS_A; }"PressB" { return VMIN_PRESS_B; }"PressR" { return VMIN_PRESS_R; }"PressL" { return VMIN_PRESS_L; }"PressStart" { return VMIN_PRESS_START; }"PressSelect" { return VMIN_PRESS_SELECT;}{number} { return VM_NUMBER; }{whitespace} { /* skip whitespace */ }{identifier} { return VM_ID; }{newline} ;. ;%%int yywrap(){return 1;}这里的lex输入文件一共有三个部分,用%%分开.第一部分中的%{和}%中的内容就是直接放在lex输出C代码中的顶部.我们通过它可以来定义一些所需要的宏,函数和include一些头文件等等.我的这个lex输入文件中也没什么特别的东西,就是常规的C源文件的include头文件%{/* need this for the call to atof() below */#include <stdio.h>#include <stdlib.h>#include <math.h>#include "globals.h"%}第一部分中,除了前面的%{和}%包含的部分,下面的就是正则表达式的定义.看了第一篇的正则表达式,这样你就能够在这里派上用场了.让我们来看看我这里定义的正则表达式:digit [0-9]number ("-"|"+")?{digit}+hexnumber "0x"({digit}|[a-fA-F])+letter [a-zA-Z]identifier ({letter}|_)({number}|{letter}|_)*newline [\n]whitespace [ \t]+string \"[^"]*\"comment "#"[^#]*"#"digit就不用说了,就是0-9的阿拉伯数字定义,第一篇文章中也举了这个例子.number就是digit的1到无限次的重复,再在其前面加上”+”和”-“符号.注意:“a”: 即使a是元字符,它仍是字符a\a: 当a是元字符时候,为字符aa?: 一个可选的a,也就是说可以是a,也可以没有aa|b: a或b(a): a本身[abc]: 字符a,b或c中的任一个[a-d]: a,b,d或者d中的任一个[^ab]: 除了a或b外的任何一个字符.: 除了新行之外的任一个字符{xxx}: 名字xxx表示的正则表达式这里需要特别说明的就是newline [\n]newline就是新行,这里我使用了[]把\n换行号括起来.因为如果我直接用\n表示的话,那么按照上面的规则,那就会看成\和n两个字符,所以我使用了[\n].有些时候newline也被写成[\n]|[\r\n].因为在文本文件中,一般换行一次,那么就是一个\n(0xA),可是在二进制文件中,换行有时候又是\r\n(0xD,0xA)一共两个字符号.第二部分就是定义扫描到正则表达式的动作.这些动作其实就是C代码,它们将会被镶嵌在lex输出的C文件中的yylex()函数中.上面的例子的动作其实十分平常,就是返回一个值.我们在外部使用这个lex为我们生成C代码的时候,只需要使用它的int yylex()函数.当我们使用一次yylex(),那么就会自动去扫描一个匹配的正则表达式,然后完成它相应的动作.这里的动作都是返回一值,那么yylex就会返回这个值.通常默认yylex返回0时候,表示文件扫描结束,所以你的动作中最好不要返回0,以免发生冲突.当然,动作中也可以不返回一值,那么yylex就会完成这个动作后自动扫描下一个可以被匹配的字符串,一直到扫描到文件结束.当扫描到一个可以被匹配的字符串,那么这个时候,全局变量yytext 就等于这个字符串请大家一定记住这些正则表达式的顺序.如果出现一个字符串,可以同时匹配多个正则表达式,那么它将会被定义在前面的正则表达式匹配.所以我一般把字符串string定义在最前面.如果文件中的字符没有被lex输入文件中任何一个字符匹配,那么它会自动地被标准输出.所以大家一定要记住在每个正则表达式处理完毕后,一定要加上{newline}和.这两个正则表达式的动作.好,让我们看看lex为我们输出C文件中提供一些常量Lex 变量例2.2这是<<编译原理与实践>>书中配套的源代码的lex输入文件.大家可以参考一下,作者为它自己定义的一个Tiny C编译所做的词法扫描器./****************************************************//* File: tiny.l *//* Lex specification for TINY *//* Compiler Construction: Principles and Practice *//* Kenneth C. Louden *//****************************************************/%{#include "globals.h"#include "util.h"#include "scan.h"/* lexeme of identifier or reserved word */char tokenString[MAXTOKENLEN+1];%}digit [0-9]number {digit}+letter [a-zA-Z]identifier {letter}+newline \nwhitespace [ \t]+%%"if" {return IF;} "then" {return THEN;} "else" {return ELSE;} "end" {return END;} "repeat" {return REPEAT;} "until" {return UNTIL;} "read" {return READ;} "write" {return WRITE;} ":=" {return ASSIGN;} "=" {return EQ;} "<" {return LT;} "+" {return PLUS;} "-" {return MINUS;} "*" {return TIMES;} "/" {return OVER;} "(" {return LPAREN;} ")" {return RPAREN;} ";" {return SEMI;} {number} {return NUM;} {identifier} {return ID;}{newline} {lineno++;} {whitespace} {/* skip whitespace */} "{" { char c;do{ c = input();if (c == EOF) break;if (c == ‘\n‘) lineno++;} while (c != ‘}‘);}. {return ERROR;}%%TokenType getT oken(void){ static int firstTime = TRUE;TokenType currentToken;if (firstTime){ firstTime = FALSE;lineno++;yyin = source;yyout = listing;}currentToken = yylex();strncpy(tokenString,yytext,MAXTOKENLEN); if (TraceScan) {fprintf(listing,"\t%d: ",lineno); printToken(currentToken,tokenString);}return currentT oken;}这里有点不同的就是,作者用了另外一个getToken函数来代替yylex作为外部输出函数.其中getToken里面也使用了lex默认的输出函数yylex(),同时还做了一些其它的事情.不过我建议大家不要像作者那样另外写自己的结果输出函数,因为在后面,需要和yacc搭配工作的时候,yacc生成的语法分析程序只认名字叫yylex()的词法结果输出函数.if (firstTime){ firstTime = FALSE;lineno++;yyin = source;yyout = listing;}其中的yyin,yyout,source,listing都是FILE*类型.yyin就是要lex 生成的词法扫描程序要扫描的文件,yyout就是基本输出文件(其实我们通常都不用yyout,即使要生成一些输出信息,我们都是自己通过fprintf 来输出)."{" { char c;do{ c = input();if (c == EOF) break;if (c == ‘\n‘) lineno++;} while (c != ‘}‘);}其中,作者的这个Tiny C是以{}来包括注释信息.作者并没有写出注释信息的正则表达式,但是它可以通过检索“{”,然后用lex内部函数input()一一检查 { 后面的字符是不是 } 来跳过注释文字.(C语言的/* */注释文字正则表达式十分难写,所以很多时候我们都用这种方法直接把它的DFA(扫描自动机)写出来).本文就是通过简单地举出两个比较实际的例子来讲解flex输入文件的.再次说明,如果你是第一次接触lex,那么请看看前面我推荐的文章,你可以在IBM的开发者网上查到.下一篇关于yacc于BNF文法的说明也是如此.请大家先参考一下其它标准的教程.。

编译原理之lex,yacc学习

编译原理之lex,yacc学习

编译原理之lex,yacc学习写在前⾯的⼏句废话最近在项⽬的过程中接触了lex 和 yacc,他们可以帮助我们来实现⾃⼰的领域语⾔。

最典型的应⽤就是可以帮助我们来实现⾃定义测试脚本的执⾏器。

但是,这⾥也有⼀个限制,就是测试脚本要做的基本事情必须有现成的C语⾔库来实现,否则就做不到了;如果基本的操作是⽤java来做的,那么还可以⽤Antlr,这⾥不对Antlr做详细介绍。

lex是什么?教科书上把lex的作⽤的作⽤叫做“词法分析 lexical analysis ”,这个中⽂叫法⾮常让⼈看不明⽩(叫做“符号提取”更合适),其实从它的英⽂单词lexical上来看他的意思其实是⾮常清楚的。

lexical,在webster上的解释是:of or relating to words or the vocabulary of a language as distinguished from its grammar and construction。

指的是:⼀种语⾔中关于词汇、单词的,与之相对的是这种语⾔的语法和组织这么来看的话 lexical analysis 的作⽤就应该是语⾔中的词汇和单词分析。

事实上他的作⽤就是从语⾔中提取单词。

放到编程语⾔中来说,他要做的事情其实就是提取编程语⾔占⽤的各种保留字、操作符等等语⾔的元素。

所以他的另外⼀个名字scanner其实更形象⼀些,就是扫描⼀个⽂本中的单词。

lex把每个扫⾯出来的单词叫统统叫做token,token可以有很多类。

对⽐⾃然语⾔的话,英语中的每个单词都是token,token有很多类,⽐如non(名词)就是⼀个类token,apple就是属于这个类型的⼀个具体token。

对于某个编程语⾔来说,token的个数是很有限的,不像英语这种⾃然语⾔中有⼏⼗万个单词。

lex⼯具会帮我们⽣成⼀个yylex函数,yacc通过调⽤这个函数来得知拿到的token是什么类型的,但是token的类型是在yacc中定义的。

lex与yacc快速入门

lex与yacc快速入门

lex与yacc快速⼊门第⼀节、lex和yacc是什么? lex 代表 lexical analyzar(词法分析器),yacc 代表 yet another compiler compiler(编译器代码⽣成器)。

lex和yacc在UNIX下分别叫flex和bison. 可以搜索到很多介绍flex&bison的⽂章,但这类⽂章对初学者来说不太容易看懂。

我们举个简单的例⼦来理解lex和yacc:在linux下,有很多系统配置⽂件,⼀些linux下的软件也有配置⽂件,那么程序是如何读取配置⽂件中的信息的呢?先⽤到lex词法分析器,读取配置⽂件中的关键词(后⾯说到的token标记其实可看做关键词);然后把关键词递交给yacc,yacc对⼀些关键词进⾏匹配,看是否符合⼀定的语法逻辑,如果符合就进⾏相应动作。

上⾯举的例⼦是分析配置⽂件内容的,当然可分析其他⽂件内容,或者制作编译器等。

第⼆节、⼀个简单的lex程序。

1、程序代码。

来看⼀个简单的lex程序,代码见下⾯,这段lex程序的⽬的是:输⼊⼏⾏字符串,输出⾏数,单词数和字符的个数。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25/******************************************** Name : test.l* Date : Mar. 11, 2014* Blog : /lucasysfeng/* Description : ⼀个简单的lex例⼦,输⼊⼏⾏字符串,* 输出⾏数,单词数和字符的个数。

*******************************************//* 第⼀段 */%{int chars = 0;int words = 0;int lines = 0;%}/* 第⼆段 */%%[a-zA-Z]+ { words++; chars += strlen(yytext); } \n { chars++; lines++; }. { chars++; }%%/* 第三段 */main(int argc, char **argv){yylex();printf("%8d%8d%8d\n", lines, words, chars);}程序中yytext是lex变量,匹配模式的⽂本存储在这⼀变量中。

Lex和Yacc解释程序实现方法

Lex和Yacc解释程序实现方法
L I U L i —n a , YANG C h u n —h u i , Z HAN G —J i n g
( 1 ・ T h e 4 7 t h R e s e a r c h, 础 e o fC h i n a E l e c t r o n i c s T e c h n o l o g y G r o u p C o r p o r a t i o n , S h e n y a n g 1 1 0 0 3 2 , C h i n a
中图分 类号 : T N 4 7
文 献标 识码 : B
文章 编号 : 1 0 0 2— 2 2 7 9 ( 2 0 1 3 ) 0 1— 0 0 3 8— 0 3
Th e Ac c o mp l i s h Me t h o d o f L e x a n d Ya c c An a l y s i s Pr O g r a m
s o u r c e p r o g r a m i n t o b e s t o b j e c t c o d e C, e t c . , a r e u s e d w i d e l y .T h e y h a v e m a n y a d v a n t a g e s s u c h a s e a s y
1 引 言
计算机程序输入通 常有一些特定的结构 , 每一 个计算机程序的输入都会被定 义成可接受 的“ 输入
语 言” 。输 入 语 言 可 以是 复 杂 的 可 编 程 语 言 , 也 可 以是 简单 的数 字 。但 是 , 输 人 工 具 总 是 会受 到 不 同 程度 的限制 , 使 用 起来 十分 困难 , 而且 经常 是伴 随着
l i n g p r o g r a m a n d a n a l y s i s p r o g r a m, w h i c h h a v e b e e n u s e f u l a n d s t a n d a r d U NI X p r o ra g m a l r e a d y .L e x a n d Ya c c ,i n c l u d i n g t e x t s e a r c h i n g p r o g r a m s e a r c h i n g f r o m t h e i n p u t i f l e,a n d c o mp i l i n g p r o g r a m t r a n s l a t i n g

Lex与Yacc

Lex与Yacc

|…
进行前执行。
| n { 语义动作n } | 没有{…},则使用缺省的语义动作
; 产生式结束用分号标记
语义动作是C的语句序列(在一对{}中间), 可以引用声明段中定义的C变量、宏等,还可 以使用yacc的伪变量。
规则段(续)
-yacc中的伪变量(类型缺省为整型)
$$ - 产生式左部非终结符的“值”
向前匹配。如果在匹配的模版中的“/”后跟有后 续表达式,只匹配模版中“/”前面的部分。如: 如果输入 A01,那么在模版 A0/1 中的 A0 是匹 配的。 将一系列常规表达式分组。
7
常规表达式举例
常规表达式
含义
joke[rs]
匹配 jokes 或 joker。
A{1,2}shis+ 匹配 AAshis, Ashis, Ashiss, Ashisss。
yywrap()
这一函数在文件(或输入)的末尾调用。如果函 数的返回值是1,就停止解析。 因此它可以用 来解析多个文件。代码可以写在第三段,这 就能够解析多个文件。 方法是使用 yyin 文件 指针(见上表)指向不同的文件,直到所有 的文件都被解析。最后,yywrap() 可以返回 1 来表示解析的结束。
FILE* 类型。 它指向记录 lexer 输出的位置。 缺 省情况下,yyin 和 yyout 都指向标准输入和输出。
yytext 匹配模式的文本存储在这一变量中(char*)。
yyleng 给出匹配模式的长度。
yylineno 提供当前的行数信息。(lexer不一定支持。)
14
Lex 函数
yylex() 这一函数开始分析。 它由 Lex 自动生成。
$i - 产生式右部第i个文法符号的“值”

Lex和Yacc简明教程

Lex和Yacc简明教程

和简明教程 Lex Yacc作者 :Thomas Niemann翻译: 傅惠忠目录序言­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­3 导言­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­4 Lex­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­6 理论­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­6练习­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­7 YACC­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­11 理论­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­11练习,第一部分­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­12练习,第二部分­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­15 计算器­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­18 描述­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­18包含文件­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­20Lex­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­21 输入文件Yacc­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­22 输入文件解释器­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­26编译器­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­27图­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­28Lex­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­34 进阶字符串­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­34保留字­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­35lex­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­35 的调试Yacc­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­37 进阶递归­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­37If­Else­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­37 歧义错误信息­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­38继承属性­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­39内含动作­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­39调试Yacc­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­39 参考书目­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­40lex yacc lex yacc本书将教会你如何使用和构造一个编译器。

利用LEX及YACC实现嵌入式SQL分析器

利用LEX及YACC实现嵌入式SQL分析器

收稿日期:2001-12-08作者简介:姚泽勤(1977-),男,硕士研究生,主要研究方向为计算机系统结构。

利用LEX 及YACC 实现嵌入式SO L 分析器姚泽勤1,柏又青2,马建峰1(1.西安电子科技大学计算机学院,陕西西安710071;2.空军工程大学电讯工程学院,陕西西安710077)摘要:Lex 和Yacc 是用来产生词法分析器和语法分析器的工具。

本文讨论了LEX 与YACC 之间的关系,然后讨论了如何利用LEX 和YACC 实现嵌入式SOL 分析器。

在上面的研究基础之上,文章最后给出了利用LEX 和YACC 实现嵌入式SOL 分析器的流程图。

关键词:嵌入式数据库;词法生成器;语法生成器;嵌入式SOL ;有限状态自动机中图分类号:TP314文献标识码:A文章编号:1671-654 (2002)01-0055-04引言从S y base 公司的SOL An y where Studio 7.0到中兴公司的Database1.0,无论是世界著名的数据库专业开发厂商还是国内大的数据库应用厂家,嵌入式数据库都是不可缺少的产品和应用工具。

而评价众多的嵌入式数据库的一个关键就是它支持SOL (结构化查询语言)的程度,一个优秀的嵌入式数据库不仅要能支持标准的SOL 语句,而且要有高的分析和执行效率。

一个高效安全的SOL 编译器是一个优秀嵌入式数据库的核心和基础。

但是直到提出LEX 与YACC 之前,编写一个编译器是一个非常耗时、令人心烦的工作,程序员不得不动手编写处理各种语法处理的函数。

1975年,Lesk 和Johnson 发表了关于LEX 和YACC ,我们可以很方便地对一条语句进行词法和语法分析。

语法分析生成器LEX 是一个UNIX 下的实用工具,它将一个词法分析规则转换为C 函数的实现。

词法分析器读入字符串,根据词法规则,将一个个的word 或字符转换为符合token 。

语法分析器YACC 能够识别的语法是BNF (Backus Naur Form )范式,用户定义一个BNF 类型的语法规则,YACC 将该规则转换为语法分析器,通过在BNF 语法规则中嵌入语法动作,可以建立某种形式的语法树。

Win7下lex_与_yacc的安装配置

Win7下lex_与_yacc的安装配置

Win7下lex_与_yacc的安装配置Win7下lex 与yacc的安装配置一、如何在windows下安装lex。

首先,下载下载flex和bison。

安装时,设定路径最好不要是在Program Files文件夹里面,因为文件夹名字带空格会影响以后的使用。

可如此:安装在c:\gnuwin32下面。

其次,由于我们使用的flex和bison都是GNU的工具,所以为了方便,采用的C/C++编译器也采用GNU的编译器GCC,目前Windows平台的GCC主要是MinGW编译器。

安装过程中,会自动开启控制台,仅需稍等片刻,任其自动完成。

安装完毕后,将c:\gnuwin32\lib里面的libfl.a和liby.a复制到C:\MinGW\lib里面。

再者,设置环境变量。

现在该安装的都已安装完毕,那么我们该设置环境变量了。

右键点击“计算机”,“属性”、“高级系统设置”、“环境变量”,在下面系统变量里面找到PATH,修改,在后面加上c:\gnuwin32\bin和C:\MinGW\bin。

注意每一个路径是用分号分隔的,然后写第一个路径,然后分号,第二个路径。

如果你的安装的目录和我不一样,就对应修改。

开始两个简单的文件来测试安装是否成功。

1) 新建文本文件,更改名称为lex.l,敲入下面代码%{int yywrap(void);%}%%%%int yywrap(void){return 1;}2) 新建文本文件,更改名称为yacc.y,敲入下面代码%{void yyerror(const char *s);%}%%program:;%%void yyerror(const char *s){}int main(){yyparse();return 0;}打开控制台,进入到刚才所建立文件(lex.l,yacc.y)所在的文件夹。

输入flex lex.l输入bison yacc.y如果看到当前文件夹上多了两个文件(yacc.tab.c,lex.yy.c),那么说明lexyacc已经安装配置成功。

Lex工具

Lex工具

Lex工具是一种词法分析程序生成器,它可以根据词法规则说明书的要求来生成单词识别程序,由该程序识别出输入文本中的各个单词。

1、lex程序的结构-定义部分-规则部分-用户子程序部分其中规则部分是必须的,定义和用户子程序部分是任选的。

(1) 定义部分定义部分起始于"%{"符号,终止于"%}"符号,其间可以是包括include语句、声明语句在内的C语句。

%{#include "stdio.h"#include "y.tab.h"extern int lineno;%}(2) 规则部分规则部分起始于"%%"符号,终止于"%%"符号,其间则是词法规则。

词法规则由模式和动作两部分组成。

模式部分可以由任意的正则表达式组成,动作部分是由C语言语句组成,这些语句用来对所匹配的模式进行相应处理。

需要注意的是,lex将识别出来的单词存放在yytext[]字符数据中,因此该数组的内容就代表了所识别出来的单词的内容。

%%[\t] {;}[0-9]+\.?|[0-9]*\.[0-9]+{ sscanf(yytext,"%1f", &yylval.val);return NUMBER; }\n { lineno++;return '\n'; }. { return yytex+[0]; }%%(3) 用户子程序部分用户子程序部分可以包含用C语言编写的子程序,而这些子程序可以用在前面的动作中,这样就可以达到简化编程的目的。

下面是带有用户子程序的lex程序片段。

"/*" skipcmnts();. /* rest of rules */%%skipcmnts(){for ( ; ; ){while (input()!='*');if(input()!='/')unput(yytext[yylen-1]);else return;}2、lex工具的使用方法首先编写一个lex程序vi lex.l%{#include "stdio.h"%}%%[\n] ;[0-9]+ printf("Interger: %s \n",yytext);[0-9]*\.[0-9]+ printf("Float: %s\n",yytext);[a-zA-Z][a-zA-Z0-9]* printf("Word:%s\n",yytext);. printf("Other symbol:%c\n",yytext[0]);%%然后使用lex将lex.l转换成C语言程序$lex lex.l使用上述命令产生的C语言程序为lex.yy.c然后使用C编译程序将lex.yy.c编译成可执行程序regn$cc -c lex.yy.c$cc lex.yy.o -ll -o regn下面可以使用regn来识别单词$vi testfilex=355y=113p=x/y# ./regn < testfileWord:xOther symbol:=Interger: 355Word:yOther symbol:=Interger: 113Word:pOther symbol:=Word:xOther symbol:/Word:y#yacc工具--------yacc工具是一种语法分析程序生成器,它可以将有关某种语言的语法说明书转换成相应的语法分析程序,由该程序完成对相应语言中语句的语法分析工作。

编译原理 lex和yacc的综合设计 python

编译原理 lex和yacc的综合设计 python

编译原理lex和yacc的综合设计python
1、Lex和Yacc是一种强大的词法分析和语法分析技术,它们常用于编译器的开发和编写编译器前端。

它们分别可以分析和解释输入字符流,并产生相应的输出。

Lex是一个词法分析器,它可以将输入字符流分解为令牌(即识别的节点),这些令牌可以用于编写解释器或编译器的前端。

Yacc则是一种用来构建语法分析器的工具,它可以识别输入的令牌序列,并生成相应的程序。

2、编译原理是编译器的最小系统,它涉及源程序的分析和分解,目标程序的生成和优化,以及中间代码的翻译。

Lex和Yacc则是用来处理字符流和语法检查的两个有力工具,在处理中间代码生成和优化方面非常有用,是编译器的核心部分。

3、Lex和Yacc的综合设计一般需要借助某种语言将可执行模块链接起来,最常用的技术是使用C,C是一种高性能语言,可以让开发者实现快速迭代,也可以利用其标准库实现代码复用,因此是完成Lex和Yacc综合设计的最佳语言。

4、Python是一种脚本语言,不适合用于编写Lex和Yacc综合设计,因为Python 并不专业,不能满足低级程序设计的需求,处理过程中往往性能不佳。

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Lex和Y acc工具介绍
――编译原理的实用工具1.词法分词器生成工具lex
Lex的主要功能是生成一个词法分析器(scanner)的C源码。

描述词法分析器的文件,经过lex编译后,生成一个lex.yy.c的文件,然后由C编译器编译生成一个词法分析器。

词法分析器,简单来说,其任务就是将输入的各种符号,转化成相应的标识符(token),转化后的标识符很容被后续阶段处理。

过程如错误!未找到引用源。

图1
现在这个lex 文件可以用来生成一个统计行数、字符个数和单词个数的工具。

规则段是由正则表达式和相应的动作组成的。

p 1 {action 1}
p 2 {action 2
}
……
p n {action n }
值得注意的是,lex 依次尝试每一个规则,尽可能地匹配最长的输入流。

如果有一些内容根
可以看出lex的确按照最长的规则匹配。

程序段部分放一些扫描器的其它模块,比如一些动作执行时需要的模块。

也可以在另一个程序文件中编写,最后再链接到一起。

生成C代码后,需用C的编译器编译。

连接时需要指定链接库。

gcc的连接参数为 -ll。

2.正则表达式
正则表达式可以描述有穷状态自动机(Finite Automata)接受的语言,也就是定义一个可以接受的串的集合。

转义字符(也称操作符):
" \ [ ] ^ - ? . * + | ( ) $ / { } % < >
这些符号有特殊含义,不能用来匹配自身。

如果需要匹配的话,可以通过引号(’’)或者转义符号(\)来指示。

比如
C”++”
C\+\+
都可以匹配C++。

非转义字符:所有除了转义字符之外的字符都是非转义字符。

一个非转义字符可以匹配自身。

比如
integer
匹配文本中出现的integer。

通配符:通配符就是”.”(dot),可以匹配任何一个字符。

字符集:用一对[]指定的字符构成一个字符集。

比如[abc]表示一个字符集,可以匹配a、b、c中的任意一个字符。

使用–可以指定范围。

比如[a-z]表示可以匹配所有小写字母的字符集。

重复:
选择和分组:|cd。

3.文法分析器生成工具yacc
简单来说,yacc(Yet Another Compiler-Compiler)就是编译器的编译器。

Yacc是一个通用的工具,能够根据用户指定的规则,生成一个词法分析程序。

yacc能识别LALR(1)且无歧义的文法,它的输入是词法分析器的输出。

我们知道,生成词法分析器是lex分内的事,因此lex和yacc常常珠联璧合。

A表示非终结符名,BODY表示产生式和动作。

产生式包括非终结符和终结符,终结符用’’引用。

一些转义字符,比如’\r’,’\n’等,和C里面的表示是一样的。

动作(action)则是在输入被当前规则识别出来时而执行的。

动作实际上就是C的代码,写在{ }中。

为了沟通词法分析器和动作,yacc引入了形式变量,以$开头。

如果希望获得词法分析器和前面的动作返回的值,我们可以使用$1,$2,…。

$i表示一条规则右侧第i个单元的值。

比如有这样的一条规则,
程序段放一些其它的程序,也可以省略,连%%都可以不要。

连接时需要指定连接库,gcc的参数为-ly。

让我们看一个经典的例子,它实现一个简单的计算器:
%{
# include <stdio.h>
# include <ctype.h>
int regs[26];
int base;
%}
%start list
%token DIGIT LETTER
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS /* supplies precedence for unary minus */
%% /* beginning of rules section */
list : /* empty */
| list stat '\n'
| list error '\n'
{ yyerrok; }
;
stat : expr
{ printf( "=%d\n", $1 ); }
| LETTER '=' expr
{ regs[$1] = $3; }
;
expr : '(' expr ')'
{ $$ = $2; }
| expr '+' expr
{ $$ = $1 + $3; }
| expr '-' expr
{ $$ = $1 - $3; }
| expr '*' expr
{ $$ = $1 * $3; }
| expr '/' expr
{ $$ = $1 / $3; }
| expr '%' expr
{ $$ = $1 % $3; }
| expr '&' expr
{ $$ = $1 & $3; }
| expr '|' expr
{ $$ = $1 | $3; }
| '-' expr %prec UMINUS
{ $$ = - $2; }
| LETTER
{ $$ = regs[$1]; }
| number
;
number : DIGIT
{ $$ = $1; base = ($1==0) ? 8 : 10; }
| number DIGIT
{ $$ = base * $1 + $2; }
;
%% /* start of programs */
yylex() { /* lexical analysis routine */
/* returns LETTER for a lower case letter, yylval = 0 through 25 */ /* return DIGIT for a digit, yylval = 0 through 9 */
/* all other characters are returned immediately */
int c;
while( (c=getchar()) == ' ' ) { /* skip blanks */ }
/* c is now nonblank */
if( islower( c ) ) {
yylval = c - 'a';
return ( LETTER );
}
if( isdigit( c ) ) {
yylval = c - '0';
return( DIGIT );
}
return( c );
}
例错误!未定义书签。

example.y
事实上,如果你熟练掌握Lex 和Yacc 的话,它们的强大功能使创建FORTRAN 和C 的编译器如同儿戏。

所以,掌握Lex 和Yacc对学好编译原理作用极大,因为编译原理这门课程并不仅仅是讲解原理的课程,而是一门实践性很强的学科,故拥有好的工具,才能使你的学习更上一层楼。

相关文档
最新文档