flex教程

lex/yacc简介

lex/yacc与flex/bison的关系

lex/yacc是一种思想,flex/bison是其gnu实现

lex/yacc的优势

轻易构造c/c++编译器

程序例子下载地址

ftp://ftp.iecc.com/pub/file/flexbison.zip

学习资料

Bison 3.0.4: Top

flex语法(分为三部分)

三部分通过%%分割

第一部分lex代码
%%
第二部分lex代码
%%
第三部分lex代码

第一部分:声明和选项设置(直接复制到生成的lex.yy.c中)

%{
变量为要复制到lex.yy.c中的c语言变量,动作中可以使用这些变量
%}

第二部分:单词匹配后进行某种动作(核心部分语法分析器,生成yylex()函数到lex.yy.c中)

语法

正则表达式1 动作1
正则表达式2 动作2
正则表达式3 动作3

  1. 正则表达式要按照正则表达式语法写,lex会编译为词法分析代码
  2. 动作是c语言语句,动作c语言语句直接复制到lex.yy.c中
  3. 两者合起来即是yylex()函数,yylex()函数可以在yacc中使用

lex将lex代码编译为词法分析器的编译理论基础

这部分代码是lex根据用户描述的语法自动生成的,背后是编译原理中的自动机理论。

单词匹配(正则表达式)

  1. 基本用法

    1. 最长匹配原则,词法分析器匹配输入时,匹配尽可能多的字符串
    2. 如果两个模式都可以匹配,那么匹配在程序中更早出现的那个模式

      flex教程
      flex教程

    当把连字号用于两个字符中间时, 表示字符的范围。当把抑扬号用在开始位置时,表示对后面的表达式取反。 如果两个范式匹配相同的字符串,就会使用匹配长度最长的范式。如果两者匹配的长度相同,就会选用第一个列出的范式。

  2. 单词匹配举例

    一个Lex/Yacc完整的示例(可使用C++) - huyansoft的专栏 - 博客频道 - ****.NET

    1. 匹配除\n以外的字符

      .

    2. 匹配\n字符

      \n

    3. 忽略空白字符

      [\t ]+ * 忽略空白 *;

    4. wc中定义的没有空白的字符

      [^ \t\n\r\f\v]+

    5. 匹配单词

      非数字由大小写字母、下划线组成
      nondigit ([_A-Za-z])

    6. 匹配数字

      一位数字,可以是0到9
      digit ([0-9])

    7. 匹配整数

      整数由1至多位数字组成
      integer ({digit}+)

    8. 匹配标识符

      非数字由大小写字母、下划线组成
      nondigit ([_A-Za-z])
      一位数字,可以是0到9
      digit ([0-9])

      标识符,以非数字开头,后跟0至多个数字或非数字
      identifier ({nondigit}({nondigit}|{digit})*)

      文法规则中使用这些变量需要加{indentifier}注意加括号

    9. 匹配一段连续空白串

      一个或一段连续的空白符
      blank_chars ([ \f\r\t\v]+)

匹配到单词后的动作

  1. 语法

    {一条或者多条c语言语句}

  2. 动作中使用的变量

    1. 使用lex代码中第一部分声明中定义的变量
    2. lex默认定义的内部变量

      变量名 作用
      yytext 指向本次匹配的输入文本
    3. 引入y.tab.h使用yacc中定义的变量

  3. 打印匹配的数据

    如果不写动作,默认动作是打印。因此宏{ECHO;}可以不用写。
    {ECHO;}
    ECHO是一个C语言宏
    \#define ECHO fwrite(yytext, yyleng, 1, yyout)

  4. 向语法分析器传递记号信息

  5. 传递字符串的值-使用函数strdup(yytext)

    passing values(yylval) other than string from flex to bison | GeekWentFreak

lex内置变量

名称 功能
char \*yytext 指针,指向所匹配的字符串
yyleng 所匹配的字符串的长度
yylval 与标记相对应的值
FILE \*yyout 输出文件
FILE \*yyin 输入文件
INITIAL 初始化开始环境
BEGIN 按条件转换开始环境
ECHO 输出所匹配的字符串

lex内置函数

名称 功能
int yylex(void) 调用扫描器, 返回标记
int yywrap(void) 约束,如果返回 1 表示扫描完成后程序就结束了, 否则返回 0

语法分析器每次需要一个记号的时候调用 yylex()从要解析的文件中读取一部分数据,然后返回相应的记号。当语法分析器需要下一个记号的时候,再次调用yylex(),词法分析器以协同的工作方式运行,每次返回时,yylex()会记录读到的文件的位置,语法分析器再次调用yylex()时,从该位置继续读取。

第三部分:直接复制到生成的lex.yy.c中

int main()
{
yylex();

}

flex程序编译

flex code.l //生成lex.yy.c
cc lex.yy.c -lfl //链接flex库文件