附录编译器的自动生成工具LEX和YACC的使用方法
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详解

Lex和Y acc工具介绍――编译原理的实用工具1.词法分词器生成工具lexLex的主要功能是生成一个词法分析器(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中的任意一个字符。
使用–可以指定范围。
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的使用(例子)

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⼊门教程(⼋).使⽤堆栈编译语法分类: C++/C/C# 2007-06-05 11:08 4571⼈阅读评论(26) 收藏举报yacccommandshellunix存储linuxLex和Yacc应⽤⽅法(⼋).使⽤堆栈编译语法草⽊⽠ 20070604⼀、序前⾯⼀些系列⽂章着重介绍了递归语法树在编译理论⽅⾯的应⽤。
本⽂则会介绍另⼀种实现⽅式----堆栈。
堆栈在底层系统有⼗分⼴泛的应⽤,同样也⼗分擅长处理语法结构,这⾥通过实际⽰例探讨如何构造堆栈完成语法分析。
重要补充:下⾯是本系列⽂章全⽰例代码统⼀的调试测试环境,另对于lex,yacc⽂件需要存储为Unix格式,这⼀点和Linux,Unix下shell很类似,DOS格式的Shell是不能够被执⾏的,同样bison,lex编译DOS格式⽂件会出错误提⽰:Red Hat Linux release 9 (Shrike)Linux 2.4.20-8gcc version 3.2.2 20030222bison (GNU Bison) 1.35lex version 2.5.4flex version 2.5.4⼆、具体⽰例本⽰例主要完成功能:1 ⽀持整型,浮点型和字符串型2 ⽀持变量存储,变量名可为多个字符3 ⽀持整型,浮点型的+-*/()=运算法则4 ⽀持字符串型赋值5 ⽀持print打印整型,浮点型和字符串型6 ⽀持打印变量值7 ⽀持while if else switch四种控制结构,并⽀持控制结构的嵌套8 ⽀持> >= < <= != == 六种⽐较运算,同时也⽀持字符串的⽐较9 ⽀持 && || 复合⽐较运算10 ⽀持对空格和TAB的忽略处理11 ⽀持#的单⾏注释12 ⽀持{}多重组合13 ⽀持编译错误的具体显⽰14 ⽀持外部变量值传⼊(整型,浮点型和字符型)15 ⽀持外部变量获取(整型,浮点型和字符型)16 完整的企业应⽤模式三、⽰例全代码(略)A.stack.l----------------------------------------------B.stack.y----------------------------------------------C.stack.h----------------------------------------------D.stackparser.c----------------------------------------------E.public.h----------------------------------------------F.main.c----------------------------------------------G.mk 编译shell⽂件----------------------------------------------bison -d stack.ylex stack.lgcc -g -c lex.yy.c stack.tab.c stackparser.car -rl stack.a *.ogcc -g -o lw main.c stack.aH.mkclean shell⽂件----------------------------------------------rm stack.tab.crm stack.tab.hrm lex.yy.crm *.orm *.arm lw四、思路说明上⾯列出的代码是⽬前最长的。
编译原理 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 并不专业,不能满足低级程序设计的需求,处理过程中往往性能不佳。
语言开发工具Lex和Yacc的分析与应用
语言开发工具Lex和Yacc的分析与应用
丁英嘉; 王能斌
【期刊名称】《《计算机应用与软件》》
【年(卷),期】1989(006)001
【摘要】本文旨在向读者介绍对UNIX 系统中的两个软件工具Lex、Yacc 的分析结果和应用方法。
Lex 是词法分析器的自动生成工具,Yacc 是语法分析器的自动生成工具。
我们在关系数据语MioroSQL 的实现过程中,灵活地利用了这两个工具,特别是解决了导致Lex被某些系统弃之不用的问题。
【总页数】8页(P5-11,65)
【作者】丁英嘉; 王能斌
【作者单位】不详
【正文语种】中文
【中图分类】TP31
【相关文献】
1.软件开发工具LEX和YACC的应用 [J], 施一萍
2.浅谈用C#语言的winform开发工具实现π值的计算 [J], 张浩然
3.面向Python语言的社区发现软件开发工具包的设计 [J], 赵卫绩;黄思琦;佟良;刘井莲
4.基于Python语言的按键脚本开发工具 [J], 郭建军; 林丽君; 何泽仁; 王克强
5.YACC在ATLAS语言语法分析中的冲突消解研究 [J], 李爱萍;王家礼;梁红玉
因版权原因,仅展示原文概要,查看原文内容请购买。
Lex使用指南
Lex使用指南Lex是由美国Bell实验室等人用C语言开发的一种词法分析器自动生成工具,它提供一种供开发者编写词法规则(正规式等)的语言(Lex语言)以及这种语言的翻译器(这种翻译器将Lex语言编写的规则翻译成为C语言程序)。
Lex是linux下的工具,本实验使用的编译工具是cygwin(cygwin在windows下模拟一个linux环境)下的flex,它与lex的使用方法基本相同,只有很少的差别。
一、Lex的基本原理和使用方法Lex的基本工作原理为:由正规式生成NFA,将NFA变换成DFA,DFA经化简后,模拟生成词法分析器。
其中正规式由开发者使用Lex语言编写,其余部分由Lex翻译器完成.翻译器将Lex源程序翻译成一个名为的C语言源文件,此文件含有两部分内容:一部分是根据正规式所构造的DFA状态转移表,另一部分是用来驱动该表的总控程序yylex()。
当主程序需要从输入字符流中识别一个记号时,只需要调用一次yylex()就可以了。
为了使用Lex所生成的词法分析器,我们需要将程序用C编译器进行编译,并将相关支持库函数连入目标代码。
Lex的使用步骤可如下图所示:生成词法分析器的过程:使用所生成的词法分析器的过程:二、lex源程序的写法:Lex源程序必须按照Lex语言的规范来写,其核心是一组词法规则(正规式)。
一般而言,一个Lex源程序分为三部分,三部分之间以符号%%分隔。
`[第一部分:定义段]%%第二部分:词法规则段[%%第三部分:辅助函数段]其中,第一部分及第三部分和第三部分之上的%%都可以省略(即上述方括号括起的部分可以省略)。
以%开头的符号和关键字,或者是词法规则段的各个规则一般顶着行首来写,前面没有空格。
Lex源程序中可以有注释,注释由/*和*/括起,但是请注意,注释的行首需要有前导空白。
1. 第一部分定义段的写法:定义段可以分为两部分:第一部分以符号%{和%}包裹,里面为以C语法写的一些定义和声明:例如,文件包含,宏定义,常数定义,全局变量及外部变量定义,函数声明等。
编译原理之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作者 :Thomas Niemann翻译: 傅惠忠目录序言3 导言4 Lex6 理论6练习7 YACC11 理论11练习,第一部分12练习,第二部分15 计算器18 描述18包含文件20Lex21 输入文件Yacc22 输入文件解释器26编译器27图28Lex34 进阶字符串34保留字35lex35 的调试Yacc37 进阶递归37IfElse37 歧义错误信息38继承属性39内含动作39调试Yacc39 参考书目40lex yacc lex yacc本书将教会你如何使用和构造一个编译器。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
附录编译器的自动生成工具LEX和YACC的使用方法一、词法分析程序产生器LEX的用法1.1 Lex概述程序设计语言从机器语言发展到今天的象pascal, C等这样的高级语言,使人们可以摆脱与机器有关的细节进行程序设计。
但是用高级语言写程序时程序员必须在程序中详尽地告诉计算机系统怎样去解决某个问题,这在某种程度上说也是一件很复杂的工作。
人们希望有新的语言——非常高级的语言,用这种语言程序员仅仅需要告诉计算机系统要解决什么问题,计算机系统能自动地从这个问题的描述去寻求解决问题的途径,或者说将这个问题的描述自动地转换成用某种高级语言如C、FORTRAN表示的程序。
这个程序就可以解决给定的问题,这种希望虽然还没有能够完全变成现实,但是在某些具体的问题领域里已经部分地实现了。
这里要介绍的Lex和下章要介绍的Yacc就是在编译程序设计这个领域里的两种非常高级的语言。
用它们可以很方便的描述词法分析器和语法分析器,并自动产生出相应的高级语言(C)的程序。
Lex是一个词法分析器(扫描器)的自动产生系统,它的示意图如图1.1。
Lex源程序是用一种面向问题的语言写成的。
这个语言的核心是正规表达式(正规式),用它描述输入串的词法结构。
在这个语言中用户还可以描述当某一个词形被识别出来时要完成的动作,例如在高级语言的词法分析器中,当识别出一个关键字时,它应该向语法分析器返回该关键字的内部编码。
Lex并不是一个完整的语言,它只是某种高级语言(称为lex的宿主语言)的扩充,因此lex没有为描述动作设计新的语言,而是借助其宿主语言来描述动作。
我们只介绍C 作为lex的宿主语言时的使用方法,在Unix系统中,FORTRAN语言的一种改进形式Ratfor也可以做lex的宿主语言。
图1.1 Lex示意图Lex自动地表示把输入串词法结构的正规式及相应的动作转换成一个宿主语言的程序,即词法分析程序,它有一个固定的名字yyler,在这里yyler是一个C语言的程序。
Yylex将识别出输入串中的词形,并且在识别出某词形时完成指定的动作。
看一个简单的例子:写一个lex源程序,将输入串中的小写字母转换成相应的大定字母。
程序如下:%%[a-z]printf(“%c”.yytext[0]+'A'-'a');上述程序中的第一行%%是一个分界符,表示识别规则的开始。
第二行就是识别规则。
左边是识别小写字母的正规式。
右边就是识别出小写字母时采取的动作:将小写字母转换成相应的大写字母。
Lex的工作原理是将源程序中的正规式转换成相应的确定有限自动机,而相应的动作则插入到yylox中适当的地方,控制流由该确定有限自动机的解释器掌握,不同的源程序,这个解释器是相同的。
关于lex工作原理的详细情况请参考[3],这里不多介绍。
1.2 lex源程序的格式lex源程序的一般格式是:{辅助定义的部分}%%{识别规则部分}%%{用户子程序部分}其中用花括号起来的各部分都不是必须有的。
当没有“用户子程序部分”时,第二个%%也可以省去。
第一个%%是必须的,因为它标志着识别规则部分的开始,最短的合法的lex源程序是:%%它的作用是将输入串照原样抄到输出文件中。
识别规则都分是Lex源程序的核心。
它是一张表,左边一列是正规式,右边一列是相应的动作。
下面是一条典型的识别规则:integer printf("found keywcrd INT");这条规则的意思是在输入串中寻找词形“integer”,每当与之匹配成功时,就打印出“foundkeyword INT”这句话。
注意在识别规则中,正规式与动作之间必须用空格分隔开。
动作部分如果只是一个简单的C表达式,则可以写在正规式右边同一行中,如果动作需要占两行以上,则须用花括号括起来,否则会出错。
上倒也可以写成:integer {printf("found keyword INT");}下面先介绍识别规则部分的写法,再介绍其余部分。
1.3 Lex用的正规式一个正规式表示一个字符串的集合。
正规式由正文字符与正规式运算符组成.正文字符组成基本的正规式,表示某一个符号串;正规式运算符则将基本的正规式组合成为复杂的正规式,表示字符串的集合。
例如:ab仅表示字符串ab,而(a b)+表示字符串的集合:{ab,abab,ababab,…)。
Lex中的正规式运算符有下列十六种:”\[ ]∧ -?•*+| ()/${} %<>上述运算符需要作为正文字符出现在正规式中时,必须借助于双引号”或反斜线\,具体用法是;xyz“++”或xyz\+\+表示字符串xyz++为避免死记上述十多个运算符,建议在使用非数字或字母字符时都用双引号或反斜线。
要表示双引号本身可用\”,要表示反外线用”\”或\\前面说过,在识别规则中空格表示正规式的结束,因此要在正规式中引进空格必须借助双引号或反斜线,但出现在方括号[]之内的空格是例外。
几个特殊符号:\n是回车换行(newline)\t是tab\b是退格(back space)下面按照运算符的功能分别介绍上述正规式运算符。
1.字符的集合用方括号对可以表示字符的集合。
正规式[a b c]与单个字符a或b或c匹配在方括号中大多数的运算符都不起作用,只有\-和∧例外。
运算符----表示字符的范围,例如[a-z 0-9 <>-]表示由所有小写字母,所有数字、尖括号及下划线组成的字符集合。
如果某字符集合中包括-在内,则必须把它写在第一个或最后一个位置上,如[-+0-9]与所有数字和正负号匹配在字符集合中,运算符∧必须写在第一个位置即紧接在左方括号之后,它的作用是求方括号中除∧之外的字符组成的字符集合相对于计算机的字符集的补集,例如 [∧abc]与除去a、b和c以外的任何符号匹配。
运算符\在方括号中同样发挥解除运算符作用的功能。
2.与任意字符匹配的正规式运算符。
形成的正规式与除回车换行符以外的任意字符匹配。
在lex的正规式中,也可以用八进制数字与\一起表示字符,如[\40-\176]与ASCII字符集中所有在八进制 40(空格)到八进制176(~)之间的可打印字符匹配。
3.可有可无的表达式运算得?指出正规式中可有可无的子式,例如ab?c与ac或abc匹配,即b是可有可无的。
4.闭包运算运算符*和十是 Lex正规式中的闭包运算符,它们表示正规式中某子式的重复,例如"a*"表示由0个或多个a组成的字符串的集合,而"a+"表示由1个或多个a组成的字符串的集合,下面两个正规式是常用的:[a-z]+[A-Za-z][A-Za-z 0-9]*第一个是所有由小写字母组成的字符串的集合,第二个是由字母开头的字母数字串组成的集合。
5、选择和字符组运算符|表示选择:(ab|cd)与ab或cd匹配运算符()表示一组字符,注意()与[ ]的区别。
(ab)表示字符串ab,而[ab]则表示单个字符a或b。
圆括号()用于表示复杂的正规式,例如:(ab|cd+)?(ef)*与abefef, efef, cdef, cddd匹配,但不与abc, abcd或abcdef匹配。
6、上下文相关性lex可以识别一定范围的上下文,因此可在一定程度上表示上下文相关性。
若某正规式的第一个字符是∧,则仅当该正规出现在一行的开始处时才被匹配,一行的开始处是指整个输入串的开始或者紧接在一个回车换行之后,注意∧还有另一个作作即求补,∧的这两种用法不可能发生矛盾。
若某正规式的最后一个字符是$,则仅当该表达式出现在一行的结尾处时才被匹配,一行的结尾处是指该表达式之后紧接一个回车换行。
运算符/指出某正规式是否被匹配取决于它的后文,例如: ab/cd,仅在ab之后紧接cd 的情况下才与ab匹配。
$其实是/的一个特殊情形,例如下面两个正规式等价:ab$,ab/\ n某正规式是否被匹配,或者匹配后执行什么样的动作也可能取决于该表达式的前文,前文相关性的处理方法在后面专门讨论,将用到运算符"<>"7、重复和辅助定义当被{}括起来的是数字对时,{}表示重复;当它括起来的是一个名字时,则表示辅助定义的展开。
例如:a{1,5} ,表示集合{a.aa.aaa.aaaa.aaaaa}.{digit}则与预先定义的名叫dight 的串匹配,并将有定义插入到它在正规式中出现的位置上,辅助定义在后面专门讨论。
最后,符号%的作用是作为lex源程序的段间分隔符。
1.4 Lex源程序中的动作前面说过当Lex识别出一个词形时,要完成相应的动作。
这一节叙述Lex为描述动作提供的帮助。
首先应指出,输入串中那些不与任何识别规则中的正规式匹配的字符串将被原样照望抄到输出文件中去。
因此如果用户不仅仅是希望照抄输出,就必须为每一个可能的词形提供识别规则,并在其中提供相应的动作。
用lex为工具写程序语言的词法分析器时尤其要注意。
最简单的一种动作是滤掉输入中的某些字符串,这种动作用C的空语句“;”来实现。
例:滤掉输入申中所有空格、tab和回车换行符,相应的识别规则如下:[\t\n];如果相邻的几条规则的动作都相同,则可以用|表示动作部分,它指出该规则的动作与下一条规则的动作相同。
例如上倒也可以写成:“”|“\t”|“\n”;注意\t和\n中的双引号可以去掉。
外部字符数组yytext的内容是当前被某规则匹配的字符串,例如正规式[a-z]+与所有由小写字母组成的字符串匹配,要想知道与它匹配的具体字符串是什么,可用下述规则:[a-z]+ printf(“% s”, yytext);动作printf(“%s”,yytext)就是将字符数组yytext的内容打印出来,这个动作用得很频繁,Lex提供了一个宏ECHO来表示它,因此上述识别规则可以写成:[a-z]+ECHO;请注意,上面说过缺省的动作就是将输入串原样抄到输出文件中,那么上述规则起什么作用呢?这一点将在“规则的二义性”一节中解释。
有时有必要知道被匹配的字符串中的字符个数,外部变量yyleng就表示当前yytext中字符的个数。
例如要对输入串中单词的个数和字符的个数进行计数(单词假定是由大写或小写字母组成的字符串),可用下述规则:[a-zA-Z]+ {words++;Chars+=yyleng;}注意被匹配的字符串的第一个字符和最后一个字符分别是yytext[0]和yytext[yyleng-1]下面介绍三个Lex提供的在写动作时可能用到的C函数l.yymore()当需下一次被匹配的字符串被添加在当前识别出的字符串后面,即不使下一次的输入替换yytext中已有的内容而是接在它的内容之后,必须在当前的动作中调用yymore( )例:假设一个语言规定它的字符串括在两个双引号之间,如果某字符串中含有双引号,则在它前面加上反斜线\。