Mercurial > ~dholland > hg > ag > index.cgi
comparison tests/agcl/oldagsrc/bciastp.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 BCIAST.SYN | |
4 | |
5 Compiler for Byte Code Interpreter (using parse tree) | |
6 Copyright (c) 1997 Parsifal Software, All Rights Reserved. | |
7 | |
8 The expression syntax is borrowed from C but with the | |
9 addition of the FORTRAN exponentiation operator (**). | |
10 | |
11 The cast, increment, and decrement operators are not | |
12 implemented, nor are operations that are defined only | |
13 for integers: | |
14 Bitwise logical operators: &, |, ^, ~, &=, |=, ^= | |
15 Remainder operators: %, %= | |
16 Shift operators: <<, >>, >>=, <<= | |
17 | |
18 The supported operations are: | |
19 Assignment operators: =, +=, -=, *=, /= | |
20 Conditional expressions: ? : | |
21 Logical operators: !, &&, || | |
22 Comparison operators: ==, !=, <, <=, >, >= | |
23 Binary arithmetic operators: +, -, *, / | |
24 Exponentiation: ** | |
25 Unary arithmetic operators: +, - | |
26 Parentheses | |
27 Built-in functions LOG, EXP | |
28 | |
29 All arithmetic is double precision floating point. | |
30 | |
31 Statements may include expression statements, blocks, if/else statements | |
32 or while statements, following the rules of C. | |
33 | |
34 The statement syntax has been written to avoid the conventional | |
35 if/else ambiguity. | |
36 | |
37 There are no declarations. All variables are presumed to be double. | |
38 | |
39 Input strings may contain any number of statements. White space may be | |
40 used freely, including both C and C++ style comments. | |
41 | |
42 vmParse makes the following external calls: | |
43 void pushChar(int character); | |
44 Push the specified character onto a character stack. | |
45 | |
46 int locateVariable(int nameLength); | |
47 Pop the last nameLength characters from the character stack | |
48 and, treating them as the name of a variable, return an | |
49 index into the variable array. | |
50 | |
51 Overrides for macros defined by AnaGram, such as SYNTAX_ERROR | |
52 are included in VMDEFS.H | |
53 | |
54 VMPT.SYN is compiled with the AnaGram parser generator | |
55 yielding VMPT.H and VMPT.CPP. | |
56 | |
57 To build VMPT, compile and link VMPT.CPP, VMDEMO.CPP and PTREE.CPP | |
58 with your C++ compiler. | |
59 | |
60 For information about AnaGram, visit http://www.parsifalsoft.com. | |
61 */ | |
62 | |
63 #include "bciast.h" | |
64 #include "agstk.h" // Defines AgStack<Object> | |
65 #include "agstr.h" // Defines AgString et al | |
66 #include <math.h> // for pow() | |
67 #include "ptree.h" | |
68 | |
69 //typedef AgStack<Statement *> StatementList; | |
70 | |
71 } | |
72 // -- CONFIGURATION SECTION ---------------------------- | |
73 [ | |
74 disregard white space | |
75 lexeme {real, name} | |
76 pointer input | |
77 parser name = astParse | |
78 parser file name = "#.cpp" | |
79 reentrant parser | |
80 | |
81 wrapper {AgStack<Statement *>, AgString} | |
82 | |
83 // Put the following in the parser control block for use during parsing | |
84 extend pcb { | |
85 // Maps symbol names to variables | |
86 // AgSharedStringDictionary symbolDictionary; | |
87 AbstractSyntaxTree *ast; | |
88 | |
89 // Temporary space to accumulate identifiers while parsing | |
90 AgString charStack; | |
91 } | |
92 ] | |
93 | |
94 /* | |
95 * Mark input string with $ to indicate it is the "grammar token", | |
96 * that is, the whole of the input we're intending to parse. | |
97 */ | |
98 (Program *) input string $ | |
99 -> statements:s, eof = PCB.ast->makeProgram(s); | |
100 | |
101 /* | |
102 * Zero or more statements. Generate a list of pointers to | |
103 * statement descriptors. | |
104 */ | |
105 (AgStack<Statement *>) statements | |
106 -> =AgStack<Statement *>(); | |
107 -> statements:s, statement:x =s.push(x); | |
108 | |
109 /* | |
110 * A single statement. | |
111 * | |
112 * Here, an "open" statement is a statement that can legally be | |
113 * followed by an "else" keyword. A "closed" statement is one that | |
114 * cannot. | |
115 * | |
116 * This resolves the common if-then-else ambiguity. See ifelse.html for | |
117 * a discussion of the ambiguity and this technique for resolving it. | |
118 */ | |
119 (Statement *) statement | |
120 -> closed statement | |
121 -> open statement | |
122 | |
123 /* | |
124 Any statement than can accept a dengling else clause | |
125 is an open statement | |
126 */ | |
127 | |
128 (Statement *) open statement | |
129 -> "if", '(', expression:x, ')', | |
130 statement:s = PCB.ast->makeIfStatement(x, s); | |
131 -> "if", '(', expression:x, ')', | |
132 closed statement:s1, | |
133 "else", | |
134 open statement:s2 = PCB.ast->makeIfElseStatement(x,s1,s2); | |
135 -> "while", '(', expression:x, ')', | |
136 open statement:s = PCB.ast->makeWhileStatement(x,s); | |
137 -> "for", '(', | |
138 expression:init, ';', | |
139 expression:cond, ';', | |
140 expression:inc, ')', open statement:s = PCB.ast->makeForStatement(init, cond, inc, s); | |
141 | |
142 (Statement *) closed statement | |
143 -> "if", '(', expression:x, ')', closed statement:s1, | |
144 "else", closed statement:s2 = PCB.ast->makeIfElseStatement(x,s1,s2); | |
145 -> "while", '(', expression:x, ')', | |
146 closed statement:s = PCB.ast->makeWhileStatement(x,s); | |
147 -> "for", '(', | |
148 expression:init, ';', | |
149 expression:cond, ';', | |
150 expression:inc, ')', closed statement:s = PCB.ast->makeForStatement(init, cond, inc, s); | |
151 -> simple statement:x = x; | |
152 | |
153 /* | |
154 * Statements that do not end with other statements. These all behave the | |
155 * same way with respect to the closed statement/open statement construct | |
156 * above, and are therefore factored out to PCB.ast->make it clearer. | |
157 * | |
158 * The bare expression appendss a pop instruction so that the resulting | |
159 * byte code will discard the expression's value. (This is not an | |
160 * optimizing compiler.) | |
161 */ | |
162 (Statement *) simple statement | |
163 -> "do", statement:s, | |
164 "while", '(', expression:x, ')', ';' = PCB.ast->makeDoStatement(s,x); | |
165 -> expression:x, ';' = PCB.ast->makeExpressionStatement(x); | |
166 -> ';' = PCB.ast->makeStatement(); | |
167 -> '{', statements:s, '}' = PCB.ast->makeStatementBlock(s); | |
168 | |
169 // General expression. As in C, comma expression has the lowest precedence. | |
170 (Expression *) expression | |
171 -> assignment expression | |
172 -> expression:x, ',', assignment expression:y = PCB.ast->makeCommaExpression(x,y); | |
173 | |
174 /* | |
175 * Next precedence: assignments. Again, as in C, except we don't | |
176 * support quite all the operators. | |
177 */ | |
178 (Expression *) assignment expression | |
179 -> conditional expression | |
180 -> name:k, '=', assignment expression:x =PCB.ast->makeSimpleAssignment(k, x); | |
181 -> name:k, "+=", assignment expression:x =PCB.ast->makeAddMemory(k, x); | |
182 -> name:k, "-=", assignment expression:x =PCB.ast->makeSubMemory(k, x); | |
183 -> name:k, "*=", assignment expression:x =PCB.ast->makeMulMemory(k, x); | |
184 -> name:k, "/=", assignment expression:x =PCB.ast->makeDivMemory(k, x); | |
185 | |
186 // Conditional expression (ternary operator) | |
187 (Expression *) conditional expression | |
188 -> logical or expression | |
189 -> logical or expression:c, '?', | |
190 expression:x, ':', conditional expression:y =PCB.ast->makeConditionalExpression(c,x,y); | |
191 | |
192 // Logical expressions with short-cut evaluation, as in C. | |
193 (Expression *) logical or expression | |
194 -> logical and expression | |
195 -> logical or expression:x, "||", | |
196 logical and expression:y =PCB.ast->makeLogicalOrExpression(x, y); | |
197 | |
198 (Expression *) logical and expression | |
199 -> equality expression | |
200 -> logical and expression:x, "&&", | |
201 equality expression:y =PCB.ast->makeLogicalAndExpression(x,y); | |
202 | |
203 // Arithmetic expressions, in operator precedence order. | |
204 (Expression *) equality expression | |
205 -> relational expression | |
206 -> equality expression:x, "==", relational expression:y =PCB.ast->makeEqExpression(x,y); | |
207 -> equality expression:x, "!=", relational expression:y =PCB.ast->makeNeExpression(x,y); | |
208 | |
209 (Expression *) relational expression | |
210 -> additive expression | |
211 -> relational expression:x, '<', additive expression:y =PCB.ast->makeLtExpression(x,y); | |
212 -> relational expression:x, "<=", additive expression:y =PCB.ast->makeLeExpression(x,y); | |
213 -> relational expression:x, '>', additive expression:y =PCB.ast->makeGtExpression(x,y); | |
214 -> relational expression:x, ">=", additive expression:y =PCB.ast->makeGeExpression(x,y); | |
215 | |
216 (Expression *) additive expression | |
217 -> multiplicative expression | |
218 -> additive expression:x, '+', | |
219 multiplicative expression:y =PCB.ast->makeAddExpression(x,y); | |
220 -> additive expression:x, '-', | |
221 multiplicative expression:y =PCB.ast->makeSubExpression(x,y); | |
222 | |
223 (Expression *) multiplicative expression | |
224 -> unary expression | |
225 -> multiplicative expression:x, '*', unary expression:y =PCB.ast->makeMulExpression(x,y); | |
226 -> multiplicative expression:x, '/', unary expression:y =PCB.ast->makeDivExpression(x,y); | |
227 | |
228 (Expression *) unary expression | |
229 -> factor | |
230 -> '-', unary expression:x =PCB.ast->makeNegExpression(x); | |
231 -> '+', unary expression:x =x; | |
232 -> '!', unary expression:x =PCB.ast->makeNotExpression(x); | |
233 | |
234 /* | |
235 * Syntactically, we can use ** for exponentiation because we don't have | |
236 * pointers. (In C, ** could be confused with pointer indirection.) | |
237 * Note that the precedence of ** is inserted between unary +/- and unary !. | |
238 */ | |
239 (Expression *) factor | |
240 -> primary | |
241 -> primary:x, "**", unary expression:y =PCB.ast->makePowExpression(x,y); | |
242 | |
243 /* | |
244 * Primary expression - bottom level of expression syntax. | |
245 * Variable references, constants, the builtin functions. | |
246 * Also, another expression in parentheses. (This is how you make | |
247 * parentheses work the way they're supposed to.) | |
248 */ | |
249 (Expression *) primary | |
250 -> real:x =PCB.ast->makeConstant(x); | |
251 -> name:k =PCB.ast->makeVariable(k); | |
252 -> "log", '(', expression:x, ')' =PCB.ast->makeLogExpression(x); | |
253 -> "exp", '(', expression:x, ')' =PCB.ast->makeExpExpression(x); | |
254 -> "sqrt", '(', assignment expression:x, ')' =PCB.ast->makeSqrtExpression(x); | |
255 -> '(', expression:x, ')' =x; | |
256 | |
257 // -- LEXICAL UNITS ------------------------------------------------ | |
258 digit = '0-9' | |
259 eof = 0 | |
260 letter = 'a-z' + 'A-Z' + '_' | |
261 | |
262 (void) white space | |
263 -> ' ' + '\t' + '\f' + '\v' + '\r' + '\n' | |
264 -> "/*", ~eof?..., "*/" // C style comment | |
265 -> "//", ~(eof+'\n')?..., '\n' // C++ style comment | |
266 | |
267 (double) real | |
268 -> simple real:x =x; | |
269 -> simple real:x, 'e'+'E', '+'?,exponent:e =x*pow(10,e); | |
270 -> simple real:x, 'e'+'E', '-',exponent:e =x*pow(10,-e); | |
271 | |
272 (double) simple real | |
273 -> integer part:i, '.', fraction part:f = i+f; | |
274 -> integer part:i, '.'? = i; | |
275 -> '.', fraction part:f = f; | |
276 | |
277 (double) integer part | |
278 -> digit:d = d-'0'; | |
279 -> integer part:x, digit:d = 10*x + d-'0'; | |
280 | |
281 (double) fraction part | |
282 -> digit:d =(d-'0')/10.; | |
283 -> digit:d, fraction part:f =(d-'0' + f)/10.; | |
284 | |
285 (int) exponent | |
286 -> digit:d = d-'0'; | |
287 -> exponent:x, digit:d = 10*x + d-'0'; | |
288 | |
289 (AgString) name | |
290 -> letter: c =AgString().concat(c); | |
291 -> name:s, letter+digit: c =s.concat(c); | |
292 | |
293 { // begin embedded C | |
294 | |
295 void ag_delete_wrappers(astParse_pcb_struct *); | |
296 | |
297 void parseStatements(AbstractSyntaxTree *tree, char *text) { | |
298 astParse_pcb_struct pcb; | |
299 pcb.ast = tree; | |
300 pcb.pointer = (unsigned char *) text; | |
301 astParse(&pcb); | |
302 if (pcb.exit_flag == AG_SUCCESS_CODE) tree->setRoot(astParse_value(&pcb)); | |
303 else ag_delete_wrappers(&pcb); | |
304 } | |
305 } // end of embedded C | |
306 /********************* End of bciast.syn ************************/ |