Constexpression's blog

编译原理实验

2023-04-28

实验2-1基于flex的词法分析器(C语言实现 )

flex 是通过处理其源文件来生词法和语法分析器的,源文件的扩展名为.l,其语法被分为三个部分:

1
2
3
4
5
6
7
8
9
/* 辅助定义部分 */
%option yylineno noyywrap
%{C代码}%
正则式定义
%%
/* 规则部分 */
正则式 {对应的动作:C代码}
%%
/* 用户子程序段 */

三个部分 %% 进行分离。

  1. 辅助定义部分,这一部分一般是一些声明及选项设置等。C 语言的注释、头文件包含等一般就放在 %{ %} 之间,这一部分的内容会被直接复制到输出文件的开头部分,定义段还可以定义正则式,这些正则式可以在其定义后被后续的正则式所引用(直接引用,或用来构造更复杂的正则式),引用之前定义的正则式,要用{}将先前定的的正则式括起来;
  2. 规则部分为一系列匹配模式和动作,模式一般使用正则表达式书写,动作部分为C代码:模式 1 {动作 1 (C代码)},在输入和模式 1 匹配的时候,执行动作部分的代码;即便对应的动作为空(比如注释会被直接忽略),也应该使用{},注意每条C语句之后都应有“;”;
  3. 用户子程序部分,本部分为 C 代码,会被原样复制到输出文件中,一般这里定义一些辅助函数等,如动作代码中使用到的辅助函数。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int line=1;
%}
LETTER [a-zA-Z]
ID ({LETTER}|_)({LETTER}|_|{DIGIT})*
OPT ("+"|"-"|"*"|"/"|"+="|"-="|"*="|"/="|">="|"<="|"=="|">"|"<"|"="|"++"|"--")
BRACKET ("("|")"|"["|"]"|"{"|"}"|";"|","|"\'"|"\""|"#")
DIGIT [0-9]
OINTEGER [1-9]{DIGIT}*
INTEGER ("+"|"-")?{OINTEGER}
DECIMAL {INTEGER}(.{OINTEGER})
FLOAT ([0-9])*+[.]([0-9])*+[Ee]([+-]?[0-9]([0-9])*|[0])
ERROEFLOAT ([0-9])*+[.](0-9)*+("E"|"e")
TYPE void|int|double|char
KEYWORD if|else|do|while|for|scanf|printf|sqrt|abs|main|return|float
TYPEIDENTIFY %d|%c|%s|%f|&{ID}
SGPS \/\/.*
DBPS \/\*(.|\n)*\*\/

%%
\n {++line;}
{TYPE} {printf("line%d:(type, %s)\n",line,yytext);}
{KEYWORD} {printf("line%d:(keyword, %s)\n",line,yytext);}
{DIGIT} {printf("line%d:(integer, %s)\n",line,yytext);}
{OINTEGER} {printf("line%d:(integer, %s)\n",line,yytext);}
{ID} {printf("line%d:(identify, %s)\n",line,yytext);}
{BRACKET} {printf("line%d:(bracket, %s)\n",line,yytext);}
{OPT} {printf("line%d:(OPT, %s)\n",line,yytext);}
{INTEGER} {printf("line%d:(integer, %s)\n",line,yytext);}
{DECIMAL} {printf("line%d:(decimal, %s)\n",line,yytext);}
{FLOAT} {printf("line%d:(float, %s)\n",line,yytext);}
{TYPEIDENTIFY} {printf("line%d:(typeidentify, %s)\n",line,yytext);}
{ERROEFLOAT} {printf("ERROEFLOAT\n");}
({SGPS}|{DBPS}) {}
. {}
[ \t]+ {}

%%
int main(){
yyin=fopen("F:/data.txt","r");
yylex();
return 0;
}
int yywrap(){
return 1;
}

匹配浮点型将浮点型数据做拆分,为啥要拆分呢,因为不拆分很难实现匹配浮点型字符串的正确格式

1
2
3
4
1、非0开头的浮点型(123.12)
2、0开头的浮点型(0.12)
3、非0整数型
4、0
1
2
3
4
1、^[1-9]\d*\.\d+$
2、^0\.\d+$
3、^[1-9]\d*$
4、^0$

有以下问题需要解决

3l14

085

0xf : INT_LIT

flaot 的指数表示

实验2-2基于flex的词法分析器(C++语言实现 )

实验2-3基于antlr的词法分析器(C语言实现 )

antlr的词法解析模块是通过处理其源文件来生词法分析器的,源文件的扩展名为.g4,其语法被分为两个部分:

1
2
lexer grammar '文件名'
词法定义
  1. 语法名部分:antlr处理的.g4文件中是可以把词法和语法部分放在一起进行处理的,当我们要将他们分开,单独处理词法部分时,需要加上lexer关键词。grammar的文件名必须和.g4前面的名称对应上。
  2. 词法部分为一系列TOKEN的定义,一般使用正则表达式书写。在定义TOKEN时,应用全大写字母,避免和语法规则混淆。

规则行务必没有缩进(即从行首开始),且对应的动作必须在同一行开始,即正则表达式与对应动作之间不允许有空行。

注意:2.0f, .04, 4e-04都是合法的float型字面量,但2f不是合法的float型字面量;123,076,0xFF等都是合法的int型字面量,但096就不是合法的int型字面量。

(一)在SysyLex.g4文件中,补充以下词法规则 (1) 标识符ID; (2) int型字面量INT_LIT; (3) float型字面量FLOAT_LIT; (4) 词法错误

(二)确认main.h中定义的token种别名称与其种别编号一致 对于下面的词法规则:

(三)在main.cpp中,正确显示token及token的种别信息.

实验3-1 基于flex/bison的语法分析器(C语言实现)

sys2022语言的特性

Bison

实验4-1 生成LLVM IR中间代码

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章