Lex工具
-------
Lex工具是一种词法分析程序生成器,它可以根据词法规则说明书的要求来生成单词识别程序,由该程序识别出输入文本中的各个单词。
1、lex程序的结构
-定义部分
-规则部分
-用户子程序部分
其中规则部分是必须的,定义和用户子程序部分是任选的。
(1)定义部分
定义部分起始于"%{"符号,终止于"%}"符号,其间可以是包括include语句、声明语句在内的C语句。
%{
#include"stdio.h"
#include"y.tab.h"
externintlineno;
%}
(2)规则部分
规则部分起始于"%%"符号,终止于"%%"符号,其间则是词法规则。词法规则由模式和动作两部分组成。模式部分可以由任意的正则表达式组成,动作部分是由C语言语句组成,这些语句用来对所匹配的模式进行相应处理。需要注意的是,lex将识别出来的单词存放在yytext[]字符数据中,因此该数组的内容就代表了所识别出来的单词的内容。
%%
[/t]{;}
[0-9]+/.?|[0-9]*/.[0-9]+
{sscanf(yytext,"%1f",&yylval.val);
returnNUMBER;}
/n{lineno++;return'/n';}
.{returnyytex+[0];}
%%
(3)用户子程序部分
用户子程序部分可以包含用C语言编写的子程序,而这些子程序可以用在前面的动作中,这样就可以达到简化编程的目的。下面是带有用户子程序的lex程序片段。
"/*"skipcmnts();
./*restofrules*/
%%
skipcmnts()
{
for(;;)
{
while(input()!='*');
if(input()!='/')
unput(yytext[yylen-1]);
elsereturn;
}
2、lex工具的使用方法
首先编写一个lex程序
vilex.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("Othersymbol:%c/n",yytext[0]);
%%
然后使用lex将lex.l转换成C语言程序
$lexlex.l
使用上述命令产生的C语言程序为lex.yy.c
然后使用C编译程序将lex.yy.c编译成可执行程序regn
$cc-clex.yy.c
$cclex.yy.o-ll-oregn
下面可以使用regn来识别单词
$vitestfile
x=355
y=113
p=x/y
#./regn<testfile
Word:x
Othersymbol:=
Interger:355
Word:y
Othersymbol:=
Interger:113
Word:p
Othersymbol:=
Word:x
Othersymbol:/
Word:y
#
yacc工具
--------
yacc工具是一种语法分析程序生成器,它可以将有关某种语言的语法说明书转换成相应的语法分析程序,由该程序完成对相应语言中语句的语法分析工作。
1、yacc程序结构
在使用yacc工具前,必须首先编写yacc程序,因为有关语法分析程序是根据yacc程序生成的。yacc程序实际上是有关语法规则的说明书,它也是由定义部分、规则部分和子程序部分组成的。yacc程序的定义部分类似于lex程序的定义部分,只是在其后可带有yacc声明,其中包括词法单词、语法变量、优先级和结合性信息。yacc程序的规则部分由语法规则和相应的动作组成,子程序部分可以包括在前面规则部分用到的子程序定义。接下来是main主程序,它调用yyparse子程序来对输入进行语法分析,而yyparse反复地调用yylex子程序来获得输入单词,在语法出错时可通过yyerror子程序来处理。
2、yacc工具的使用方法
实例:我们将yacc程序分成片段,把这些片段组合在一起就是yacc程序。我们要使用的语法规则是一个有关四则运算的语法规则,可用BNF范式描述
list:expr/n
listexpr/n
expr:NUMBER
expr+expr
expr-expr
expr*expr
expr/expr
(expr)
其含义是list是一个表达式序列,每个后面带有一个新行。表达式是一个数值,或是由运算符连起来的两个表达式,以及用圆括号括起来的表达式。
下面是有关上述语法规则的yacc程序片段。
$vihoc.y
%{
#defineYYSTYPEdouble
%}
%tokenNUMBER
%left'+''-'
%left'*''/'
%%
list:
|list'/n'
|listexpr'/n'{printf("/t%.8g/n",$2);}
;
expr:NUMBER{$$=$1;}
|expr'+'expr{$$=$1+$3;}
|expr'-'expr{$$=$1-$3;}
|expr'*'expr{$$=$1*$3;}
|expr'/'expr{$$=$1/$3;}
|'('expr')'{$$=$2;}
%%
上述yacc程序片段实际上是它的定义部分和规则部分。在yacc声明部分,%tokenNUMBER表明了NUMBER是一个单词符号,%left则表明了运算符号的左结合性,并且'*'和'/'和优先级比'+'和'-'的优先级高。在yacc程序的规则部分,备用规则是用'|'隔开的,规则中的动作实际上是C语句序列,其中$n(即$1,$2等)是用来引用规则中的第几个成份,而$$则代表了整个规则的返回值。
下面的yacc程序片段是main主程序
#include<stdio.h>
#include<ctype.h>
char*progname;
intlineno=1;
main(argc,argv)
intargc;
char*argv[];
{progname=argv[0];
yyparse();
}
main主程序调用yyparse子程序来处理来处理输入,而yyparse又是通过yylex子程序来获得输入单词并通过yyerror子程序来报告出错信息。下面是有关这两个子程序的yacc程序片段
yylex()
{intc;
while((c=getchar())==''||c=='/t');
if(c==EOF)
return0;
if(c=='.'||isdigit(c)){
ungetc(c,stdin);
scanf("%lf",&yylval);
returnNUMBER;
}
if(c=='/n')
lineno++;
returnc;
}
yyerror(s)
char*s;
{warning(s,(char*)0);
}
warning(s,t)
char*s,*t;
{fprintf(stderr,"%s:%s",progname,s);
if(t)
fprintf(stderr,"%s",t);
fprintf(stderr,"nearline%d/n",lineno);
}
这样就完成了整个yacc程序
接下来就使用yacc将hoc.y转换成C语言程序
$yacchoc.y
使用上述命令产生的C语言程序为y.tab.c,这时可以使用C编译程序将它编译成可执行程序hoc.
$ccy.tab.c-ohoc
下面是使用hoc的例子
#./hoc
4*3*2
24
(1+2)*(3+4)
21
1/2
0.5
355/133
2.6691729
-3-4
./hoc:Syntaxerrornearline5
上述结果显示中,分别表明了计算结果,最后一次计算出错的原因是由于在规则定义中未来定义单目减运算符号。
附一个项目中的部分代码:
文件expr.lex:
%{
#include "y.tab.h"
#define copy_return(token)/
strcpy(yylval.temp, yytext);/
return token;/
%}
%%
TYPE1_REC {return TYPE1_REC;}
TYPE2_REC {return TYPE2_REC;}
CORP[0-9]* {return CORP;}
HEAD[0-9]* {return HEAD;}
MEMB[0-9]* {return MEMB;}
SHOP[0-9]* {return SHOP;}
= {return EQUAL;}
[A-Z0-9_]+ {copy_return(COLUMN);}
/"[a-zA-Z0-9%_]*/" {copy_return(VALUE);}
"{" {return PL;}
"}" {return PR;}
[ /n/t] {REJECT;}
%%
文件expr.y:
%{
#include <stdio.h>
#include <string.h>
#include "infparser.h"
extern char* yytext;
%}
%union {
char temp[4096];
}
%token TYPE1_REC
%token TYPE2_REC
%token CORP
%token HEAD
%token MEMB
%token SHOP
%token COLUMN
%token VALUE
%token EQUAL
%token PL
%token PR
%type<temp> COLUMN
%type<temp> VALUE
%%
records : record | records record {}
record : type1_rec | type2_rec {}
type2_rec : TYPE2_REC EQUAL PL type2_body PR { CreateType2Rec(); };
type1_rec : TYPE1_REC EQUAL PL type1_body PR {CreateType1Rec();};
type1_body : memb corp head { CreateType1Head(); }
| type1_body shop { AppendShop2Type1(); }
type2_body : memb corp head shop {};
corp : CORP EQUAL PL expressions PR {};
head : HEAD EQUAL PL expressions PR {};
memb : MEMB EQUAL PL expressions PR {};
shop : SHOP EQUAL PL expressions PR {};
expressions : expression | expressions expression {};
expression : COLUMN EQUAL VALUE {
CreateColumnValue($1, $3);
};
%%
int yyerror(char* msg)
{
}
文件Makefile:
INCLUDE = -I../base -I../util -I../db -I../ocilib /
-I$(ORACLE_HOME)/rdbms/demo /
-I$(ORACLE_HOME)/rdbms/public
LDLIBS =../base/libbase.a ../util/libutil.a ../db/libdb.a ../base/libbase.a /
../ocilib/liboracle.a /
-lnsl -lstdc++ -ll -L$(LD_LIBRARY_PATH) -locci -lclntsh
LIBS = ../db/libdb.a ../util/libutil.a ../base/libbase.a
CC= gcc
CFLAGS+= -g
LEX = /usr/bin/lex
YACC = /usr/bin/yacc
.SUFFIXES:.cpp
LEX_SRC = lex.yy.c
YACC_SRC = y.tab.c
SRCS= entry.cpp infparser.cpp
OBJS= $(YACC_SRC:.c=.o) $(LEX_SRC:.c=.o) $(SRCS:.cpp=.o)
.cpp.o:
@$(CC) $(CFLAGS) $(INCLUDE) -c $<
.c.o:
@$(CC) $(CFLAGS) $(INCLUDE) -c $<
PROGRAM = ./jentry
$(PROGRAM):$(OBJS) $(LIBS)
@echo "Loading $(PROGRAM) ..."
$(CC) -o $(PROGRAM) $(OBJS) $(LDLIBS)
@echo "done."
clean:;@rm -f $(OBJS) $(PROGRAM) $(LIBRARY) $(LEX_SRC) $(YACC_SRC)
y.tab.c : expr.y expr.lex
@$(YACC) -d expr.y
lex.yy.o: lex.yy.c
lex.yy.c: expr.lex
@$(LEX) expr.lex
depend:; @makedepend $(INCLUDE) $(SRCS)
分享到:
相关推荐
C语言的lex和yacc工具说明.doc
使用lex和yacc编写shell 在Linux环境中使用C语言编写一个简单的shell命令解释器程序,程序应当具有以下基本特征: 能够执行fg、bg、cd、history、exit等内部命令。 能够执行外部程序命令,命令可以带参数。 使用输入...
在本章中,将会首先给出一个最基本的lex和yacc联合使用的框架,这个基本框架 最主要的特点就是能够正确的被编译。在我学习lex和yacc的过程中经历了无数次 的痛苦折磨,我发现一个一开始足够简单而且能够被正确编译的...
C语言编译器的Lex及Yacc词法及语法分析规则源码
c语言编译器,用lex和yacc工具完成词法分析与语法分析并生成语法树
在windows下可以使用的lex&yacc编译器,使用超级方便
此文档详细介绍了lex和yacc的词法语法分析,附有部分源码,是比较不错的东东。
都是做作业时在维普上下载的,崭新的没怎么看过的,谁要就拿去吧。 利用LEX和YACC实现对SQL查询语句...应用Yacc和Lex工具开发命令分析程序.pdf 软件开发工具LEX和YACC的应用.pdf 语言开发工具Lex和Yacc的分析与应用.pdf
用lex和yacc写的tiny c编译 用lex和yacc写的tiny c编译 用lex和yacc写的tiny c编译
用c++语言和lex-yacc工具实现的文法工具,基本功能相当于一个c语言文法,在平台性编程和可配置编程中作用很大,增加程序的灵活性。
2.lexyacc-simple.tgz,一个简单的simple语言的编译器,可以解释执行,也可编译为栈机器的汇编语言。 3.cc-ansi99-parser_20130313_082654.tgz,一个ansi99标准的C语言的编译器,只进行词法和语法分析,不生成目标...
Lex和Yacc制作的C语言编译器,开发平台为Ubuntu18,可实现简单C语言的编译,包含中间代码的生成、语法树打印等功能
词法分析器的作用是读取源程序生成词法单元,并过滤掉注释和空白。项目中的词法分析使用了lex 。
这里是我所实现的程序的一个最关键部件:C语言头文件解析器。 其中比较关键的就是字节对齐的部分。 一个sizeof我写了很久。C语言的复杂真是可想而知。 而我只写了一个还不是非常完善的头文件解析器。 希望能对其它...
用lex和yacc写成的一个具有解析类C语言的编译器,能够解析基础的C语言文法,并生成相应的语法树,通过语义分析形成中间代码。
Plycc_使用PLY(Python Lex-Yacc)的C语言编译器.zip
实验分为两部分,第一部分是词法分析生成器Lex的构造,第二部分是语法分析生成器Yacc的构造。另外,根据自己开发的工具,生成C语言子集的词法分析器和语法分析器。
lex和yacc编写的c语言编译器 词法分析与语法分析的原始文件扩展: ://www.quut.com/c/ANSI-C-grammar-l-1998.html和 实现了C语言除了struct和指针几乎所有的语法。 运行 环境要求:flex bison g ++ 11 python3 中间...
#OS 外壳自述文件用 LEX/YACC 编写的 Linux shell,由 Kyle Lin 和 Joachim Jones 编写。 我们的代码包含在 node.h、shell.l 和 shell.y 文件中。 #缺少功能文件名补全#特征所有内置命令(setenv、printenv、...