-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcalc.y
executable file
·174 lines (139 loc) · 4.55 KB
/
calc.y
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
169
170
171
172
173
174
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "calc.h"
/* prototypes */
nodeType *opr(int oper, int nops, ...);
nodeType *id(int i);
nodeType *con(int value);
nodeType *boole(int value);
void freeNode(nodeType *p);
int ex(nodeType *p);
int yylex(void);
void yyerror(char *s);
int sym[26];
%}
%union {
int iValue; /* integer value */
int bValue;
char sIndex; /* symbol table index */
nodeType *nPtr; /* node pointer */
};
%token <iValue> NUMBER
%token <bValue> TRUE FALSE
%token <sIndex> VARIABLE
%token WHILE IF PRINT END DO THEN ELSE OR AND NOT OVER PLUS MINUS MULTI LESS BIGGER EQUAL ASSIGN LESSEQ BIGEQ LAPREN COMMA RPAREN SEMI START
%nonassoc IFX
%nonassoc ELSE
%left GE LE EQ NE LESS BIGGER
%left PLUS MINUS
%left MULTI OVER
%nonassoc UMINUS
%type <nPtr> expitem boolreln stmnt explist
%%
prgmbody :
stmntlist { exit(0); }
;
stmntlist :
stmntlist stmnt { ex($2); freeNode($2); }
| /* NULL */
;
stmnt :
PRINT expitem SEMI { $$ = opr(PRINT, 1, $2,SEMI); }
| START explist END { $$ = $2; }
| WHILE expitem DO stmnt { $$ = opr(WHILE, 2, $2, $4); }
| IF expitem THEN stmnt { $$ = opr(IF, 2, $2, $4); }
| IF expitem THEN stmnt ELSE stmnt { $$ = opr(IF, 3, $2, $4, $6); }
| VARIABLE ASSIGN expitem SEMI { $$ = opr(ASSIGN, 2, id($1), $3); }
;
explist :
expitem { $$ = $1; }
| explist SEMI expitem { $$ = opr(SEMI, 2, $1, $3); }
;
expitem :
NUMBER { $$ = con($1); }
| expitem PLUS expitem { $$ = opr(PLUS, 2, $1, $3); }
| expitem MINUS expitem { $$ = opr(MINUS, 2, $1, $3); }
| expitem MULTI expitem { $$ = opr(MULTI, 2, $1, $3); }
| expitem OVER expitem { $$ = opr(OVER, 2, $1, $3); }
| FALSE { $$ = boole($1); }
| TRUE { $$ = boole($1); }
| VARIABLE { $$ = id($1); }
| boolreln
| LAPREN expitem RPAREN { $$ = $2; }
| expitem OR expitem
| expitem AND expitem
| NOT expitem
;
boolreln :
expitem LESS expitem { $$ = opr(LESS, 2, $1, $3); }
| expitem LESSEQ expitem { $$ = opr(LESSEQ, 2, $1, $3); }
| expitem EQUAL expitem { $$ = opr(EQUAL, 2, $1, $3); }
| expitem BIGEQ expitem { $$ = opr(BIGEQ, 2, $1, $3); }
| expitem BIGGER expitem { $$ = opr(BIGGER, 2, $1, $3); }
;
%%
nodeType *con(int value) {
nodeType *p;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeCon;
p->con.value = value;
return p;
}
nodeType *boole(int boo) {
nodeType *p;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeBoolean;
p->boole.boo = boo;
return p;
}
nodeType *id(int i) {
nodeType *p;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeId;
p->id.i = i;
return p;
}
nodeType *opr(int oper, int nops, ...) {
va_list ap;
nodeType *p;
int i;
/* allocate node, extending op array */
if ((p = malloc(sizeof(nodeType) + (nops-1) * sizeof(nodeType *))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeOpr;
p->opr.oper = oper;
p->opr.nops = nops;
va_start(ap, nops);
for (i = 0; i < nops; i++)
p->opr.op[i] = va_arg(ap, nodeType*);
va_end(ap);
return p;
}
void freeNode(nodeType *p) {
int i;
if (!p) return;
if (p->type == typeOpr) {
for (i = 0; i < p->opr.nops; i++)
freeNode(p->opr.op[i]);
}
free (p);
}
void yyerror(char *s) {
fprintf(stdout, "%s\n", s);
}
int main(void) {
yyparse();
return 0;
}