Chinaunix首页 | 论坛 | 博客
  • 博客访问: 309379
  • 博文数量: 60
  • 博客积分: 2579
  • 博客等级: 大尉
  • 技术积分: 570
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-17 14:54
文章分类

全部博文(60)

文章存档

2011年(1)

2010年(1)

2009年(35)

2008年(23)

分类: C/C++

2008-06-04 13:24:06

 

名称

 

  lex - 词法任务生成程序 ( Generates programs for lexical tasks

 

用法

 

  lex [-ct] [-n|-v] [file...]

 

  [Compaq]  下列的语法在环境变量设为 svr4 时使用。

 

  lex [-crt] [-n|-v] [-V] [-Qy|-Qn] [file...]

 

标准

 

  本文中的接口遵循下列工业标准:

 

  lex:  XPG4, XPG4-UNIX

 

选项

 

  -c  C代码写入文件lex.yy.c 。此为缺省值。

 

  -n  支持统计摘要。当你为有限状态机设置自己的表格尺寸时,lex将自动产生这些统计摘要,即使并没有选择此标志。

 

  -r  将明达FORTRAN语言代码写入文件lex.yy.r 。(Tru64 UNIX没有RATFOR 编译器)

 

  -t  输出到标准输出而不是文件。

 

  -v  提供关于所产生的有限状态机统计的摘要。

 

  -V  [Compaq]  lex 版本号输出到标准错误输出。要求环境变量CMD_ENV 设为svr4

 

  -Q[y|n]

[Compaq]  决定是否将lex 版本号写入输出文件。缺省为 -Qn,表示不写入。要求环境变量CMD_ENV 设为svr4

 

说明

 

  lex命令利用文件中包含的规则和动作来产生一个程序文件:lex.yy.c ,该文件可由cc命令编译。

  这个程序能够接受输入信息,并根据文件中定义的规则将其分解为逻辑片段,以及执行文件所包含

动作中的程序片段。

 

  生成程序是一个名为yylex()C语言函数。lex 命令将该函数置于lex.yy.c文件中。你可以单独

  使用yylex()函数来接受简单的,一个词的输入,或者将其与其它C语言程序联合使用以执行更为

复杂的输入信息的分析功能。例如,你可以利用lex来产生一个程序,该程序在将输入流送给由

yacc命令生成的分析程序前作上标记,

 

  yylex()函数利用有限状态机结构对输入流进行分析。该结构只允许程序在某一时刻存在一种状态,

  且状态的数量是有限的。文件中的规则定义程序如何根据接受的输入信息从一种状态转移到另一种

状态。

 

  lex命令从文件/usr/ccs/lib/ncpform/usr/ccs/lib/ncform中读取有限状态机结构信息。可以使

用环境变量LEXER来指定其它位置。

 

  如果没有指定文件,lex将读取标准输入。它将多个文件当作一个文件处理。

 

  输入文件格式

 

  输入文件可以包含三个区域:定义区域,规则区域和用户子程序区域。各区域之间被只由%%组成的行分割,如:

 

       definitions

       %%

       rules

       %%

       user_subroutines

 

  定义区域

 

  如果要在规则中使用变量,你必须在定义区域中定义它们。变量在左边,定义体在右边,例如,定义D为数字:

 

       D       [0-9]

 

  你可以在规则区域中使用定义的变量,使用时将它们用{}括上,如{D}

 

  在定义区域内,你可以设置下列两个互斥的声明。

 

  %array

声明yytext类型为以空字符结尾的数组。

 

  %pointer

声明yytext类型为以空字符结尾的字符串指针。此定义选择 /usr/ccs/lib/ncpform 框架

 

  在定义区域中,你也可以设置有限状态机的表格尺寸。缺省的尺寸对于小程序而言足够大,

  你或许想为更为复杂的程序设置更大的尺寸:

 

  %p  number

      位置数(default 5000)

 

  %n  number

      状态数(default 2500)

 

  %e  number

      分析树节点数(default 2000)

 

  %a  number

      转变数(default 5000)

 

  %k  number

      包装的字符类数(default 2000)

 

  %o  number

      输出槽数(default 5000)

 

  如果扩展的字符出现在正则表达式字符串中,你可能需要利用 %o 参数重设输出数组的

尺寸。(可能的尺寸为10000 - 20000)。此重设反映了相对于ASCII字符集更为巨大的扩展字符集。

 

  规则区域

 

  规则区域是必须的。它必须由 %% 前导,即使没有定义项。命令不认识没有定界符的规则。

 

  在规则区域中,左侧是由yylex()函数的输入文件所承认的模式。右侧是当模式被识别时

所要执行的C语言程序片段。

 

  模式可以包含扩展字符,除了一个例外:扩展字符不能出现在由括号包含的字符类表达式内。

 

  列与列之间由 tab键分割。例如,寻找文件中的词LEAD,将它用词GOLD替换,执行以下的步骤:

 

   1.  创建名为transmute.l的文件,它包含以下行:      

 

            %%

            (LEAD)  printf("GOLD");

 

2.       然后在shell下执行下列命令:

      

lex transmute.l

            cc -o transmute lex.yy.c -ll

 

3.       你可以使用如下命令进行测试:

      

            transmute

 

  这个命令显示文件transmute.l的内容,词LEADGOLD替换。

  每个模式可以具有相应的动作,也就是当模式匹配时所要执行的C语言代码片段。每条语句

必须由‘;’结尾,如果一个动作有多条语句,则应该用{}括起。如果有用户子程序区域,则

规则区域之后需要分割符 %%

 

  当函数yylex()匹配一个输入流中的字符串,它先将匹配的文本拷贝到外部字符数组yytext中,

然后执行所规定的动作。

 

  你可以利用下列可选项来构建所需的模式:

 

  x, y

      匹配字符本身

 

  [ ]

匹配括号中范围表达式中或列表中的任何一个字符。如[abcx-z]匹配a,b,c,x,y, z

 

  " "

匹配引号内的字符或字符串,即使其为操作符。如"$"阻止将字符 $解释为操作符。

 

  \  

与双引号的作用一样。如\$ 阻止将字符 $ 解释为操作符。

 

  *  

匹配零个或多个连续重复的单个字符,该单字符由前导的正则表达式所匹配。

x* 匹配零个或多个重复的x字符序列。

 

  +  

匹配一个或多个连续重复的单个字符,该单字符由前导的正则表达式所匹配。

 

  ? 

匹配零个或一个连续重复的单个字符,该单字符由前导的正则表达式所匹配。

 

  ^ 

只匹配行首的字符。^x 匹配以x开头的行。

 

  [^]

匹配任何除了 ^ 后的字符。如[^xyz]匹配除了x, y, z之外的任何字符。

 

  .  

      匹配除了换行字符外的任何字符。

 

  $  

      匹配行尾。与 ^ 相反。

 

  |  

      匹配两个字符中的任意一个。x|y 匹配xy

 

  /  

匹配一个扩展正则表达式仅当其后跟另一个扩展正则表达式时。它只将前面的表

达式所匹配的内容读入yytext文件。对于正则表达式 a*b/cc 和输入 aaabcc

字符串 aaab 将被读入yytext文件。

 

  ( )

匹配圆括号内的模式,这被用于集合。它将整个模式读入文件 yytext 。圆括号内的

字符集可用来替代任何其它模式内的单字符。(xyz123) 匹配字符串 xyz123并将整个

字符串读入文件 yytext

 

  {} 

匹配在定义项内定义的字符。如果 D 被定义为数字,则 {D} 匹配所有的数字。

 

  {m,n}

匹配连续重复出现次数界于mn之间的字符序列。如x{2,4} 匹配xxxxx,或xxxx

 

  如果某一行由一个空格开头,lex 将其拷贝到输出文件 lex.yy.c ,如果该行在规则区域内,

lex 将其拷贝到文件lex.yy.c的声明区域内。如果该行在定义项内,lex 将其拷贝到文件

lex.yy.c的程序代码区域内。

 

 

  用户子程序区域

 

  lex库将三个子程序定义为宏以供在规则中使用。

 

  input( )

      yyin中读取一个字符。

 

  unput( )

      当字符被读之后替换。

 

  output( )

      将一个字符写入yyout

 

  你可以通过在用户子程序区域内提供的程序重载这三个宏。但是,如果你提供自己的程序,

你必须在定义项内解除三个宏的定义:

 

       %{

       #undef input

       #undef unput

       #undef output

       }%

 

  当利用lex命令作为简单地从标准输入到标准输出的传输管道时,你可以避免使用libl.a

书写框架。它具有一个你可使用的调用yylex()函数的主函数。

 

  每个由lex命令产生的外部名称都有前缀 yy 。如 yyinyyoutyylexyyext

 

  将空格放入表达式

 

  Normally, spaces or tabs end a rule and, therefore, the expression that

  defines a rule.  However, you can enclose the spaces or tab characters in

  "" (double quotes) to include them in the expression. Use quotes around all

  spaces in expressions that are not already within sets of [ ] (brackets).

  正常情况下,空格或tab键结束一条规则,也就是定义一条规则的表达式。然而,可以将它们放在

双引号内再置于表达式内。所有表达式内的不在括号内的空格都要使用双引号。

 

  其它特殊字符

 

  lex程序认识许多C语言中正常的特殊字符。这些字符序列如下:

 

  序列       意义

  \n         换行符

  \t         制表符

  \b         删除键

  \\         反斜线

  \digits    由三位八进制数的值表示的字符

  \xdigits   由十六进制数的值表示的字符

 

  不要在表达式中使用实际的换行字符。

 

  当在表达式中使用这些特殊字符时,不必使用双引号。除了这些特殊字符和先前描述的操作符号外,

其它字符均为文本字符。

 

  匹配规则

 

  当多于一个的表达式能够匹配当前的输入时,lex首先选取最长的匹配;当长度相同时,选取最先找到的。例如:

 

       integer keyword action...;

       [a-z]+ identifier action...;

 

  对于上述规则,当 integers 作为输入词时,lex将会将其匹配为 identifier 因为匹配 [a-z]+ 八个字符而

integer 只能匹配七个。然而,如果integer 作为输入词,那么两条规则都匹配七个字符,此时将会选择第

一条因为它首先发生。更短的输入如int只能匹配第二条规则。

 

  使用通配符匹配字符串

 

  因为 lex命令首先选择最长的匹配,所以不要使用如包含表达式'.*'的规则。

 

  前述的规则看起来可以很好的认识单引号中的字符串。然而,词法分析器向后找寻最远的

单引号来完成匹配。例如如果获得如下的输入,词法分析器将会匹配整个字符串。

 

       'first' quoted string here, 'second' here

 

  为了查找小的字符串,即 first second,使用下列规则:

 

       '[^'\n]*'

 

  这将会匹配字符串'first'

 

  因为不匹配换行符,所以表达式如 .* 将会在当前行结束匹配。不要试图使用表达式:[.\n] +

打破这个限制,因为词法分析器将试图读入整个输入文件,这将导致内部缓冲区溢出。

 

  查找字符串中的字符串

 

  lex 程序将会分解输入流,但不找寻符合表达式的所有匹配。每个字符仅利用一次。例如,为了匹配

在输入文件中的 she he,使用如下规则:

 

       she   s++;

       he    h++;

       \n    |

       .     ;

 

  后两条规则忽略除了 he she 之外的所有字符。然而因为she 包含he,所以lex命令并不认识

包含在 she中的he

 

  为了重载这个选择,可以使用REJECT。该指示符告述lex命令执行下一条规则,此时lex调整输入

指针到第一条规则开始执行时的位置。例如,为了找出she中的he,使用如下规则:

 

       she    {s++; REJECT;}

       he     {h++; REJECT;}

       \n     |

       .      ;

 

  在记录she之后,lex抛弃输入流并重新匹配he。在这种情况下,你可以省略he后的REJECT

因为she包含hehe不包含she。在其它的情况下则很难决定输入字符的归属。

 

  总之,当lex命令的目的不是分解输入流,而是检测输入流中某些模式的所有匹配,而这些模式

的匹配有可能互相重叠或包含时,REJECT 是很有用的。

 

注意

 

  因为lex为中间文件和输出文件使用固定的名称,所以在某一给定的目录下只能有一个lex生成

的程序。如果指定没有 t ,则所有信息,错误,和警告都将写入到标准输出。反之则输出到标准错误。

 

  [Compaq]  yytext数组的缺省维数为200,由常量YYLMAX定义。如果需要更大的数组,

则需要在lex命令文件中重新定义:

 

       {

       #undef YYLMAX

       #define YYLMAX 8192

       }

 

  其它两个数组也使用YYLMAX,它们是yysubf, yylstate

 

示例

 

   1.  下列命令抽取文件lexcommands中的lex指令,并将输出写入到文件lex.yy.c

 

            lex lexcommands

2.       文件lexcommands中包含lex程序的一个示例,它将被放到lex命令文件中。下面的程序将

大写转化为小写,删除行尾的空格,并将多个空格用单个字符替代:

 

            %%

            [A-Z] putchar(tolower(yytext[0]));

            [ ]+$ ;

            [ ]+ putchar(' ');

 

环境变量

 

  下列的环境变量影响 lex()的行为:

 

  LANG

提供未设置或为空的本地类别变量的缺省值。

 

  LC_ALL

如果设置,将会覆盖所有其它本地变量的值。

 

  LC_COLLATE

决定输出如何排序,针对 x 选项。

 

  LC_CTYPE

当字符(单字节或多字节)处于输入的参数和文件中时,决定字节次序如何解释。

 

  LC_MESSAGES

决定影响命令所显示的诊断消息内容格式的方式。

 

  NLSPATH

为处理 LC_MESSAGES 定义消息目录的位置。

 

文件

 

  /usr/ccs/lib/libl.a

      运行时库

 

  /usr/ccs/lib/ncform

针对lex的缺省的有限状态机的C语言框架。

 

  /usr/ccs/lib/ncpform

针对lex的缺省的有限状态机的C语言框架,其中yytext定义为指针。

 

  /usr/ccs/lib/nrform

针对lex的缺省的有限状态机的FORTRAN语言框架。

 

SEE ALSO

 

  Commands:  yacc(1)

 

  Standards:  standards(5)

 

  Programming Support Tools

 

阅读(2134) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~