lex快速入门

Linux 2016-07-06

起步

lex是用C语言开发的词法分析自动生成工具,它接受正规表示的词法描述,生成识别输入语言词法的词法分析器。

lex所规定的格式说明文件(一般以.l为扩展名)经过处理后,输出该词法分析程序lex.yy.c

该程序含有一个词法分析总控程序yylex(),但通常不含主函数main(),用户要自己编写main()和调用yylex()进行此法识别的主函数

lex的命令格式

lex [-ctvn -V -Q[y|n]] [files]
  • -c 指明动作是c语言(默认设置)
  • -t 输出到stdout而不是lex.yy.c
  • -v 提供一个两行的统计概述
  • -V 在stderr上输出lex的版本信息
  • -Q[y|n] y表示在lex.yy.c上打印版本恩信息,默认为n

关于有限自动机的限制

状态的数量必须是有限个的,lex中默认了限制了自动机的状态数、位置数、分析树的节点数、转换数、压缩的字符数、输出数组的大小,用户可以具体修改设置

  • %p n 位置数为n(默认 2000)
  • %n n 状态数为n (默认 4000)
  • %e n 分析树节点树n (8000)
  • %a n 转换数为n (16000)
  • %k n 压缩的字符类数n (20000)
  • %o n 输出数组的大小n (24000)

lex的使用

用户通过调用yylex()使用此法分析程序。每调用一次,yylex()就从输入流中识别一个单词并返回一个整型值(被识别出的单词内部码

内部码指的是词法分析程序在识别出某一类单词时返回的整型数值,它由用户自行定义取值。用户自定义的数值应大于256

lex源文件结构

文件一般由三部分组成:声明,翻译规则,辅助函数。其中,声明和辅助函数不是必要的,翻译规则则是必须的。

声明

声明部分可以分为C语言部分和辅助定义部分

C语言部分被包裹在%{%}之间,里面可以是任意的C代码,包括预处理语句(包含头文件,常量定义,子程序声明),辅助定义部分的作为是定义一些宏及多重入口。

翻译规则

这是lex的核心,它告诉lex都应该识别那些类的单词,以及识别后要做的事。其格式为:

R1    Action1
R2    Action2
...    ...
Rm    Actionm

为避免二义性,在R中若出现空格回车制表符,就用\s,\n,\t表示。Action中可以使用已定义的常量,全局变量和外部变量,也可以调用在辅助函数部分定义的函数。Action中多条语句用{}包裹。

辅助函数

辅助函数部分包含了识别规则动作代码中的所调用的局部函数。这些函数由用户编写,用户还可以在此定义main函数。 lex定义的全局变量:

  • char yytex[]:用于存放和拼接当前正在识别的单词,默认长度256
  • yylval:可用于表示所识别的单词的值;默认类型是int,也可以由用户重新定义为其他类型
  • int yyleng:用于记录当前正在识别的单词的长度(其实值就是strlen(yytext))

特殊规定

在识别过程中,lex将输入流中不与其他匹配的字符会原封不动的输出到标准输出上。

多重入口

在一些程序设计中,同一词文出现在不同的上下文是有不同的语义的。lex定义多重入口为:

<condition>r    {/* action */}

这格式的含义是当且仅当系统当前处于条件condition时,词型r才用于匹配,否则,这条规则不发生作用。为此,用户在编写lex文件时候应完成一些工作。

在lex源程序定义部分,用关键字%start定义若干所需要的开始条件名:

%start cond1 cond2 ... condk

condition的顺序可以任意的,若一行写不下可定义多行,一样以%start开头。其使用方法是:

<condition>r      {action}

这句话表示只有当lex状态在condition条件此规则才起作用.若要使lex回复状态,则通过BEGIN 0即可,BEGIN是lex为用户提供的一个宏.


本文由 hongweipeng 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

赏个馒头吧