-
Notifications
You must be signed in to change notification settings - Fork 0
/
expr.c
147 lines (132 loc) · 3.53 KB
/
expr.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
#include "defs.h"
#include "data.h"
#include "decl.h"
// Parse a primary factor and return an
// AST node representing it.
static struct ASTnode *primary(void) {
struct ASTnode *n;
switch (Token.token) {
case T_INTLIT:
n = mkastleaf(A_INTLIT, Token.intvalue);
scan(&Token);
return n;
case T_LPAREN:
scan(&Token);
n = binexpr(0);
if (Token.token != T_RPAREN) {
fprintf(stderr, "syntax error on line %d, expected ')'\n", Line);
exit(1);
}
scan(&Token);
return n;
case T_PRINT:
scan(&Token);
n = binexpr(0);
if (Token.token != T_SEMI) {
fprintf(stderr, "syntax error on line %d, expected ';'\n", Line);
exit(1);
}
n = mkastunary(A_PRINT, n, 0);
scan(&Token);
return n;
default:
fprintf(stderr, "syntax error on line %d, token %d\n", Line, Token.token);
exit(1);
}
}
// Convert a binary operator token into an AST operation.
int arithop(int tokentype) {
switch (tokentype) {
case T_PLUS:
return (A_ADD);
case T_MINUS:
return (A_SUBTRACT);
case T_STAR:
return (A_MULTIPLY);
case T_SLASH:
return (A_DIVIDE);
case T_LPAREN:
return (A_LPAREN);
case T_RPAREN:
return (A_RPAREN);
case T_PERCENT:
return (A_MODULO);
case T_PRINT:
return (A_PRINT);
default:
fprintf(stderr, "SYntax error on line %d, token %d\n", Line, tokentype);
exit(1);
}
}
// Operator precedence for each token
static int OpPrec[] = { 0, 10, 10, 20, 20, 20, 0, 0, 0, 0, 0};
// Check that we have a binary operator and
// return its precedence.
static int op_precedence(int tokentype) {
switch (tokentype) {
case T_LPAREN:
return 30;
case T_RPAREN:
return 30;
case T_PRINT:
return 5;
case T_SEMI:
return 5;
default:
int prec = OpPrec[tokentype];
if (prec == 0) {
fprintf(stderr, "Syntax error on line %d, token %d\n", Line, tokentype);
exit(1);
}
return prec;
}
}
struct ASTnode *binexpr(int ptp) {
struct ASTnode *left, *right;
int tokentype;
// Get the primary expression on the left.
left = primary();
// If no tokens left, return just the left node
tokentype = Token.token;
if (tokentype == T_SEMI || tokentype == T_EOF)
return left;
// While the precedence of this token is
// more than that of the previous token precedence
while (op_precedence(tokentype) > ptp && tokentype != T_RPAREN) {
// Fetch the next token
scan(&Token);
// Check for opening parenthesis
if (tokentype == T_LPAREN) {
// Parse the expression inside the parentheses
right = binexpr(0);
// Check for closing parenthesis
if (Token.token != T_RPAREN) {
fprintf(stderr, "syntax error on line %d, expected ')'\n", Line);
exit(1);
}
scan(&Token);
}
else if (tokentype == T_PRINT) {
right = binexpr(0);
if (Token.token != T_SEMI) {
fprintf(stderr, "syntax error on line %d, expected ';'\n", Line);
exit(1);
}
scan(&Token);
} else {
// Parse the next primary expression
right = binexpr(op_precedence(tokentype));
}
if (tokentype != T_PRINT) {
// Join the left and right expressions with the operator
left = mkastnode(arithop(tokentype), left, right, 0);
}
// Update the details of the current token
tokentype = Token.token;
if (tokentype == T_SEMI)
return (left);
}
// Return the tree we have when the precedence
// is the same or lower
return left;
}