Mercurial > ~dholland > hg > ag > index.cgi
comparison tests/agcl/oldagsrc/xvmc.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 XVMC.SYN | |
4 | |
5 Extensible Scripting Language | |
6 Copyright (c) 1998 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 supported operations are: | |
12 Assignment operators: =, +=, -=, *=, /=, %=, , &=, |=, ^=>>=, <<= | |
13 Conditional expressions: ? : | |
14 Logical operators: !, &&, || | |
15 Bitwise logical operators: &, |, ^, ~ | |
16 Comparison operators: ==, !=, <, <=, >, >= | |
17 Shift operators: <<, >> | |
18 Binary arithmetic operators: +, -, *, /, % | |
19 Unary arithmetic operators: +, - | |
20 Exponentiation: ** | |
21 Autoincrement operators: ++, --; | |
22 Cast operators (<type name>) | |
23 Parentheses | |
24 Function calls | |
25 Object method calls | |
26 | |
27 Built in data types are int, double and String. | |
28 | |
29 Statements may include variable declarations, expression statements, | |
30 blocks, if/else statements, while , do/while, or for statements, | |
31 following the rules of C. | |
32 | |
33 The statement syntax has been written to avoid the conventional | |
34 if/else ambiguity. | |
35 | |
36 Input strings may contain any number of statements. White space may be | |
37 used freely, including both C and C++ style comments. | |
38 | |
39 xvmc.syn is compiled with the AnaGram parser generator | |
40 yielding xvm.h and xvm.cpp. | |
41 | |
42 For information about AnaGram, visit http://www.parsifalsoft.com. | |
43 */ | |
44 | |
45 #include <math.h> | |
46 #include "xvm.h" // defines external interface | |
47 #include "integer.h" | |
48 #include "double.h" | |
49 #include "xstring.h" | |
50 | |
51 static VirtualMachine *vm; | |
52 | |
53 typedef VirtualMachine::CodeSeg Code; // For the sake of readability | |
54 | |
55 } | |
56 // -- CONFIGURATION SECTION ---------------------------- | |
57 [ | |
58 default token type = Code | |
59 disregard white space | |
60 lexeme {real, name string, string literal, character constant} | |
61 distinguish lexemes | |
62 distinguish keywords {'a-z' + 'A-Z' + '0-9' + '_'} | |
63 pointer input | |
64 parser name = vmCompile | |
65 parser file name = "#.cpp" | |
66 line numbers | |
67 ~allow macros | |
68 escape backslashes // for Visual C++ | |
69 ] | |
70 | |
71 input string $ // specify grammar token | |
72 -> eof =Code(); | |
73 -> statements:x, eof =x; | |
74 -> statements:x, error, ~(eof + ';' + '}' + space)?..., eof =x; | |
75 | |
76 statement | |
77 -> executable statement | |
78 -> declaration, ';' | |
79 -> error, ~(eof + ';' + '}' + space)?..., ';' =errorLog.add("Continuing scan"), Code(); | |
80 | |
81 declaration | |
82 -> type name:t, name string:n =vm->declareVariable(t,n), Code(); | |
83 -> type name:t, name string:n, '=', expression:x ={ | |
84 int name = vm->declareVariable(t,n); | |
85 return Code(VirtualMachine::PUSHV) << name << x << VirtualMachine::ASSIGN << VirtualMachine::POP; | |
86 } | |
87 -> type name:t, name string:n, '[', expression:size, ']' =vm->declareArray(t,n, size); | |
88 -> type name:t, name string:n, '(', expression list:args, ')' =vm->declareObject(t,n,args); | |
89 | |
90 expression list | |
91 -> =Code(); | |
92 -> expressions:x =x; | |
93 | |
94 expressions | |
95 -> expression:x =x.initList(); | |
96 -> expressions:list, ',', expression:x =list.append(x); | |
97 | |
98 | |
99 executable statement | |
100 -> unconditional statement | |
101 -> conditional statement | |
102 | |
103 statements | |
104 -> statement:x =x; | |
105 -> statements:x, statement:s =x << s; | |
106 | |
107 | |
108 /* | |
109 An unconditional statement is any statement that does not involve | |
110 an if statement | |
111 */ | |
112 | |
113 unconditional statement | |
114 -> expression:x, ';' =x << VirtualMachine::POP; | |
115 -> ';' =Code(); | |
116 -> '{', '}' =Code(); | |
117 -> '{', statements:s, '}' =s; | |
118 -> '{', statements:s, error, ~(eof + ';' + '}' + space)?..., '}' =errorLog.add("Continuing scan"), s; | |
119 -> "do", executable statement:s, while clause:x, ';' =vm->codeDoWhile(s,x); | |
120 -> while clause:x, unconditional statement:s =vm->codeWhile(x,s); | |
121 -> "for", '(', for exprs:init, ';', condition:cond, ';', for exprs:inc, | |
122 ')', unconditional statement:s =vm->codeFor(init, cond, inc, s); | |
123 | |
124 for exprs | |
125 -> =Code(); | |
126 -> for expr list | |
127 | |
128 for expr list | |
129 -> expression:x =x << VirtualMachine::POP; | |
130 -> for expr list:list, ',', expression:x =list << x << VirtualMachine::POP; | |
131 | |
132 while clause | |
133 -> "while", '(', condition:x, ')' =x; | |
134 | |
135 | |
136 /* | |
137 Any statement with an if in it is a conditional statement | |
138 */ | |
139 | |
140 conditional statement | |
141 -> while clause:x, conditional statement:s =vm->codeWhile(x,s); | |
142 -> "for", '(', for exprs:init, ';', condition:cond, ';', for exprs:inc, | |
143 ')', conditional statement:s =vm->codeFor(init, cond, inc, s); | |
144 -> if clause:x, executable statement:s =x << VirtualMachine::BRF << s.size() << s; | |
145 -> if clause:x, unconditional statement:s1, | |
146 "else", statement:s2 ={ | |
147 s1 << VirtualMachine::BR << s2.size(); | |
148 x << VirtualMachine::BRF << s1.size() << s1 << s2; | |
149 return x; | |
150 } | |
151 | |
152 if clause | |
153 -> "if", '(', condition:x, ')' =x; | |
154 | |
155 condition | |
156 -> expression:x =x.testOK(); | |
157 | |
158 expression | |
159 -> conditional expression | |
160 -> lvalue:k, '=', expression:x =k << x << VirtualMachine::ASSIGN; | |
161 -> lvalue:k, "+=", expression:x =k << x << VirtualMachine::ADD_EQ; | |
162 -> lvalue:k, "-=", expression:x =k << x << VirtualMachine::SUB_EQ; | |
163 -> lvalue:k, "*=", expression:x =k << x << VirtualMachine::MULT_EQ; | |
164 -> lvalue:k, "/=", expression:x =k << x << VirtualMachine::DIV_EQ; | |
165 -> lvalue:k, "%=", expression:x =k << x << VirtualMachine::MOD_EQ; | |
166 -> lvalue:k, "|=", expression:x =k << x << VirtualMachine::OR_EQ; | |
167 -> lvalue:k, "&=", expression:x =k << x << VirtualMachine::AND_EQ; | |
168 -> lvalue:k, "^=", expression:x =k << x << VirtualMachine::XOR_EQ; | |
169 -> lvalue:k, "<<=", expression:x =k << x << VirtualMachine::LS_EQ; | |
170 -> lvalue:k, ">>=", expression:x =k << x << VirtualMachine::RS_EQ; | |
171 | |
172 lvalue | |
173 -> variable name:k =Code(VirtualMachine::PUSHV).setType(vm->symbolTable[k].type) << k; | |
174 -> lvalue:k, '[', expression:x, ']' =k.setType(k.type->element) << x << VirtualMachine::SUBSCRIPT; | |
175 | |
176 conditional expression | |
177 -> logical or expression | |
178 -> logical or condition:c, '?', | |
179 expression:x, ':', conditional expression:y ={ | |
180 //if (!c.type->isTruthDefined()) errorLog.add("True/False not defined"); | |
181 x << VirtualMachine::BR << y.size(); | |
182 c << VirtualMachine::BRF << x.size() << x << y; | |
183 return c; | |
184 } | |
185 | |
186 logical or condition | |
187 -> logical or expression:x =x.testOK(); | |
188 | |
189 logical or expression | |
190 -> logical and expression | |
191 -> logical or condition:x, "||",logical and expression:y ={ | |
192 //if (!x.type->isTruthDefined()) errorLog.add("True/False not defined"); | |
193 return x << VirtualMachine::OR << y.size() << y; | |
194 } | |
195 | |
196 logical and expression | |
197 -> bitwise or expression | |
198 -> logical and condition:x, "&&", bitwise or expression:y ={ | |
199 //if (!x.type->isTruthDefined()) errorLog.add("True/False not defined"); | |
200 return x << VirtualMachine::AND << y.size() << y; | |
201 } | |
202 | |
203 logical and condition | |
204 -> logical and expression:x =x.testOK(); | |
205 | |
206 | |
207 | |
208 bitwise or expression | |
209 -> bitwise xor expression | |
210 -> bitwise or expression:x, '|', | |
211 bitwise xor expression:y =x.binop(VirtualMachine::BITOR,y); | |
212 | |
213 bitwise xor expression | |
214 -> bitwise and expression | |
215 -> bitwise xor expression:x, '^', | |
216 bitwise and expression:y =x.binop(VirtualMachine::XOR,y); | |
217 | |
218 bitwise and expression | |
219 -> equality expression | |
220 -> bitwise and expression:x, '&', | |
221 equality expression:y =x.binop(VirtualMachine::BITAND,y); | |
222 | |
223 equality expression | |
224 -> relational expression | |
225 -> equality expression:x, "==", relational expression:y =x.binop(VirtualMachine::EQ,y); | |
226 -> equality expression:x, "!=", relational expression:y =x.binop(VirtualMachine::NE,y); | |
227 | |
228 relational expression | |
229 -> shift expression | |
230 -> relational expression:x, '<', shift expression:y =x.binop(VirtualMachine::LT,y); | |
231 -> relational expression:x, "<=", shift expression:y =x.binop(VirtualMachine::LE,y); | |
232 -> relational expression:x, '>', shift expression:y =x.binop(VirtualMachine::GT,y); | |
233 -> relational expression:x, ">=", shift expression:y =x.binop(VirtualMachine::GE,y); | |
234 | |
235 shift expression | |
236 -> additive expression | |
237 -> shift expression:x, "<<", additive expression:y =x.binop(VirtualMachine::LS,y); | |
238 -> shift expression:x, ">>", additive expression:y =x.binop(VirtualMachine::RS,y); | |
239 | |
240 additive expression | |
241 -> multiplicative expression | |
242 -> additive expression:x, '+', | |
243 multiplicative expression:y =x.binop(VirtualMachine::ADD,y); | |
244 -> additive expression:x, '-', | |
245 multiplicative expression:y =x.binop(VirtualMachine::SUB,y); | |
246 | |
247 multiplicative expression | |
248 -> cast expression | |
249 -> multiplicative expression:x, '*', cast expression:y =x.binop(VirtualMachine::MULT,y); | |
250 -> multiplicative expression:x, '/', cast expression:y =x.binop(VirtualMachine::DIV,y); | |
251 -> multiplicative expression:x, '%', cast expression:y =x.binop(VirtualMachine::MOD,y); | |
252 | |
253 cast expression | |
254 -> unary expression | |
255 -> '(', type name:t, ')', cast expression:x =x.cast((VirtualMachine::Type::Id) t) << VirtualMachine::CAST << t; | |
256 | |
257 unary expression | |
258 -> power expression | |
259 -> "++", unary expression:x =x << VirtualMachine::INCR; | |
260 -> "--", unary expression:x =x << VirtualMachine::INCR; | |
261 -> '-', unary expression:x =x << VirtualMachine::NEG; | |
262 -> '+', unary expression:x =x; | |
263 -> '!', unary expression:x =vm->list(stdout), x << VirtualMachine::NOT; | |
264 -> '~', unary expression:x =x << VirtualMachine::COMPL; | |
265 | |
266 | |
267 | |
268 power expression | |
269 -> primary | |
270 -> primary:x, "**", unary expression:y =x.binop(VirtualMachine::POW,y); | |
271 | |
272 primary | |
273 -> real:x =vm->doubleList.push(x), Code(VirtualMachine::PUSHD).setType(&DoubleType::doubleType) << (int)(vm->doubleList.size() - 1); | |
274 -> integer constant:x =Code(VirtualMachine::PUSHI).setType(&IntegerType::intType) << x; | |
275 -> string literal:k =Code(VirtualMachine::PUSHS).setType(&StringType::stringType) << k; | |
276 -> lvalue:k =k; | |
277 -> lvalue:k, "++" =k << VirtualMachine::PUSH << VirtualMachine::INCR << VirtualMachine::POP; | |
278 -> lvalue:k, "--" =k << VirtualMachine::PUSH << VirtualMachine::DECR << VirtualMachine::POP; | |
279 -> name string:n, '(', expression list:args, ')' =vm->invokeFunction(n, args); | |
280 -> lvalue:k, '.', name string:n, '(', expression list: args, ')' =vm->invokeMethod(k, n, args); | |
281 -> '(', expression:x, ')' =x; | |
282 | |
283 // -- LEXICAL UNITS ------------------------------------------------ | |
284 digit = '0-9' | |
285 eof = 0 | |
286 letter = 'a-z' + 'A-Z' + '_' | |
287 space = ' ' + '\t' + '\f' + '\v' + '\r' + '\n' | |
288 | |
289 | |
290 (void) white space | |
291 -> space | |
292 -> "/*", ~eof?..., "*/" // C style comment | |
293 -> "//", ~(eof+'\n')?..., '\n' // C++ style comment | |
294 | |
295 (double) real | |
296 -> simple real | |
297 -> simple real:x, 'e'+'E', '+'?,exponent:e =x*pow(10,e); | |
298 -> simple real:x, 'e'+'E', '-',exponent:e =x*pow(10,-e); | |
299 | |
300 (double) simple real | |
301 -> integer:i, '.', fraction part:f = i+f; | |
302 -> integer:i, '.' =i; | |
303 -> '.', fraction part:f = f; | |
304 | |
305 (int) integer constant | |
306 -> integer | |
307 -> character constant | |
308 | |
309 (int) integer | |
310 -> digit:d = d-'0'; | |
311 -> integer:x, digit:d = 10*x + d-'0'; | |
312 | |
313 (double) fraction part | |
314 -> digit:d =(d-'0')/10.; | |
315 -> digit:d, fraction part:f =(d-'0' + f)/10.; | |
316 | |
317 (int) exponent | |
318 -> digit:d = d-'0'; | |
319 -> exponent:x, digit:d = 10*x + d-'0'; | |
320 | |
321 (int) type name, variable name | |
322 -> name string:k ={ | |
323 char *name = popString(k); | |
324 VirtualMachine::Type::Id id = VirtualMachine::Type::idType(name); | |
325 if (id != VirtualMachine::Type::UNDEFINED) return (int) id; | |
326 CHANGE_REDUCTION(variable_name); | |
327 return vm->locateVariable(name); | |
328 } | |
329 | |
330 (int) name string | |
331 -> letter: c =pushChar(c), 1; | |
332 -> name string:k, letter+digit: c =pushChar(c), k+1; | |
333 | |
334 not double quote = ~eof - ('"' + '\\' + '\n') | |
335 not single quote = ~eof - ('\'' + '\\' + '\n') | |
336 | |
337 (int) character constant | |
338 -> '\'', char constant element:c, '\'' =c; | |
339 | |
340 (int) char constant element | |
341 -> not single quote | |
342 -> escape sequence | |
343 | |
344 (int) string literal | |
345 -> string chars:k, '"' =vm->stringList.push(CharString(popString(k))), vm->stringList.size() - 1; | |
346 | |
347 (int) string chars | |
348 -> '"' =0; | |
349 -> string chars:k, string char:c =pushChar(c), k+1; | |
350 | |
351 (int) string char | |
352 -> not double quote | |
353 -> escape sequence | |
354 | |
355 (int) escape sequence | |
356 -> "\\a" ='\a'; | |
357 -> "\\b" ='\b'; | |
358 -> "\\f" ='\f'; | |
359 -> "\\n" ='\n'; | |
360 -> "\\r" ='\r'; | |
361 -> "\\t" ='\t'; | |
362 -> "\\v" ='\v'; | |
363 -> "\\\\" ='\\'; | |
364 -> "\\?" = '\?'; | |
365 -> "\\'" ='\''; | |
366 -> "\\\"" ='"'; | |
367 -> octal escape | |
368 -> hex escape | |
369 | |
370 (int) octal escape | |
371 -> one octal | two octal | three octal | |
372 | |
373 (int) one octal | |
374 -> '\\', '0-7':d =d-'0'; | |
375 | |
376 (int) two octal | |
377 -> one octal:n, '0-7':d =8*n + d-'0'; | |
378 | |
379 (int) three octal | |
380 -> two octal:n, '0-7':d =8*n + d-'0'; | |
381 | |
382 (int) hex escape | |
383 -> "\\x", hex digit:d =d; | |
384 -> hex escape:n, hex digit:d =16*n + d; | |
385 | |
386 (int) hex digit | |
387 -> '0-9' | |
388 -> 'a-f' + 'A-F':d =(d&7) + 9; | |
389 | |
390 [ | |
391 sticky {one octal, two octal, hex escape} | |
392 ] | |
393 | |
394 | |
395 | |
396 { // begin embedded C | |
397 | |
398 #include <string.h> | |
399 | |
400 | |
401 ErrorRecord::ErrorRecord(char *msg) : message(msg), line(PCB.line), column(PCB.column) | |
402 {/* Initializers do it all */} | |
403 | |
404 ErrorLog errorLog; | |
405 | |
406 #define SYNTAX_ERROR errorLog.add(PCB.error_message) | |
407 | |
408 int VirtualMachine::compile(char *text) { | |
409 vm = this; | |
410 resetCharStack(); | |
411 vmCompile_pcb.pointer = (unsigned char *) text; | |
412 vmCompile(); | |
413 { | |
414 Code program = vmCompile_value() << EXIT; | |
415 int n = program.size(); | |
416 codeStore = new int[n]; | |
417 while (n--) codeStore[n] = program[n]; | |
418 } | |
419 | |
420 return vmCompile_pcb.exit_flag != AG_SUCCESS_CODE; | |
421 } | |
422 | |
423 Code VirtualMachine::codeWhile(Code x, Code s) { | |
424 Code branch(VirtualMachine::BR); | |
425 branch << 0; | |
426 //if (!x.type->isTruthDefined()) errorLog.add("True/False not defined"); | |
427 x << VirtualMachine::BRF << (s.size() + branch.size()); | |
428 int blockLength = s.size() + x.size() + branch.size(); | |
429 x << s << VirtualMachine::BR << -blockLength; | |
430 return x; | |
431 } | |
432 | |
433 Code VirtualMachine::codeDoWhile(Code s, Code x) { | |
434 Code branch(VirtualMachine::BR); | |
435 branch << 0; | |
436 int blockLength = s.size() + x.size() + branch.size(); | |
437 //if (!x.type->isTruthDefined()) errorLog.add("True/False not defined"); | |
438 s << x << VirtualMachine::BRT << -blockLength; | |
439 return s; | |
440 } | |
441 | |
442 Code VirtualMachine::codeFor(Code init, Code cond, Code inc, Code s) { | |
443 s << inc; // append increment code to end of body of for loop | |
444 //if (!cond.type->isTruthDefined()) errorLog.add("True/False not defined"); | |
445 init << codeWhile(cond, s); | |
446 return init; | |
447 } | |
448 | |
449 } // end of embedded C | |
450 /********************* End of VM.SYN ************************/ |