tastynoob
Articles58
Tags18
Categories7
一个计算器的语法分析器

一个计算器的语法分析器

之前做了个计算器项目,用到了语法分析,我也是对语法分析方面很感兴趣,就来写一篇博客

先把所有代码粘贴上
这个计算器的语法分析采用抽象语法分析,其语法表达式为:

1
2
3
4
5
6
7
8
expr : term + term
| term - term
| term
term : pri * pri
| pri / pri
| pri
pri : num
| '(' expr ')'

代码挺简单的,拓展性也挺强,可直接复制粘贴

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
158
159
160
161
162
163
164
165
166
167
168
#include <math.h>
#include <string.h>

typedef struct
{
char tag;
float val;
} Token;

typedef struct
{
char* str;
int p;
Token buffer;
char null;
} Parser;//用来缓存数据

//创建一个token
Token CreateToken(char ch);
Token CreateToken_(char ch,float v);

Parser parser = { 0,0,{0},1 };
int error_flag =0;

float Term();
Token Get();
float Expression();
float Primary();

void Error(){//错误处理函数,这里可以随便改
error_flag = 1;
}

//创建一个token
Token CreateToken(char ch){
Token t = {ch,0};
return t;
}
Token CreateToken_(char ch,float v){
Token t = {ch,v};
return t;
}


void Push(Token* t){
if(!parser.null){
Error();
}
parser.buffer = *t;
parser.null=0;
}

Token Get(){
if(!parser.null){
parser.null=1;
return parser.buffer;
}
char ch = parser.str[parser.p++];
float val;
switch (ch)
{
case '=':
return CreateToken(ch);
case '+':case '-':case '*':case '/':case '(':case ')':
return CreateToken(ch);
case '0':case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9':
parser.p--;
sscanf(&parser.str[parser.p],"%f",&val);
while((parser.str[parser.p]<='9' && parser.str[parser.p]>='0') || parser.str[parser.p]=='.')parser.p++;
return CreateToken_('0',val);
case 's':case 'c':case 't':
return CreateToken(ch);
default:
return CreateToken(ch);
}
}

float Expression(){//expr表达式
float val = Term();
Token t = Get();
while (t.tag == '+' || t.tag == '-')
{
if (t.tag == '+')
{
val += Term();
t = Get();
}
if (t.tag == '-')
{
val -= Term();
t = Get();
}
}
Push(&t);
return val;
}

float Term(){//term表达式
float val = Primary();

while (1)
{
Token token = Get();
switch (token.tag)
{
case '*':
val *= Primary();
break;
case '/':
val /= Primary();
break;
default:
Push(&token);
return val;
}
}
}

float Primary() {//pri表达式
float val=0;
Token token = Get();
switch (token.tag)
{
case '0':
val = token.val;
break;
case '(':
val = Expression();
token = Get();
if (token.tag != ')')
{
Error();
}
break;
default:
Error();
}
return val;
}

float ParseGet(char* str){
parser.str = str;
float val=0;
while (1) {
Token token = Get();
if (token.tag == '=')
{
parser.null=1;
parser.p=0;
parser.str=0;
return val;
}
else
{
Push(&token);
val = Expression();
}
if (error_flag){
error_flag = 0;

parser.null=1;
parser.p=0;
parser.str=0;
return FLT_MAX;
}
}
}
Author:tastynoob
Link:https://tastynoob.github.io/1970/01/01/%E7%AE%97%E6%B3%95/%E8%AE%A1%E7%AE%97%E5%99%A8%E8%AF%AD%E6%B3%95%E5%88%86%E6%9E%90/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可
×