This repository has been archived by the owner on Aug 16, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.c
157 lines (130 loc) · 3.03 KB
/
parser.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
150
151
152
153
154
155
156
157
/*
* 语法分析器(parser)的代码实现。
*
* 值得注意的是,这里是使用“递归下降分析法”实现的。
* 递归下降分析,要求对每一个终结符都给出一个分析函数,
* 提供给每个非终结符函数调用。
* 因此,根据parser.h中定义的文法,
* 在开头处就直接声明了一系列内部静态分析函数,
* 他们都是递归下降分析法所必要的。
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <setjmp.h>
#include "parser.h"
/**
* handler 错误处理函数
*
* @param id 错误代码
*/
static void handler(int id);
static AST *parse_re();
static AST *parse_union();
static AST *parse_simple();
static AST *parse_basic();
static AST *parse_cat();
static AST *parse_element();
/* 全局env,用于错误处理 */
static jmp_buf env;
AST *re2ast(const char *re)
{
/* 错误标记,0表示无错误 */
int id;
if ((id = setjmp(env)) == 0) {
set_re(re);
} else {
handler(id);
}
return parse_re();
}
AST *parse_re()
{
AST *left, *right;
left = parse_simple();
right = parse_union();
return ast_alt(left, right);
}
AST *parse_union() {
AST *p;
AST *left, *right;
p = NULL;
if (step('|')) {
left = parse_simple();
right = parse_union();
p = ast_alt(left, right);
}
return p;
}
AST *parse_simple()
{
AST *left, *right;
left = parse_basic();
right = parse_cat();
return ast_cat(left, right);
}
AST *parse_cat()
{
AST *left, *right;
left = parse_basic();
if (left == NULL) {
return NULL;
}
right = parse_cat();
return ast_cat(left, right);
}
AST *parse_basic()
{
AST *p;
p = parse_element();
if (step('*')) {
p = ast_star(p);
}
return p;
}
AST *parse_element()
{
AST *p;
Token *token;
p = NULL;
if (step('(')) {
p = parse_re();
if (step(')')) {
return p;
} else {
longjmp(env, 1); /* Error 1: Missing a ')'. */
}
}
token = next_token();
switch (token->t) {
case END: /* END of STRING */
break;
case METACHAR: /* METACHAR */
rollback();
break;
default: /* OTHER and ESCAPE */
if (isprint(token->c)) {
p = ast_char(token->c);
} else {
longjmp(env, 2); /* Error 2: Char is not printable. */
}
break;
}
return p;
}
void handler(int id)
{
switch (id) {
case 1:
printf("Missing a ')' at position %d.\n", getp());
break;
case 2:
printf("Character at position %d is not printable.\n", getp());
break;
case 3:
default:
printf("Unknown error.\n");
break;
}
exit(id);
}