编译原理与设计-Lab5-语法分析实验

选择 C 语言的一个子集,基于 BIT-MiniCC 构建 C 语法子集的语法分 析器,该语法分析器能够读入词法分析器输出的存储在文件中的属性字符流,进 行语法分析并进行错误处理,如果输入正确时输出 JSON 格式的语法树,输入不正确时报告语法错误。

实现的具体过程和步骤

1 定义C语言子集

参照后续给出的文法,扩充定义自己希望实现的 C 语言语法子集。参考文法只给出了函数定义以及简单的表达式相关的文法。局部变量声明、分支语 句以及循环语句等需要自己进行扩充。采用自顶向下的分析方法时,不能有左递归,避免文法产生式的多个候选式存在公共因子。如果出现左递归或者公共因子, 则可以通过文法等价变换进行消除。

1 根据C11的语法规则编写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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
statement
: labeledStatement
| compoundStatement
| expressionStatement
| selectionStatement
| iterationStatement
| jumpStatement
;
assignmentOperator
: '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '&=' | '^=' | '|='
;
expressionStatement
: expression? ';'
;
expression
: assignmentExpression
| expression ',' assignmentExpression
;
compoundStatement
: '{' blockItemList? '}'
;
iterationStatement
: 'while' '(' expression ')' statement
| 'do' statement 'while' '(' expression ')' ';'
| 'for' '(' expression? ';' expression? ';' expression? ')' statement
| 'for' '(' declaration expression? ';' expression? ')' statement
;
selectionStatement
: 'if' '(' expression ')' statement ('else' statement)?
| 'switch' '(' expression ')' statement
;
jumpStatement
: 'goto' Identifier ';'
| 'continue' ';'
| 'break' ';'
| 'return' expression? ';'
| 'goto' unaryExpression ';' // GCC extension
;
labeledStatement
: Identifier ':' statement
| 'case' constantExpression ':' statement
| 'default' ':' statement
;

// 局部变量声明
declarationList
: declaration
| declarationList declaration
;
declarationSpecifier
: storageClassSpecifier
| typeSpecifier
| typeQualifier
| functionSpecifier
| alignmentSpecifier
;
initDeclaratorList
: initDeclarator
| initDeclaratorList ',' initDeclarator
;
initDeclarator
: declarator
| declarator '=' initializer
;
declarator
: pointer? directDeclarator gccDeclaratorExtension*
;
directDeclarator
: Identifier
| '(' declarator ')'
;
storageClassSpecifier
: 'typedef'
| 'extern'
| 'static'
| '_Thread_local'
| 'auto'
| 'register'
;
typeSpecifier
: ('void'
| 'char'
| 'short'
| 'int'
| 'long'
| 'float'
| 'double'
| 'signed'
| 'unsigned'
| '_Bool'
;
typeQualifier
: 'const'
;
pointer
: '*' typeQualifierList?
;
initializer
: assignmentExpression
| '{' initializerList '}'
| '{' initializerList ',' '}'
;
initializerList
: designation? initializer
| initializerList ',' designation? initializer
;
assignmentExpression
: conditionalExpression
| unaryExpression assignmentOperator assignmentExpression
;
// 赋值语句
conditionalExpression
: logicalOrExpression ('?' expression ':' conditionalExpression)?
;
logicalAndExpression
: inclusiveOrExpression
| logicalAndExpression '&&' inclusiveOrExpression
;
logicalOrExpression
: logicalAndExpression
| logicalOrExpression '||' logicalAndExpression
;
unaryExpression
: postfixExpression
| '++' unaryExpression
| '--' unaryExpression
| unaryOperator castExpression
| 'sizeof' unaryExpression
| 'sizeof' '(' typeName ')'
;
unaryOperator
: '&' | '*' | '+' | '-' | '~' | '!'
;
constantExpression
: conditionalExpression
;
expression
: assignmentExpression
| expression ',' assignmentExpression
;
postfixExpression
: primaryExpression
| postfixExpression '[' expression ']'
| postfixExpression '(' argumentExpressionList? ')'
| postfixExpression '.' Identifier
| postfixExpression '->' Identifier
| postfixExpression '++'
| postfixExpression '--'
;

2 消除左递归

  • expression

    1
    2
    3
    4
    expression
    : assignmentExpression
    | expression ',' assignmentExpression
    ;

    exp本身不符合LL(0)文法规则,需要消除左递归,消除后expression和expression+分别对应

  • assignmentExpression

    1
    2
    3
    4
    assignmentExpression
    : conditionalExpression
    | unaryExpression assignmentOperator assignmentExpression
    ;

    conditionalExpression的FIRST几核中包含了unaryExpression的FIRST集合,不符合LL(0)文法规法。BITMiniCC中,对于ASTBinaryExpression节点:

    1
    2
    3
    public ASTToken op;
    public ASTExpression expr1;
    public ASTExpression expr2;

    分别对应assignmentOperator,unaryExpression,assignmentExpression

  • postfixExpression

    1
    2
    3
    4
    5
    6
    7
    8
    9
    postfixExpression
    : primaryExpression
    | postfixExpression '[' expression ']'
    | postfixExpression '(' argumentExpressionList? ')'
    | postfixExpression '.' Identifier
    | postfixExpression '->' Identifier
    | postfixExpression '++'
    | postfixExpression '--'
    ;
  • argumentExpressionList

    1
    2
    3
    4
    argumentExpressionList
    : assignmentExpression
    | argumentExpressionList ',' assignmentExpression
    ;

    简化为只有一个参数

2 JAVA实现语法分析器

从递归下降分析方法、LL(1)分析方法、LR 分析方法中选择一种算法, 基于 BIT-MiniCC 设计并实现语法分析器。可以使用 ANTLR,也可以手动编码实现。语法分析的输入为词法分析的输 出,因此语法分析器首先要读入 xxx.tokens 文件;在分析的过程中构建语法树。

3 将语法树输出为 JSON 文件

未完成

运行效果截图

  1. test0

    Example

  2. test1

    Screenshot2020-04-16 00.17.47

    放大

    Screenshot2020-04-16 00.15.33

  3. test2

    Screenshot2020-04-16 00.25.24

  4. test3

    Screenshot2020-04-16 00.27.54

实验心得体会

  • 这次实验对我来说是前所未有的挑战,看懂框架的文法、参照框架和C语言标准实现语法分析器,在编程能力、数据结构、文法基本理解各方面上都有很大的挑战。
  • 首先是对知识的运用,知识基础之薄弱在应用时原形毕露,
  • 在编码过程我遇到了很多问题,反复调试了很多次都无法正确的运行。树生成失败,空指针,对象初始化等等问题层出不穷,一方面是本身对于框架的研究不够,另一方面也是没有严谨编程习惯
  • 这次实验我投入的时间和精力并不足以达到完成这个实验的要求

title:编译原理与设计-Lab5-语法分析实验

author:Anne416wu

link:https://www.annewqx.top/posts/1742/

publish time:2020-04-14

update time:2022-07-20


评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×