Mercurial > ~dholland > hg > ag > index.cgi
comparison examples/mpp/ex.syn @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13d2b8934445 |
---|---|
1 { | |
2 /* | |
3 * AnaGram, a System for Syntax Directed Programming | |
4 * C Macro preprocessor | |
5 * Constant Expression Evaluator Module | |
6 * | |
7 * Copyright 1993-2000 Parsifal Software. All Rights Reserved. | |
8 * | |
9 * This software is provided 'as-is', without any express or implied | |
10 * warranty. In no event will the authors be held liable for any damages | |
11 * arising from the use of this software. | |
12 * | |
13 * Permission is granted to anyone to use this software for any purpose, | |
14 * including commercial applications, and to alter it and redistribute it | |
15 * freely, subject to the following restrictions: | |
16 * | |
17 * 1. The origin of this software must not be misrepresented; you must not | |
18 * claim that you wrote the original software. If you use this software | |
19 * in a product, an acknowledgment in the product documentation would be | |
20 * appreciated but is not required. | |
21 * 2. Altered source versions must be plainly marked as such, and must not be | |
22 * misrepresented as being the original software. | |
23 * 3. This notice may not be removed or altered from any source distribution. | |
24 */ | |
25 | |
26 #include "mpp.h" | |
27 } | |
28 | |
29 [ | |
30 //far tables // uncomment for 16 bit environment | |
31 ~allow macros | |
32 line numbers | |
33 //escape backslashes // uncomment if using MSVC++ | |
34 default token type = long | |
35 default input type = token | |
36 ~declare pcb | |
37 ~diagnose errors | |
38 error trace | |
39 event driven | |
40 input values | |
41 ~test range | |
42 ~lines and columns | |
43 enum { | |
44 eof =0, | |
45 SPACE =' ', | |
46 ANDAND ='A', // "&&" | |
47 ANDassign, // "&=" | |
48 ARROW, // "->" | |
49 CONCAT, // "##" | |
50 DECR, // "--" | |
51 DIVassign, // "/=" | |
52 ELLIPSIS, // "..." | |
53 EQ, // "==" | |
54 ERassign, // "^=" | |
55 GE, // ">=" | |
56 ICR, // "++" | |
57 LE, // "<=" | |
58 LS, // "<<" | |
59 LSassign, // "<<=" | |
60 MODassign, // "%=" | |
61 MINUSassign, // "-=" | |
62 MULTassign, // "*=" | |
63 NE, // "!=" | |
64 ORassign, // "|=" | |
65 OROR, // "||" | |
66 PLUSassign, // "+=" | |
67 RS, // ">>" | |
68 RSassign, // ">>=" | |
69 CHARACTERconstant, // character constant | |
70 STRINGliteral, // character string | |
71 HEXconstant =129, | |
72 OCTconstant, | |
73 DECconstant, | |
74 FLOATconstant, // real | |
75 NAME, | |
76 AUTO, // "auto" | |
77 BREAK, // "break" | |
78 CASE, // "case" | |
79 CHAR, // "char" | |
80 CONSTANT, // "const" | |
81 CONTINUE, // "continue" | |
82 DEFAULT, // "default" | |
83 DO, // "do" | |
84 DOUBLE, // "double" | |
85 ELSE, // "else" | |
86 ENUM, // "enum" | |
87 EXTERN, // "extern" | |
88 FLOAT, // "float" | |
89 FOR, // "for" | |
90 GOTO, // "goto" | |
91 IF, // "if" | |
92 INT, // "int" | |
93 LONG, // "long" | |
94 REGISTER, // "register" | |
95 RETURN, // "return" | |
96 SHORT, // "short" | |
97 SIGNED, // "signed" | |
98 SIZEOF, // "sizeof" | |
99 STATIC, // "static" | |
100 STRUCT, // "struct" | |
101 SWITCH, // "switch" | |
102 TYPEDEF, // "typedef" | |
103 UNION, // "union" | |
104 UNSIGNED, // "unsigned" | |
105 VOIDkey, // "void" | |
106 VOLATILE, // "volatile" | |
107 WHILE, // "while" | |
108 UNRECOGNIZED, | |
109 } | |
110 parser file name = "#.cpp" | |
111 ] | |
112 | |
113 expression evaluator $ | |
114 -> exp, eof | |
115 | |
116 exp | |
117 -> conditional exp | |
118 | |
119 conditional exp | |
120 -> logical or exp | |
121 -> logical or exp:c, '?', conditional exp:x, ':', | |
122 conditional exp:y = c != 0 ? x : y; | |
123 | |
124 logical or exp | |
125 -> logical and exp | |
126 -> logical or exp:x, OROR, logical and exp:y =x != 0 || y!=0; | |
127 | |
128 logical and exp | |
129 -> inclusive or exp | |
130 -> logical and exp:x, ANDAND, inclusive or exp:y =x != 0 && y !=0; | |
131 | |
132 inclusive or exp | |
133 -> exclusive or exp | |
134 -> inclusive or exp:x, '|', exclusive or exp:y =x | y; | |
135 | |
136 exclusive or exp | |
137 -> and exp | |
138 -> exclusive or exp:x, '^', and exp:y =x ^ y; | |
139 | |
140 and exp | |
141 -> equality exp | |
142 -> and exp:x, '&', equality exp:y =x & y; | |
143 | |
144 equality exp | |
145 -> relational exp | |
146 -> equality exp:x, EQ, relational exp:y =x == y; | |
147 -> equality exp:x, NE, relational exp:y =x != y; | |
148 | |
149 relational exp | |
150 -> shift exp | |
151 -> relational exp:x, '<', shift exp:y =x < y; | |
152 -> relational exp:x, '>', shift exp:y =x > y; | |
153 -> relational exp:x, LE, shift exp:y =x <= y; | |
154 -> relational exp:x, GE, shift exp:y =x >= y; | |
155 | |
156 shift exp | |
157 -> additive exp | |
158 -> shift exp:x, LS, additive exp:y =x << y; | |
159 -> shift exp:x, RS, additive exp:y =x >> y; | |
160 | |
161 additive exp | |
162 -> multiplicative exp | |
163 -> additive exp:x, '+', multiplicative exp:y =x + y; | |
164 -> additive exp:x, '-', multiplicative exp:y =x - y; | |
165 | |
166 multiplicative exp | |
167 -> unary exp | |
168 -> multiplicative exp:x, '*', unary exp:y =x * y; | |
169 -> multiplicative exp:x, '/', nonzero:y =x / y; | |
170 -> multiplicative exp:x, '%', nonzero:y =x % y; | |
171 | |
172 nonzero | |
173 -> unary exp: x ={ | |
174 if (x != 0) return x; | |
175 syntax_error("Divide by Zero"); | |
176 PCB.exit_flag = 5; | |
177 return x; | |
178 } | |
179 | |
180 unary exp | |
181 -> primary exp | |
182 -> '+', unary exp:x = x; | |
183 -> '-', unary exp:x = -x; | |
184 -> '~', unary exp:x = ~x; | |
185 -> '!', unary exp:x = !x; | |
186 | |
187 primary exp | |
188 -> HEXconstant:x =decode("%lx",x.handle); | |
189 -> OCTconstant:x =decode("%lo",x.handle); | |
190 -> DECconstant:x =decode("%ld",x.handle); | |
191 -> CHARACTERconstant:x =decode("'%lc'",x.handle); | |
192 -> NAME =0; | |
193 -> '(', conditional exp:x, ')' =x; | |
194 | |
195 | |
196 { // Embedded C | |
197 #include <stdio.h> | |
198 | |
199 | |
200 // Macro Definitions | |
201 | |
202 #define PCB (*ex_pcb) | |
203 #define SYNTAX_ERROR syntax_error("Syntax error in constant expression"); | |
204 | |
205 | |
206 // Static data | |
207 | |
208 static ex_pcb_type *ex_pcb; // Pointer to active pcb | |
209 | |
210 | |
211 /* | |
212 | |
213 decode() is a simple function to recover the numeric value of a | |
214 token. Its task is somewhat simplified by the fact that the only | |
215 values allowed in this example are longs. | |
216 | |
217 */ | |
218 | |
219 static long decode(const char *fmt, unsigned ndx) { | |
220 long v; | |
221 sscanf(td[ndx], fmt, &v); | |
222 return v; | |
223 } | |
224 | |
225 | |
226 // Members of expression_evaluator Class | |
227 | |
228 | |
229 // Constructor | |
230 | |
231 /* | |
232 Each expression_evaluator has its own parser control block. | |
233 Therefore, before calling ex() or its initializer init_ex() it is | |
234 necessary to make sure the pcb pointer for ex() is correctly set. | |
235 */ | |
236 | |
237 expression_evaluator::expression_evaluator() { | |
238 ex_pcb = &pcb; // set up pointer to pcb | |
239 init_ex(); // init parser | |
240 } | |
241 | |
242 | |
243 // Reset expression_evaluator | |
244 | |
245 token_sink& reset(expression_evaluator &x) { | |
246 ex_pcb = &x.pcb; // set up pointer to pcb | |
247 init_ex(); // init parser | |
248 return x; | |
249 } | |
250 | |
251 | |
252 // Xmit Token to expression_evaluator | |
253 | |
254 /* | |
255 There could be space tokens in the input to the expression | |
256 evaluator, but they are never significant so it is acceptable to | |
257 filter them out on input. | |
258 | |
259 If the expression_evaluator has encountered an error, there is no | |
260 point in giving it any further input. | |
261 | |
262 Otherwise, the input_code and input_value fields of the pcb are set | |
263 up, the pcb pointer for ex is set, and ex() is called to deal with | |
264 the token. | |
265 | |
266 When looping, it is only necessary to set up ex_pcb at the | |
267 beginning of the loop. | |
268 */ | |
269 | |
270 token_sink& expression_evaluator::operator << (token t) { | |
271 if (t.id == SPACE || pcb.exit_flag != AG_RUNNING_CODE) return *this; | |
272 pcb.input_code = t.id; | |
273 pcb.input_value = t; | |
274 ex_pcb = &pcb; | |
275 ex(); | |
276 return *this; | |
277 } | |
278 | |
279 token_sink &expression_evaluator::operator << (token *tp) { | |
280 ex_pcb = &pcb; | |
281 while (pcb.exit_flag == AG_RUNNING_CODE) { | |
282 if (pcb.input_code == SPACE) continue; | |
283 pcb.input_code = tp->id; | |
284 pcb.input_value = *tp++; | |
285 ex(); | |
286 } | |
287 return *this; | |
288 } | |
289 | |
290 | |
291 // Return Value of expression_evaluator | |
292 | |
293 /* | |
294 The (long) cast operator is overloaded to provide a mechanism to | |
295 retrieve the value of the expression evaluated by the | |
296 expression_evaluator. | |
297 | |
298 If there was a syntax error, the return value is zero. | |
299 */ | |
300 | |
301 expression_evaluator::operator long() { | |
302 ex_pcb = &pcb; | |
303 if (pcb.exit_flag == AG_SUCCESS_CODE) return ex_value(); | |
304 else return 0; | |
305 } | |
306 | |
307 /* | |
308 // Check expression_evaluator for error | |
309 | |
310 int error(expression_evaluator &x) { | |
311 return x.pcb.exit_flag != AG_SUCCESS_CODE; | |
312 } | |
313 */ | |
314 } // End of Embedded C |