comparison tests/agcl/oldagsrc/bcip.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 bcip.syn Version 1.0
3
4 A simple byte code compiler
5
6 Copyright (c) 1996-1999 Parsifal Software, All Rights Reserved.
7
8 The expression syntax is borrowed from C but with the addition
9 of the FORTRAN exponentiation operator (**).
10
11 The cast, increment, and decrement operators are not
12 implemented, nor are the following operations that are defined
13 only 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, sqrt
28
29 All arithmetic is double precision floating point.
30
31 Statements may include expression statements, blocks, if/else
32 statements, while statements, do-while statements, or for
33 statements, following the rules of C.
34
35 The statement syntax has been written to avoid the conventional
36 if/else ambiguity.
37
38 There are no declarations. All variables are presumed to be
39 double.
40
41 Input strings may contain any number of statements. White space
42 may be used freely, including both C and C++ style comments.
43
44 The parser is invoked by the constructor for the virtual machine
45 to parse the source code and compile it into byte code.
46
47 With this organization, it is possible to create various
48 virtual machine objects all of which use the same symbol dictionary,
49 so that all can operate on the same data array. Furthermore, if
50 there are multiple data arrays, all consistent with the same
51 symbol dictionary, then any virtual machine object created using the
52 given symbol dictionary can operate on any of the data arrays.
53
54 Thus a given virtual machine may operate on different data
55 arrays at different times. The data array, of course, must be
56 consistent with the symbol dictionary used to initialize the virtual
57 machine.
58
59 The symbol dictionary maps character strings to indices into the
60 data array, so that each unique variable name is assigned a
61 particular location in the data array. Different virtual
62 machines may be initialized with the same symbol dictionary. When
63 this is done, these virtual machines can all operate on the
64 same data array.
65
66 An override for the SYNTAX_ERROR macro defined by AnaGram and
67 the definition of the ScriptMethod class are in the bci.h
68 file. bci.cpp has function definitons for the ScriptMethod
69 class. bcidemo.cpp demonstrates one way to use the virtual
70 machine.
71
72 bcip.syn is compiled with the AnaGram parser generator yielding
73 bcip.h and bcip.cpp.
74
75 To build bcidemo, compile bcip.cpp, bci.cpp, cntnrs.cpp and bcidemo.cpp
76 and link them with your C++ compiler.
77
78 For information about AnaGram, visit http://www.parsifalsoft.com.
79 */
80
81 #include <math.h>
82 #include "bci.h" // defines external interface
83
84 }
85 // -- CONFIGURATION SECTION ----------------------------
86 [
87 disregard white space
88 lexeme {real, name}
89 pointer input
90 parser name = bciParse
91 parser file name = "#.cpp"
92 reentrant parser
93 extend pcb {
94 AgStringDictionary *symbolDictionary;
95 AgStack<double> realList; // List of real constants
96 int compile(AgStringDictionary *, AgString);
97 CodeFragment code;
98
99 AgCharStack charStack; // Stack to accumulate variable names
100 int locateVariable(int k); // Identify variable named on character stack
101 int stashReal(double);
102 CodeFragment codeIfElse(CodeFragment &, CodeFragment &, CodeFragment &);
103 CodeFragment codeWhile(CodeFragment &, CodeFragment &);
104 CodeFragment codeDoWhile(CodeFragment &, CodeFragment &);
105 CodeFragment codeFor(CodeFragment &, CodeFragment &, CodeFragment &, CodeFragment &);
106 }
107 wrapper {CodeFragment}
108 ]
109
110 (CodeFragment) input string $ // specify grammar token
111 -> statements:x, eof =x.cat(HLT);
112
113 (CodeFragment) statements
114 -> =CodeFragment();
115 -> statements:x, statement:y =x.cat(y);
116
117 (CodeFragment) statement
118 -> open statement
119 -> closed statement
120
121 // Any statement that could be followed by an else is an open statement
122 (CodeFragment) open statement
123 -> if clause:x, statement:s =x.cat(BRF, s.size()).cat(s);
124 -> if clause:x, closed statement:s1,
125 "else", open statement:s2 =PCB.codeIfElse(x,s1,s2);
126 -> while clause:x, open statement:s =PCB.codeWhile(x,s);
127 -> "for", '(', expression:init, ';', expression:cond, ';',
128 expression:inc, ')', open statement:s =PCB.codeFor(init, cond, inc, s);
129
130 // A statement that cannot be followed by "else" is a closed statement
131 (CodeFragment) closed statement
132 -> simple statement
133 -> if clause:x, closed statement:s1, "else",
134 closed statement:s2 =PCB.codeIfElse(x,s1,s2);
135 -> while clause:x, closed statement:s =PCB.codeWhile(x,s);
136 -> "do", statement:s, while clause:x, ';' =PCB.codeDoWhile(s,x);
137 -> "for", '(', expression:init, ';', expression:cond, ';',
138 expression:inc, ')', closed statement:s =PCB.codeFor(init, cond, inc, s);
139
140 (CodeFragment) if clause
141 -> "if", '(', expression:x, ')' =x;
142
143 (CodeFragment) while clause
144 -> "while", '(', expression:x, ')' =x;
145
146 (CodeFragment) simple statement
147 -> expression:x, ';' =x.cat(POP);
148 -> ';' =CodeFragment();
149 -> '{', statements:s, '}' =s;
150
151 (CodeFragment) expression
152 -> assignment expression
153 -> expression:x, ',', assignment expression:y =x.cat(POP).cat(y);
154
155 (CodeFragment) assignment expression
156 -> conditional expression
157 -> name:k, '=', assignment expression:x =x.cat(STORE, k);
158 -> name:k, "+=", assignment expression:x =x.cat(ADDM, k);
159 -> name:k, "-=", assignment expression:x =x.cat(SUBM, k);
160 -> name:k, "*=", assignment expression:x =x.cat(MULM,k);
161 -> name:k, "/=", assignment expression:x =x.cat(DIVM, k);
162
163 (CodeFragment) conditional expression
164 -> logical or expression
165 -> logical or expression:c, '?', expression:x,
166 ':', conditional expression:y =PCB.codeIfElse(c, x, y);
167
168 (CodeFragment) logical or expression
169 -> logical and expression
170 -> logical and expression:x, "||",
171 logical or expression:y =x.cat(OR, y.size()).cat(y);
172
173 (CodeFragment) logical and expression
174 -> equality expression
175 -> equality expression:x, "&&",
176 logical and expression:y =x.cat(AND, y.size()).cat(y);
177
178 (CodeFragment) equality expression
179 -> relational expression
180 -> equality expression:x, "==", relational expression:y =x.cat(y).cat(EQ);
181 -> equality expression:x, "!=", relational expression:y =x.cat(y).cat(NE);
182
183 (CodeFragment) relational expression
184 -> additive expression
185 -> relational expression:x, '<', additive expression:y =x.cat(y).cat(LT);
186 -> relational expression:x, "<=", additive expression:y =x.cat(y).cat(LE);
187 -> relational expression:x, '>', additive expression:y =x.cat(y).cat(GT);
188 -> relational expression:x, ">=", additive expression:y =x.cat(y).cat(GE);
189
190 (CodeFragment) additive expression
191 -> multiplicative expression
192 -> additive expression:x, '+', multiplicative expression:y =x.cat(y).cat(ADD);
193 -> additive expression:x, '-', multiplicative expression:y =x.cat(y).cat(SUB);
194
195 (CodeFragment) multiplicative expression
196 -> unary expression
197 -> multiplicative expression:x, '*', unary expression:y =x.cat(y).cat(MUL);
198 -> multiplicative expression:x, '/', unary expression:y =x.cat(y).cat(DIV);
199
200 (CodeFragment) unary expression
201 -> factor
202 -> '-', unary expression:x =x.cat(NEG);
203 -> '+', unary expression:x = x;
204
205 (CodeFragment) factor
206 -> primary
207 -> primary:x, "**", unary expression:y =x.cat(y).cat(POW);
208
209 (CodeFragment) primary
210 -> real:x =CodeFragment().cat(PUSHI, x);
211 -> name:k =CodeFragment().cat(PUSH, k);
212 -> "log", '(', assignment expression:x, ')' =x.cat(LOG);
213 -> "exp", '(', assignment expression:x, ')' =x.cat(EXP);
214 -> "sqrt", '(', assignment expression:x, ')' =x.cat(SQRT);
215 -> '(', expression:x, ')' =x;
216 -> '!', primary:x =x.cat(NOT);
217
218 // -- LEXICAL UNITS ------------------------------------------------
219 digit = '0-9'
220 eof = 0
221 letter = 'a-z' + 'A-Z' + '_'
222
223 (void) white space
224 -> ' ' + '\t' + '\f' + '\v' + '\r' + '\n'
225 -> "/*", ~eof?..., "*/" // C style comment
226 -> "//", ~(eof+'\n')?..., '\n' // C++ style comment
227
228 (int) real
229 -> simple real:x =PCB.stashReal(x);
230 -> simple real:x, 'e'+'E', '+'?,exponent:e =PCB.stashReal(x*pow(10,e));
231 -> simple real:x, 'e'+'E', '-',exponent:e =PCB.stashReal(x*pow(10,-e));
232
233 (double) simple real
234 -> integer part:i, '.', fraction part:f = i+f;
235 -> integer part, '.'?
236 -> '.', fraction part:f = f;
237
238 (double) integer part
239 -> digit:d = d-'0';
240 -> integer part:x, digit:d = 10*x + d-'0';
241
242 (double) fraction part
243 -> digit:d =(d-'0')/10.;
244 -> digit:d, fraction part:f =(d-'0' + f)/10.;
245
246 (int) exponent
247 -> digit:d = d-'0';
248 -> exponent:x, digit:d = 10*x + d-'0';
249
250 (int) name
251 -> name string =PCB.symbolDictionary->identify(PCB.charStack.popString());
252
253 name string
254 -> letter: c =PCB.charStack.push((char) c);
255 -> name string, letter+digit: c =PCB.charStack.push((char) c);
256
257 { // Begin embedded C
258
259 #define SYNTAX_ERROR
260
261 int bciParse_pcb_struct::stashReal(double x) {
262 int n = realList.size();
263 realList.push(x);
264 return n;
265 }
266
267 CodeFragment bciParse_pcb_struct::codeIfElse(CodeFragment &condition,
268 CodeFragment &trueStatement,
269 CodeFragment &falseStatement)
270 {
271 return condition.cat(BRF, trueStatement.size() + 2)
272 .cat(trueStatement)
273 .cat(BR, falseStatement.size())
274 .cat(falseStatement);
275 }
276
277 CodeFragment bciParse_pcb_struct::codeWhile(CodeFragment &condition,
278 CodeFragment &statement)
279 {
280 // loop back distance is length of statement + length of condition + 2 branch instructions
281 int loopBackDistance = condition.size() + statement.size() + 4;
282 return condition.cat(BRF, statement.size() + 2) // size of statement +size of loopback
283 .cat(statement)
284 .cat(BR, -loopBackDistance);
285 }
286
287 CodeFragment bciParse_pcb_struct::codeDoWhile(CodeFragment &statement,
288 CodeFragment &condition)
289 {
290 // loop back distance is
291 // length of statement + length of condition + 1 branch instruction
292 int loopBackDistance = statement.size() + condition.size() + 2;
293 return statement.cat(condition)
294 .cat(BRT, -loopBackDistance);
295 }
296
297 CodeFragment bciParse_pcb_struct::codeFor(CodeFragment &initializer,
298 CodeFragment &condition,
299 CodeFragment &increment,
300 CodeFragment &statement)
301 {
302 // Calculate the length of the jump back at the bottom of the loop
303 // It consists of the length of the increment, condition and statement
304 // CodeFragments + 5 inserted Bytecodes: 1 Pop, and 2 each for each of
305 // two branches
306 int loopBackDistance = increment.size() + condition.size() + statement.size() + 5;
307
308 // Put it all together
309 return initializer.cat(POP) // clear expression value from stack
310 .cat(BR, increment.size() + 1) // Skip increment on first time through
311 .cat(increment).cat(POP) // clear expresson value from stack
312 .cat(condition)
313 .cat(BRF, statement.size() + 2) // exit when condition is false
314 .cat(statement)
315 .cat(BR, -loopBackDistance);
316 }
317
318 int bciParse_pcb_struct::compile(AgStringDictionary *s, AgString text) {
319 symbolDictionary = s;
320 charStack.reset();
321 pointer = (unsigned char *) text.ptr();
322 bciParse(this);
323 if(exit_flag != AG_SUCCESS_CODE) return 1;
324 code = bciParse_value(this);
325 return 0;
326 }
327
328 } // End of embedded C
329 /********************* End of bcip.syn ************************/
330