在这个实验中,使用 FlexBison 两个工具联合构建词法分析器和语法分析器。这是实现编译器前端的重要步骤,特别是在处理编程语言时,词法和语法分析能够帮助理解和解析源代码。

实验流程

  1. 词法分析:通过 Flex 来定义和识别编程语言的单词(token)。这包括关键字、标识符、常量、操作符等。
  2. 语法分析:通过 Bison 来解析语法规则,生成抽象语法树(AST),并根据这些规则识别程序的结构(如语句、表达式等)。
1. 构建词法分析器
  • Lex.l 文件:这个文件包含用于词法分析的规则。每条规则对应于一种单词,通过正则表达式来匹配不同类型的词。

  • Lex 文件内容(简略示例):

    %{
    #include "Parser.tab.h" // 包含 Bison 生成的 token 定义
    %}
    
    %%
    "int"       { return TYPE; }
    "float"     { return TYPE; }
    "return"    { return RETURN; }
    "if"        { return IF; }
    "else"      { return ELSE; }
    "while"     { return WHILE; }
    [0-9]+      { return INT; }
    [0-9]+"."[0-9]+ { return FLOAT; }
    [a-zA-Z_][a-zA-Z0-9_]* { return ID; }
    "=="        { return RELOP; }
    "+"         { return PLUS; }
    "-"         { return MINUS; }
    "*"         { return STAR; }
    "/"         { return DIV; }
    "&&"        { return AND; }
    "||"        { return OR; }
    "!"         { return NOT; }
    "="         { return ASSIGNOP; }
    ";"         { return SEMI; }
    ","         { return COMMA; }
    "{"         { return LC; }
    "}"         { return RC; }
    "("         { return LP; }
    ")"         { return RP; }
    %%
    
  • Flex 的工作流程

    1. 定义正则表达式来识别不同的单词。
    2. 调用 Flex 编译器生成 Lex.yy.c,通过其中的 yylex() 函数进行词法分析。
    3. 返回标识符的种类码给语法分析器(Bison),比如 int 返回 TYPE,运算符 + 返回 PLUS
2. 构建语法分析器
  • Parser.y 文件:包含语言的语法规则,定义程序结构,如表达式、条件语句、循环等。

  • Bison 文件内容(简略示例):

    %{
    #include <stdio.h>
    #include <stdlib.h>
    %}
    
    %token INT FLOAT ID ASSIGNOP RELOP PLUS MINUS STAR DIV AND OR NOT TYPE RETURN IF ELSE WHILE SEMI COMMA LP RP LC RC
    
    %%
    program:
        statement_list
        ;
    
    statement_list:
        statement_list statement
        | statement
        ;
    
    statement:
        TYPE ID ASSIGNOP expression SEMI
        | IF LP expression RP statement ELSE statement
        | WHILE LP expression RP statement
        ;
    
    expression:
        expression PLUS term
        | expression MINUS term
        | term
        ;
    
    term:
        term STAR factor
        | term DIV factor
        | factor
        ;
    
    factor:
        ID
        | INT
        | FLOAT
        ;
    %%
    
  • Bison 的工作流程

    1. 编译 Parser.y 文件,生成 Parser.tab.cParser.tab.h
    2. Parser.tab.h 中定义标识符对应的枚举值,这些枚举值在 Flex 中被引用。
    3. 使用 Bison 生成的 parser() 函数进行语法分析,将词法分析器返回的 token 进行语法解析。
3. 联合使用 Flex 和 Bison
  • 工作流程
    1. Flex 负责从输入流中识别单词并返回对应的单词种类码。
    2. Bison 接收 Flex 提供的单词种类码,匹配语法规则,生成抽象语法树。
    3. 语法分析过程中,Bison 根据需求调用 Flex 以获取下一个单词。

通过 Flex 和 Bison 的联合使用,您可以有效地实现从源代码到抽象语法树的构建,这也是编译器实现中的重要环节。

简单示例问题

  1. 问题:使用 Flex 如何识别一个浮点型常量? 答案:可以使用正则表达式 [0-9]+"."[0-9]+ 来识别浮点型常量。

  2. 问题:Bison 中如何定义 if-else 语句的语法规则? 答案IF LP expression RP statement ELSE statement; 定义了 if-else 的语法规则。

  3. 问题:Flex 和 Bison 如何交换信息? 答案:Flex 通过返回标识符种类码,供 Bison 使用这些种类码进行语法分析。

        FLEX(Fast Lexical Analyzer Generator)是一个应用软件,用于生成词法分析器。它的主要功能是通过词法规则(使用正则表达式定义)自动生成用于扫描文本的词法分析程序。FLEX 本质上是一个自动化工具,帮助开发者快速构建编译器或解释器中的词法分析器。

具体地,FLEX 的工作流程如下:

  1. 编写词法规则:用户定义的词法规则存储在 .l 文件中,使用正则表达式描述语言中的不同单词(token)类型,如标识符、关键字、操作符等。

  2. 自动生成 C 代码:FLEX 会根据这些规则生成相应的 C 代码(通常名为 lex.yy.c),该代码可以扫描输入文本并识别出符合定义的单词。

  3. 执行词法分析:生成的 lex.yy.c 文件通过调用 yylex() 函数执行词法分析,将识别到的单词类别(token)返回给调用程序,如语法分析器(例如 Bison)或其他应用程序。

FLEX 被广泛应用于编译器构建、解释器设计、文本处理工具开发等领域,尤其适用于实现编程语言的词法分析部分。

要调用 FLEX,需要按照以下步骤来编译和运行词法分析程序:

1. 编写词法规则文件(.l 文件)

首先,需要编写一个包含词法规则的 .l 文件,这是 FLEX 程序的输入。这个文件通常包含正则表达式和动作部分,用于匹配输入文本并执行相应的操作。

示例 example.l 文件:

%{
#include <stdio.h>
%}

%%

[0-9]+    { printf("Integer: %s\n", yytext); }
[ \t\n]+  { /* 忽略空白字符 */ }
.         { printf("Unknown character: %s\n", yytext); }

%%

int main() {
    yylex();
    return 0;
}

int yywrap() {
    return 1;
}
  • 这里我们定义了一个简单的词法分析器,能够识别整数,并忽略空白字符。

2. 使用 FLEX 编译 .l 文件

在终端或命令行中,使用以下命令调用 FLEX 来生成词法分析器的 C 源代码:

flex example.l

这将生成一个名为 lex.yy.c 的 C 源代码文件,它包含 FLEX 自动生成的词法分析器代码。

3. 编译生成的 C 文件

使用 C 编译器(如 GCC)将生成的 lex.yy.c 文件编译成可执行程序:

gcc lex.yy.c -o lexer -lfl
  • -lfl 选项用于链接 FLEX 库,它提供了 yylex() 函数等必要的功能。
  • -o lexer 指定输出的可执行文件名为 lexer

4. 运行词法分析器

编译完成后,就可以运行生成的可执行文件 lexer

./lexer

词法分析器将等待你输入文本,并根据你在 .l 文件中定义的规则进行匹配和处理。例如:

123 abc

5. 提供输入文件(可选)

也可以通过重定向输入文件来运行分析器。例如,如果有一个 input.txt 文件,内容如下:

456 xyz

可以使用以下命令:

./lexer < input.txt

这将输出:

Integer: 456
Unknown character: x
Unknown character: y
Unknown character: z
  • 最后总结一下
  • 步骤 1:编写 .l 文件。
  • 步骤 2:使用 flex 编译该文件,生成 lex.yy.c
  • 步骤 3:使用 C 编译器编译生成的 C 文件,生成可执行程序。
  • 步骤 4:运行词法分析器,并根据输入执行分析。

通过这些步骤,就可以成功调用 FLEX 来创建一个自定义的词法分析器。

Logo

中德AI开发者社区由X.Lab发起,旨在促进中德AI技术交流与合作,汇聚开发者及学者,共同探索前沿AI应用与创新。加入我们,共享资源,共创未来!🚀

更多推荐