comparison tests/agcl/contrib/yabasic.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 /*
4 YABASIC --- a tiny integrated Basic Compiler/Interpreter
5
6 BISON - part
7
8 this Program is subject to the GNU General Public License;
9 see the file yabasic.c for details.
10 */
11
12
13 //#undef WINDOWS
14 #include "yabasic.h" /* definitions of yabasic */
15 #include <malloc.h>
16
17 #if HAVE_ALLOCA_H
18 #include <alloca.h>
19 #endif
20
21 void __yy_bcopy(char *,char *,int); /* prototype missing */
22
23 int yylineno=1;
24 int yylex(void);
25
26 char *popString(int);
27 void pushChar(int);
28
29 }
30
31 [
32 ~case sensitive
33 disregard white space
34 lexeme {digit string, name, STRING, STRSYM, number}
35 distinguish lexemes
36 parser name = parseBasic
37 line numbers
38 escape backslashes
39 ]
40
41 white space = ' ' + '\t'
42
43 //(double *) step_part
44
45
46 SEP
47 -> ["REM", ~(eof + white space + '\n')?...], '\n' ={
48 yylineno++;
49 if (interactive) PCB.exit_flag = AG_SUCCESS_CODE;
50 return;
51 }
52
53 (double) number
54 -> simple real
55 -> simple real:x, 'e'+'E', '+'?,exponent:e =x*pow(10,e);
56 -> simple real:x, 'e'+'E', '-',exponent:e =x*pow(10,-e);
57
58 (double) simple real
59 -> integer part:i, '.', fraction part:f = i+f;
60 -> integer part, '.'?
61 -> '.', fraction part:f = f;
62
63 (double) integer part
64 -> digit:d = d-'0';
65 -> integer part:x, digit:d = 10*x + d-'0';
66
67 (double) fraction part
68 -> digit:d =(d-'0')/10.;
69 -> digit:d, fraction part:f =(d-'0' + f)/10.;
70
71 (int) exponent
72 -> digit:d = d-'0';
73 -> exponent:x, digit:d = 10*x + d-'0';
74
75 (int) name //value of name token is length of name string
76 -> letter: c =pushChar(c), 1;
77 -> name:k, letter+digit: c =pushChar(c), k+1;
78
79
80 (char *) SYMBOL
81 -> name:k =strdup(popString(k));
82
83 (char *) STRSYM
84 -> name:k, '$' =pushChar('$'), strdup(popString(k+1));
85
86 (char *) DIGITS
87 -> digit string:k =strdup(popString(k));
88
89 (int) digit string
90 -> digit:d =pushChar(d), 1;
91 -> digit string:k, digit:d =pushChar(d), k+1;
92
93 (char *) STRING
94 -> '"', string text:k, '"' =strdup(popString(k));
95 -> '"', string text:k, '\n' =strdup(popString(k));
96
97 (int) string text
98 -> =0;
99 -> string text:k, ~(eof + '"' + '\n'):c =pushChar(c), k+1;
100 -> string text:k, "\\\"" =pushChar('"'), k+1;
101
102 /*
103 [
104 left {"OR"}
105 left {"AND"}
106 left {"NOT"}
107 left {'-', '+'}
108 left {'*', '/'}
109 left {'^'}
110 nonassoc {UMINUS}
111 ]
112 */
113
114 letter = 'a-z' + 'A-Z'
115 digit = '0-9'
116 eof = 0 + -1
117
118
119 program $
120 -> statement list, eof =end_of_file = TRUE;
121
122 statement list
123 ->
124 /*
125 -> statement_list, !{
126 if (errorlevel<=ERROR) {YYABORT;}},
127 SEP, !{
128 yylineno+=$3;},
129 statement
130 */
131 -> statement list, SEP, statement
132 -> statement list, SEP, label, statement
133
134 label
135 -> "LABEL", SYMBOL:s =create_label(s);
136 -> DIGITS:s =create_label(s);
137
138
139 statement /* empty */
140 ->
141 -> string_assignment
142 -> assignment
143 -> for_loop
144 -> if_clause
145 -> "GOTO", symbol_or_lineno:s ={create_goto(s);}
146 -> "GOSUB", symbol_or_lineno:s ={create_gosub(s);}
147 -> "ON", "INTERRUPT", "BREAK" ={create_exception(TRUE);}
148 -> "ON", "INTERRUPT", "CONTINUE" ={create_exception(FALSE);}
149 -> "ON", expression, "GOTO", !{create_skipper();}, goto_list ={create_nop();}
150 -> "ON", expression, "GOSUB", !{create_skipper();}, gosub_list ={create_nop();}
151 // -> LABEL, symbol_or_lineno ={create_label($2);}
152 -> "OPEN", hashed_number:n, ',', string expression, ',', string expression ={create_myopen(n,'+');}
153 -> "OPEN", hashed_number:n, ',', string expression ={create_myopen(n,'-');}
154 -> "CLOSE", hashed_number:n ={create_myclose(n);}
155 -> "PRINT", printintro, printlist, !{
156 create_revert(FALSE);},
157 semicolon
158 -> "INPUT", inputintro, inputlist =lastinput->args=0;
159 -> "READ", readlist
160 -> "DATA", datalist
161 -> "RESTORE" =create_restore("");
162 -> "RESTORE", symbol_or_lineno:s =create_restore(s);
163 -> "RETURN" ={create_return();}
164 -> "DIM", dimlist
165 -> "OPEN", "WINDOW", expression, ',', expression =create_openwin(FALSE);
166 -> "OPEN", "WINDOW", expression, ',', expression, ',', string expression ={create_openwin(TRUE);}
167 -> "DOT", mapping =create_dot();
168 -> "LINE", mapping, "TO", mapping =create_line('l');
169 -> "CIRCLE", mapping, ',', expression =create_circle();
170 -> "TEXT", string expression, ',', mapping =create_text(TRUE);
171 -> "TEXT", mapping, ',', string expression =create_text(FALSE);
172 -> "MAP", expression, ',', expression, ',', expression, ',', expression, "TO", expression, ',', expression, ',', expression, ',', expression =create_makemap();
173 -> "ARROW", mapping, "TO", mapping =create_line('a');
174 -> "XTICK", mapping, ',', string expression =create_tick(1);
175 -> "YTICK", mapping, ',', string expression =create_tick(3);
176 -> "XTICK", mapping =create_tick(0);
177 -> "YTICK", mapping =create_tick(2);
178 -> "CLOSE", "WINDOW" =create_closewin();
179 -> "CLEAR", "WINDOW" =create_clearwin();
180 -> "CLEAR", "SCREEN" =create_clearscreen();
181 -> "OPEN", "PRINTER" =create_openprinter(0);
182 -> "OPEN", "PRINTER", string expression =create_openprinter(1);
183 -> "CLOSE", "PRINTER" =create_closeprinter();
184 -> "WAIT", expression =create_mywait();
185 -> "BELL" =create_bell();
186 -> "INKEY" ={create_function(MYINKEY); create_popstrsym(NULL);}
187 -> "SYSTEM2", '(', string expression, ')' ={create_function(MYSYSTEM2);
188 create_popdblsym(NULL);}
189 -> "POKE", string expression, ',', string expression ={create_poke('s');}
190 -> "POKE", string expression, ',', expression ={create_poke('d');}
191 -> "END" ={create_myend();}
192
193 string_assignment
194 -> STRSYM:s, '=', string expression ={create_popstrsym(s);}
195 -> "MID", '(', STRSYM:s, !{
196 create_pushstrptr(s);},
197 ',', expression, ',', expression, ')', '=', string expression ={create_changestring(MYMID);}
198 -> "LEFT", '(', STRSYM:s, !{
199 create_pushstrptr(s);},
200 ',', expression, ')', '=', string expression ={create_changestring(MYLEFT);}
201 -> "RIGHT", '(', STRSYM:s, !{
202 create_pushstrptr(s);},
203 ',', expression, ')', '=', string expression ={create_changestring(MYRIGHT);}
204 -> STRSYM:s, '(', !{
205 pushcounter();},
206 indexlist, ')', '=', string expression ={create_doarray(s,ASSIGNSTRINGARRAY);}
207 -> "MID", '(', STRSYM:s, '(', !{
208 pushcounter();},
209 indexlist, ')', !{
210 create_doarray(s,GETSTRINGPOINTER);},
211 ',', expression, ',', expression, ')', '=', string expression ={create_changestring(MYMID);}
212 -> "LEFT", '(', STRSYM:s, '(', !{
213 pushcounter();},
214 indexlist, ')', !{
215 create_doarray(s,GETSTRINGPOINTER);},
216 ',', expression, ')', '=', string expression ={create_changestring(MYLEFT);}
217 -> "RIGHT", '(', STRSYM:s, '(', !{
218 pushcounter();},
219 indexlist, ')', !{
220 create_doarray(s,GETSTRINGPOINTER);},
221 ',', expression, ')', '=', string expression ={create_changestring(MYRIGHT);}
222
223 string expression
224 -> primary string expression
225 -> string expression, '+', primary string expression ={create_concat();}
226
227 primary string expression
228 -> STRSYM:s ={create_pushstrsym(s);}
229 -> string_function
230 -> STRING:s ={if (s==NULL) {error(ERROR,"String not terminated");create_pushstr("");} else {create_pushstr(s);}}
231 -> STRSYM:s, '(', !{
232 pushcounter();},
233 indexlist, ')' ={create_doarray(s,CALLSTRINGARRAY);}
234 -> '(', string expression, ')'
235
236 string_function
237 -> "LEFT", '(', string expression, ',', expression, ')' ={create_function(MYLEFT);}
238 -> "RIGHT", '(', string expression, ',', expression, ')' ={create_function(MYRIGHT);}
239 -> "MID", '(', string expression, ',', expression, ',', expression, ')' ={create_function(MYMID);}
240 -> "STR", '(', expression, ')' ={create_function(MYSTR);}
241 -> "STR", '(', expression, ',', string expression, ')' ={create_function(MYSTR2);}
242 -> "INKEY" ={create_function(MYINKEY);}
243 -> "CHR", '(', expression, ')' ={create_function(MYCHR);}
244 -> "UPPER", '(', string expression, ')' ={create_function(MYUPPER);}
245 -> "LOWER", '(', string expression, ')' ={create_function(MYLOWER);}
246 -> "LTRIM", '(', string expression, ')' ={create_function(MYLTRIM);}
247 -> "RTRIM", '(', string expression, ')' ={create_function(MYRTRIM);}
248 -> "TRIM", '(', string expression, ')' ={create_function(MYTRIM);}
249 -> "SYSTEM", '(', string expression, ')' ={create_function(MYSYSTEM);}
250 -> "DATE" ={create_function(MYDATE);}
251 -> "TIME" ={create_function(MYTIME);}
252 -> "PEEK2", '(', string expression, ')' ={create_function(MYPEEK2);}
253
254 assignment
255 -> SYMBOL:s, '=', expression ={create_popdblsym(s);}
256 -> SYMBOL:s, '(', !{
257 pushcounter();},
258 indexlist, ')', '=', expression ={create_doarray(s,ASSIGNARRAY);}
259
260 primary expression
261 -> number:n =create_pushdbl(n);
262 -> function
263 -> SYMBOL:s =create_pushdblsym(s);
264 -> SYMBOL:s, '(', !pushcounter();,
265 indexlist, ')' ={create_doarray(s,CALLARRAY);}
266 -> '(', expression, ')'
267 -> '-', primary expression /* 1ef4:fa2arec <֠ */ ={create_negate();}
268
269 exponential expression
270 -> primary expression
271 -> exponential expression, '^', primary expression ={create_dblbin('^');}
272
273 multiplicative expression
274 -> exponential expression
275 -> multiplicative expression, '*', exponential expression ={create_dblbin('*');}
276 -> multiplicative expression, '/', exponential expression ={create_dblbin('/');}
277
278 expression
279 -> multiplicative expression
280 -> expression, '+', multiplicative expression ={create_dblbin('+');}
281 -> expression, '-', multiplicative expression ={create_dblbin('-');}
282
283 /*
284 -> expression, '+', expression ={create_dblbin('+');}
285 -> expression, '-', expression ={create_dblbin('-');}
286 -> expression, '*', expression ={create_dblbin('*');}
287 -> expression, '/', expression ={create_dblbin('/');}
288 -> expression, '^', expression ={create_dblbin('^');}
289 -> '-', expression /* 1ef4:fa2arec <֠ * / ={create_negate();}
290 */
291
292 mapping
293 -> expression, ',', expression
294 -> "MAP", '(', expression, ',', expression, ')' ={create_map();}
295
296 function
297 -> "SIN", '(', expression, ')' ={create_function(MYSIN);}
298 -> "ASIN", '(', expression, ')' ={create_function(MYASIN);}
299 -> "COS", '(', expression, ')' ={create_function(MYCOS);}
300 -> "ACOS", '(', expression, ')' ={create_function(MYACOS);}
301 -> "TAN", '(', expression, ')' ={create_function(MYTAN);}
302 -> "ATAN", '(', expression, ')' ={create_function(MYATAN);}
303 -> "ATAN", '(', expression, ',', expression, ')' ={create_function(MYATAN2);}
304 -> "EXP", '(', expression, ')' ={create_function(MYEXP);}
305 -> "LOG", '(', expression, ')' ={create_function(MYLOG);}
306 -> "SQRT", '(', expression, ')' ={create_function(MYSQRT);}
307 -> "INT", '(', expression, ')' ={create_function(MYINT);}
308 -> "FRAC", '(', expression, ')' ={create_function(MYFRAC);}
309 -> "MOD", '(', expression, ',', expression, ')' ={create_function(MYMOD);}
310 -> "RAN", '(', expression, ')' ={create_function(MYRAN);}
311 -> "RAN", '(', ')' ={create_function(MYRAN2);}
312 -> "MIN", '(', expression, ',', expression, ')' ={create_function(MYMIN);}
313 -> "MAX", '(', expression, ',', expression, ')' ={create_function(MYMAX);}
314 -> "XMAP", '(', expression, ')' ={create_function(MYXMAP);}
315 -> "YMAP", '(', expression, ')' ={create_function(MYYMAP);}
316 -> "LEN", '(', string expression, ')' ={create_function(MYLEN);}
317 -> "VAL", '(', string expression, ')' ={create_function(MYVAL);}
318 -> "ASC", '(', string expression, ')' ={create_function(MYASC);}
319 -> "INSTR", '(', string expression, ',', string expression, ')' ={create_function(MYINSTR);}
320 -> "SYSTEM2", '(', string expression, ')' ={create_function(MYSYSTEM2);}
321 -> "PEEK", '(', string expression, ')' ={create_function(MYPEEK);}
322
323 (double) const
324 -> number:n =n;
325 -> '+', number:n =n;
326 -> '-', number:n =-n;
327
328 /*
329 number
330 -> FNUM ={$$=$1;}
331 -> DIGITS ={$$=atoi($1);}
332 */
333
334 (int) intnum
335 -> DIGITS:d =atoi(d);
336
337 (char *) symbol_or_lineno
338 -> DIGITS:s =s;
339 -> SYMBOL:s =s;
340
341 dimlist
342 -> SYMBOL:s, '(', !{
343 pushcounter();},
344 indexlist, ')' ={create_dim(s,'d');}
345 -> dimlist, ',', SYMBOL:s, '(', !{
346 pushcounter();},
347 indexlist, ')' ={create_dim(s,'d');}
348 -> STRSYM:s, '(', !{
349 pushcounter();},
350 indexlist, ')' ={create_dim(s,'s');}
351 -> dimlist, ',', STRSYM:s, '(', !{
352 pushcounter();},
353 indexlist, ')' ={create_dim(s,'s');}
354
355 indexlist
356 -> expression ={inccounter();}
357 -> indexlist, ',', expression ={inccounter();}
358
359 for_loop
360 -> "FOR", SYMBOL:s, '=', expression, !{
361 pushname(s);create_popdblsym(s);pushgoto();
362 create_pushdblsym(s);},
363 "TO", expression, step_part:p, !{
364
365 create_dblrelop((p>0)?'{':'}');
366 create_decide();
367 pushlabel();},
368 /*
369 SEP, !{
370 yylineno+=$10;},
371 */ SEP,
372 statement list, !{
373 create_pushdbl(p);
374 create_pushdblsym(s);
375 create_dblbin('+');
376 create_popdblsym(s);
377 swap();popgoto();poplabel();},
378 next_or_eofile, next_symbol ={/* cookie*/}
379
380 next_or_eofile
381 -> "NEXT"
382 -> eof ={end_of_file=TRUE;
383 error(ERROR,"'next'-statement is missing"); PCB.exit_flag = AG_SYNTAX_ERROR_CODE;}
384
385 (double) step_part
386 -> /* can be omitted */ =1.0;
387 -> "STEP", const:v =v;
388
389 next_symbol
390 -> /* can be omitted */ ={pop();}
391 -> SYMBOL:s ={if (strcmp(pop()->pointer,s))
392 {error(ERROR,"'for' and 'next' do not match"); PCB.exit_flag = AG_SYNTAX_ERROR_CODE;}
393 }
394
395 if_clause
396 -> "IF", condition, !{
397 create_decide();pushlabel();},
398 "THEN", statement list, !{
399 pushlabel();swap();poplabel();},
400 else_part, !{
401 poplabel();},
402 endif_or_eof
403
404 endif_or_eof
405 -> "ENDIF"
406 -> eof ={end_of_file=TRUE;
407 error(ERROR,"'endif'-statement is missing"); PCB.exit_flag = AG_SYNTAX_ERROR_CODE;}
408 /*
409 condition
410 -> '(', condition, ')'
411 -> condition, "OR", condition ={create_boole('|');}
412 -> "NOT", condition ={create_boole('!');}
413 */
414
415 condition
416 -> and condition
417 -> condition, "OR", and condition ={create_boole('|');}
418
419
420 and condition
421 -> primary condition
422 -> and condition, "AND", primary condition ={create_boole('&');}
423
424 primary condition
425 -> comparison
426 -> '(', condition, ')'
427 -> "NOT", primary condition
428
429 comparison
430 -> string expression, '=', string expression ={create_strrelop('=');}
431 -> string expression, "<>", string expression ={create_strrelop('!');}
432 -> string expression, '<', string expression ={create_strrelop('<');}
433 -> string expression, "<=", string expression ={create_strrelop('{');}
434 -> string expression, '>', string expression ={create_strrelop('>');}
435 -> string expression, ">=", string expression ={create_strrelop('}');}
436 -> expression, '=', expression ={create_dblrelop('=');}
437 -> expression, "<>", expression ={create_dblrelop('!');}
438 -> expression, '<', expression ={create_dblrelop('<');}
439 -> expression, "<=", expression ={create_dblrelop('{');}
440 -> expression, '>', expression ={create_dblrelop('>');}
441 -> expression, ">=", expression ={create_dblrelop('}');}
442 //-> MYEOF, '(', hashed_number, ')' ={create_testeof($3);}
443
444 else_part /* can be omitted */
445 ->
446 -> "ELSE", statement list
447
448 inputlist
449 -> input
450 -> input, ',', inputlist
451
452 input
453 -> SYMBOL:s ={create_myread('d');create_popdblsym(s);}
454 -> SYMBOL:s, '(', !{
455 pushcounter();},
456 indexlist, ')' ={create_myread('d');create_doarray(s,ASSIGNARRAY);}
457 -> STRSYM:s ={create_myread('s');create_popstrsym(s);}
458 -> STRSYM:s, '(', !{
459 pushcounter();},
460 indexlist, ')' ={create_myread('s');create_doarray(s,ASSIGNSTRINGARRAY);}
461
462 readlist
463 -> readitem
464 -> readlist, ',', readitem
465
466 readitem
467 -> SYMBOL:s ={create_readdata('d');create_popdblsym(s);}
468 -> SYMBOL:s, '(', !{
469 pushcounter();},
470 indexlist, ')' ={create_readdata('d');create_doarray(s,ASSIGNARRAY);}
471 -> STRSYM:s ={create_readdata('s');create_popstrsym(s);}
472 -> STRSYM:s, '(', !{
473 pushcounter();},
474 indexlist, ')' ={create_readdata('s');create_doarray(s,ASSIGNSTRINGARRAY);}
475
476 datalist
477 -> STRING:s ={create_strdata(s);}
478 -> const:v ={create_dbldata(v);}
479 -> datalist, ',', STRING:s ={create_strdata(s);}
480 -> datalist, ',', const:v ={create_dbldata(v);}
481
482 printlist /* possible empty */
483 ->
484 -> expression ={create_print('d');}
485 -> printlist, ',', expression ={create_print('d');}
486 -> string expression ={create_print('s');}
487 -> printlist, ',', string expression ={create_print('s');}
488
489 inputintro
490 -> ={create_myswitch(0);create_readline(NULL);}
491 -> stream
492 -> position ={create_myswitch(0);create_readline(NULL);}
493 -> !{
494 create_myswitch(0);},
495 prompt
496 -> position, !{
497 create_myswitch(0);},
498 prompt
499
500 printintro
501 -> /* can be empty */ ={create_myswitch(0);}
502 -> stream
503 -> "REVERSE" ={create_revert(TRUE);create_myswitch(0);}
504 -> position ={create_myswitch(0);}
505 -> "REVERSE", position ={create_revert(TRUE);create_myswitch(0);}
506
507 prompt
508 -> STRING:s ={create_readline(s);}
509
510 position
511 -> "AT", '(', expression, ',', expression, ')' ={create_mymove();}
512
513 stream
514 -> '#', intnum:n ={create_myswitch(n);}
515
516 (int) hashed_number
517 -> '#', intnum:n =n;
518 -> intnum:n /* need not contain hash */ =n;
519
520 semicolon /* can be left out */
521 -> ={create_print('n');}
522 -> ';'
523
524 goto_list
525 -> symbol_or_lineno:s ={create_goto(s);create_findnop();}
526 -> goto_list, ',', symbol_or_lineno:s ={create_goto(s);create_findnop();}
527
528 gosub_list
529 -> symbol_or_lineno:s ={create_gosub(s);create_findnop();}
530 -> gosub_list, ',', symbol_or_lineno:s ={create_gosub(s);create_findnop();}
531
532 {
533 #define CHAR_STACK_LENGTH 500
534
535 static char charStack[CHAR_STACK_LENGTH+1];
536 static char *charStackTop = charStack;
537
538 /* Define an error record */
539 typedef struct {
540 char *message; /* identifies error */
541 int line; /* location of error */
542 int column;
543 } ErrorRecord;
544
545 ErrorRecord errorRecord; /* define an error record */
546
547 void diagnoseError(char *msg) {
548 if (parseBasic_pcb.exit_flag == AG_RUNNING_CODE)
549 parseBasic_pcb.exit_flag = AG_SEMANTIC_ERROR_CODE; /* stop parse */
550 errorRecord.message = msg;
551 errorRecord.line = parseBasic_pcb.line;
552 errorRecord.column = parseBasic_pcb.column;
553 }
554
555 void pushChar(int c) { /* append char to name string */
556 if (charStackTop < charStack+CHAR_STACK_LENGTH) {
557 *charStackTop++ = (char) c;
558 return;
559 }
560 /* buffer overflow, kill parse and issue diagnostic */
561 diagnoseError("Character Stack Overflow");
562 }
563
564 static char *popString(int nChars) { /* get string */
565 *charStackTop = 0;
566 return charStackTop -= nChars;
567 }
568
569 FILE *parserInputFile;
570 void switch_to_my_file(FILE *inputfile) /* switches lex input to given file */
571 {
572 parserInputFile = inputfile;
573 return;
574 }
575
576 #define GET_INPUT ((PCB).input_code = fgetc(parserInputFile))
577
578 int yyparse() {
579 parseBasic();
580 return !(PCB.exit_flag == AG_SUCCESS_CODE);
581 }
582
583
584 }