Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
2
2022fall-Compiler_CMinus
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李晓奇
2022fall-Compiler_CMinus
Commits
7804af88
Commit
7804af88
authored
Sep 25, 2022
by
李晓奇
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
final commit
parent
38c8231f
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
120 additions
and
11 deletions
+120
-11
.gitignore
.gitignore
+2
-0
Reports/.gitignore
Reports/.gitignore
+1
-0
Reports/1-parser/README.md
Reports/1-parser/README.md
+117
-2
src/parser/lexical_analyzer.l
src/parser/lexical_analyzer.l
+0
-9
tests/parser/syntree_simple/*.syntax_tree
tests/parser/syntree_simple/*.syntax_tree
+0
-0
No files found.
.gitignore
View file @
7804af88
...
...
@@ -2,3 +2,5 @@ build
Documentations/1-parser/*.pdf
compile_commands.json
.cache
tmp.cminus
Reports/.gitignore
0 → 100644
View file @
7804af88
1-parser/*.pdf
Reports/1-parser/README.md
View file @
7804af88
# lab1 实验报告
学号 姓名
PB20111654 李晓奇
## 实验要求
完成
*cminus*
语言的语法分析器和词法分析器。具体任务是补全文件
`lexical_analyzer.l`
和
`syntax_analyzer.y`
。使得输入
*cminus*
代码后,可以经lexer转变为记号流,或者经过parser(调用lexer)分析语法是否合规。
## 实验难点
-
理解flex和bison的工作机制
-
设计合适的token简化设计
-
lexer针对注释的规则撰写
## 实验设计
#### 1)文法符号的设计
因为本质是翻译文法规则,所以定义文法中出现的一系列文法符号就是核心所在。而为了flex和bison的交互,仔细设计二者共享的token就很重要。
我的整体设计是:
-
对文法符号串进行全大写
-
适当简写,如STMT统一代指STATEMENT,DEC代指DECLARATION等,这个在注释中有标注
-
终止符由下划线
`_`
开始
这样定义的不必要符号特别多,典型的是针对规则
`relop → <= ∣ < ∣ > ∣ >= ∣ == ∣ !=`
的终止符定义,在书写匹配规则的时候,发现为这条规则的每个选择都写一遍太麻烦,对比一些示例后仔细想了想,应该不会对后续的编译流程产生影响,我就将这条规则的算术运算符统一规定为:
`_RELOP`
。这样,对于这条规则,词法方面只要利用选择规则识别、将具体字符串拷贝、位置按长度修改即可,而语法方面只需要连接节点即可,避免了两方面都要进行的六次重复。
所有的token如下:
```
%token <node> ERROR
%type <node> TYPE_SPEC RELOP ADDOP MULOP
%type <node> DEC_LIST DEC VAR_DEC FUN_DEC LOCAL_DEC
%type <node> COM_STMT STMT_LIST STMT EXPR_STMT ITER_STMT SELC_STMT RET_STMT
%type <node> EXPR SIMPLE_EXPR VAR ADD_EXPR TERM FACTOR INTEGER FLOAT CALL
%type <node> PARAM PARAMS PARAM_LIST ARGS ARG_LIST
%token <node> _IF _ELSE _WHILE _RETURN _INT _FLOAT _VOID
%token <node> _ASSIGN _RELOP _ADD_OP _MUL_OP
%token <node> _L_SQUARE _R_SQUARE _L_PARE _R_PARE _L_BRACKET _R_BRACKET
%token <node> _SEMI _COMMA _ID _INTEGER _FLOATPOINT
%type <node> program
%start program
```
#### 2)匹配后的动作
根据我的理解,在数据结构上,两部分程序分别完成两件事:
1.
词法分析识别出终止符,构造对应的节点(叶节点),传递给parser
2.
语法分析根据得到的终止符进行归约,不断构造归约后的父节点,并与子节点连接直至树根
当语法分析归约到顶点即
*program*
时,将这个根节点置为全局变量
`gt`
的root值,由此语法树分析完成,可以用来进行后续分析,或者在本次实验中用来遍历打印语法树。
所以匹配后的动作:
-
词法分析:利用
`pass_node()`
构建并传递叶节点
-
语法分析:根据归约使用的文法,将子节点归约/连接至父节点,要注意空节点的情况。
#### 3)针对注释的正则表达式
这个容易出现匹配不到多行、贪婪匹配等问题,BUG基本都在这里。
查阅
[
资料
](
http://westes.github.io/flex/manual/Start-Conditions.html
)
后发现可以利用flex的start-condition解决,官方也提供了匹配多行注释相应的解决方案,稍加修改就可以拿来用了。
## 实验结果验证
请提供部分自行设计的测试
就多行注释匹配做一个验证,书写
`tmp.cminus`
文件如下:
```
c
/*
This is a bad comment use */
and
should
fail
the
parser
.
*/
int
mian
()
{
int
a
=
1
;
}
```
词法分析:
```
$ ./build/lexer ./tmp.cminus
Token Text Line Column (Start,End)
278 and 3 (2,5)
278 should 3 (6,12)
278 fail 3 (13,17)
278 the 3 (18,21)
278 parser 3 (22,28)
.269 * 5 (0,1)
269 / 5 (1,2)
263 int 7 (0,3)
278 mian 7 (4,8)
272 ( 7 (8,9)
273 ) 7 (9,10)
274 { 8 (0,1)
263 int 9 (4,7)
278 a 9 (8,9)
266 = 9 (10,11)
279 1 9 (12,13)
276 ; 9 (13,14)
275 } 10 (0,1)
```
可见只匹配了最近的回注释
`*/`
标记
语法分析:
```
c
error
at
line
3
column
2
:
syntax
error
```
在第三行报错,符合预期。
## 实验反馈
实验文档挺清晰的~
src/parser/lexical_analyzer.l
View file @
7804af88
...
...
@@ -21,15 +21,6 @@ void comment_helper(char *comment, unsigned int len)
#ifdef __DEBUG_COMMENT__
printf("Get COMMENT in line<%d>: \"%s\"\n", lines, comment);
#endif
/* pos_end += 2;
* for (int i = 2; i < len-2; i++){
* if (comment[i] == '\n' || comment[i] == '\r'){
* lines++;
* pos_end = 0;
* } else
* pos_end++;
* }
* pos_end += 2; */
}
/*****************声明和选项设置 end*****************/
...
...
tests/parser/syntree_simple/*.syntax_tree
deleted
100644 → 0
View file @
38c8231f
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment