Mercurial > ~dholland > hg > ag > index.cgi
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/agcl/contrib/yabasic.syn Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,584 @@ +{ + +/* + YABASIC --- a tiny integrated Basic Compiler/Interpreter + + BISON - part + + this Program is subject to the GNU General Public License; + see the file yabasic.c for details. +*/ + + +//#undef WINDOWS +#include "yabasic.h" /* definitions of yabasic */ +#include <malloc.h> + +#if HAVE_ALLOCA_H +#include <alloca.h> +#endif + +void __yy_bcopy(char *,char *,int); /* prototype missing */ + +int yylineno=1; +int yylex(void); + +char *popString(int); +void pushChar(int); + +} + +[ + ~case sensitive + disregard white space + lexeme {digit string, name, STRING, STRSYM, number} + distinguish lexemes + parser name = parseBasic + line numbers + escape backslashes +] + +white space = ' ' + '\t' + +//(double *) step_part + + +SEP + -> ["REM", ~(eof + white space + '\n')?...], '\n' ={ + yylineno++; + if (interactive) PCB.exit_flag = AG_SUCCESS_CODE; + return; + } + +(double) number + -> simple real + -> simple real:x, 'e'+'E', '+'?,exponent:e =x*pow(10,e); + -> simple real:x, 'e'+'E', '-',exponent:e =x*pow(10,-e); + +(double) simple real + -> integer part:i, '.', fraction part:f = i+f; + -> integer part, '.'? + -> '.', fraction part:f = f; + +(double) integer part + -> digit:d = d-'0'; + -> integer part:x, digit:d = 10*x + d-'0'; + +(double) fraction part + -> digit:d =(d-'0')/10.; + -> digit:d, fraction part:f =(d-'0' + f)/10.; + +(int) exponent + -> digit:d = d-'0'; + -> exponent:x, digit:d = 10*x + d-'0'; + +(int) name //value of name token is length of name string + -> letter: c =pushChar(c), 1; + -> name:k, letter+digit: c =pushChar(c), k+1; + + +(char *) SYMBOL + -> name:k =strdup(popString(k)); + +(char *) STRSYM + -> name:k, '$' =pushChar('$'), strdup(popString(k+1)); + +(char *) DIGITS + -> digit string:k =strdup(popString(k)); + +(int) digit string + -> digit:d =pushChar(d), 1; + -> digit string:k, digit:d =pushChar(d), k+1; + +(char *) STRING + -> '"', string text:k, '"' =strdup(popString(k)); + -> '"', string text:k, '\n' =strdup(popString(k)); + +(int) string text + -> =0; + -> string text:k, ~(eof + '"' + '\n'):c =pushChar(c), k+1; + -> string text:k, "\\\"" =pushChar('"'), k+1; + +/* +[ + left {"OR"} + left {"AND"} + left {"NOT"} + left {'-', '+'} + left {'*', '/'} + left {'^'} + nonassoc {UMINUS} +] +*/ + +letter = 'a-z' + 'A-Z' +digit = '0-9' +eof = 0 + -1 + + +program $ + -> statement list, eof =end_of_file = TRUE; + +statement list + -> +/* + -> statement_list, !{ +if (errorlevel<=ERROR) {YYABORT;}}, + SEP, !{ +yylineno+=$3;}, + statement +*/ + -> statement list, SEP, statement + -> statement list, SEP, label, statement + +label + -> "LABEL", SYMBOL:s =create_label(s); + -> DIGITS:s =create_label(s); + + +statement /* empty */ + -> + -> string_assignment + -> assignment + -> for_loop + -> if_clause + -> "GOTO", symbol_or_lineno:s ={create_goto(s);} + -> "GOSUB", symbol_or_lineno:s ={create_gosub(s);} + -> "ON", "INTERRUPT", "BREAK" ={create_exception(TRUE);} + -> "ON", "INTERRUPT", "CONTINUE" ={create_exception(FALSE);} + -> "ON", expression, "GOTO", !{create_skipper();}, goto_list ={create_nop();} + -> "ON", expression, "GOSUB", !{create_skipper();}, gosub_list ={create_nop();} +// -> LABEL, symbol_or_lineno ={create_label($2);} + -> "OPEN", hashed_number:n, ',', string expression, ',', string expression ={create_myopen(n,'+');} + -> "OPEN", hashed_number:n, ',', string expression ={create_myopen(n,'-');} + -> "CLOSE", hashed_number:n ={create_myclose(n);} + -> "PRINT", printintro, printlist, !{ +create_revert(FALSE);}, + semicolon + -> "INPUT", inputintro, inputlist =lastinput->args=0; + -> "READ", readlist + -> "DATA", datalist + -> "RESTORE" =create_restore(""); + -> "RESTORE", symbol_or_lineno:s =create_restore(s); + -> "RETURN" ={create_return();} + -> "DIM", dimlist + -> "OPEN", "WINDOW", expression, ',', expression =create_openwin(FALSE); + -> "OPEN", "WINDOW", expression, ',', expression, ',', string expression ={create_openwin(TRUE);} + -> "DOT", mapping =create_dot(); + -> "LINE", mapping, "TO", mapping =create_line('l'); + -> "CIRCLE", mapping, ',', expression =create_circle(); + -> "TEXT", string expression, ',', mapping =create_text(TRUE); + -> "TEXT", mapping, ',', string expression =create_text(FALSE); + -> "MAP", expression, ',', expression, ',', expression, ',', expression, "TO", expression, ',', expression, ',', expression, ',', expression =create_makemap(); + -> "ARROW", mapping, "TO", mapping =create_line('a'); + -> "XTICK", mapping, ',', string expression =create_tick(1); + -> "YTICK", mapping, ',', string expression =create_tick(3); + -> "XTICK", mapping =create_tick(0); + -> "YTICK", mapping =create_tick(2); + -> "CLOSE", "WINDOW" =create_closewin(); + -> "CLEAR", "WINDOW" =create_clearwin(); + -> "CLEAR", "SCREEN" =create_clearscreen(); + -> "OPEN", "PRINTER" =create_openprinter(0); + -> "OPEN", "PRINTER", string expression =create_openprinter(1); + -> "CLOSE", "PRINTER" =create_closeprinter(); + -> "WAIT", expression =create_mywait(); + -> "BELL" =create_bell(); + -> "INKEY" ={create_function(MYINKEY); create_popstrsym(NULL);} + -> "SYSTEM2", '(', string expression, ')' ={create_function(MYSYSTEM2); + create_popdblsym(NULL);} + -> "POKE", string expression, ',', string expression ={create_poke('s');} + -> "POKE", string expression, ',', expression ={create_poke('d');} + -> "END" ={create_myend();} + +string_assignment + -> STRSYM:s, '=', string expression ={create_popstrsym(s);} + -> "MID", '(', STRSYM:s, !{ +create_pushstrptr(s);}, + ',', expression, ',', expression, ')', '=', string expression ={create_changestring(MYMID);} + -> "LEFT", '(', STRSYM:s, !{ +create_pushstrptr(s);}, + ',', expression, ')', '=', string expression ={create_changestring(MYLEFT);} + -> "RIGHT", '(', STRSYM:s, !{ +create_pushstrptr(s);}, + ',', expression, ')', '=', string expression ={create_changestring(MYRIGHT);} + -> STRSYM:s, '(', !{ +pushcounter();}, + indexlist, ')', '=', string expression ={create_doarray(s,ASSIGNSTRINGARRAY);} + -> "MID", '(', STRSYM:s, '(', !{ +pushcounter();}, + indexlist, ')', !{ +create_doarray(s,GETSTRINGPOINTER);}, + ',', expression, ',', expression, ')', '=', string expression ={create_changestring(MYMID);} + -> "LEFT", '(', STRSYM:s, '(', !{ +pushcounter();}, + indexlist, ')', !{ +create_doarray(s,GETSTRINGPOINTER);}, + ',', expression, ')', '=', string expression ={create_changestring(MYLEFT);} + -> "RIGHT", '(', STRSYM:s, '(', !{ +pushcounter();}, + indexlist, ')', !{ +create_doarray(s,GETSTRINGPOINTER);}, + ',', expression, ')', '=', string expression ={create_changestring(MYRIGHT);} + +string expression + -> primary string expression + -> string expression, '+', primary string expression ={create_concat();} + +primary string expression + -> STRSYM:s ={create_pushstrsym(s);} + -> string_function + -> STRING:s ={if (s==NULL) {error(ERROR,"String not terminated");create_pushstr("");} else {create_pushstr(s);}} + -> STRSYM:s, '(', !{ +pushcounter();}, + indexlist, ')' ={create_doarray(s,CALLSTRINGARRAY);} + -> '(', string expression, ')' + +string_function + -> "LEFT", '(', string expression, ',', expression, ')' ={create_function(MYLEFT);} + -> "RIGHT", '(', string expression, ',', expression, ')' ={create_function(MYRIGHT);} + -> "MID", '(', string expression, ',', expression, ',', expression, ')' ={create_function(MYMID);} + -> "STR", '(', expression, ')' ={create_function(MYSTR);} + -> "STR", '(', expression, ',', string expression, ')' ={create_function(MYSTR2);} + -> "INKEY" ={create_function(MYINKEY);} + -> "CHR", '(', expression, ')' ={create_function(MYCHR);} + -> "UPPER", '(', string expression, ')' ={create_function(MYUPPER);} + -> "LOWER", '(', string expression, ')' ={create_function(MYLOWER);} + -> "LTRIM", '(', string expression, ')' ={create_function(MYLTRIM);} + -> "RTRIM", '(', string expression, ')' ={create_function(MYRTRIM);} + -> "TRIM", '(', string expression, ')' ={create_function(MYTRIM);} + -> "SYSTEM", '(', string expression, ')' ={create_function(MYSYSTEM);} + -> "DATE" ={create_function(MYDATE);} + -> "TIME" ={create_function(MYTIME);} + -> "PEEK2", '(', string expression, ')' ={create_function(MYPEEK2);} + +assignment + -> SYMBOL:s, '=', expression ={create_popdblsym(s);} + -> SYMBOL:s, '(', !{ +pushcounter();}, + indexlist, ')', '=', expression ={create_doarray(s,ASSIGNARRAY);} + +primary expression + -> number:n =create_pushdbl(n); + -> function + -> SYMBOL:s =create_pushdblsym(s); + -> SYMBOL:s, '(', !pushcounter();, + indexlist, ')' ={create_doarray(s,CALLARRAY);} + -> '(', expression, ')' + -> '-', primary expression /* 1ef4:fa2arec <֠ */ ={create_negate();} + +exponential expression + -> primary expression + -> exponential expression, '^', primary expression ={create_dblbin('^');} + +multiplicative expression + -> exponential expression + -> multiplicative expression, '*', exponential expression ={create_dblbin('*');} + -> multiplicative expression, '/', exponential expression ={create_dblbin('/');} + +expression + -> multiplicative expression + -> expression, '+', multiplicative expression ={create_dblbin('+');} + -> expression, '-', multiplicative expression ={create_dblbin('-');} + +/* + -> expression, '+', expression ={create_dblbin('+');} + -> expression, '-', expression ={create_dblbin('-');} + -> expression, '*', expression ={create_dblbin('*');} + -> expression, '/', expression ={create_dblbin('/');} + -> expression, '^', expression ={create_dblbin('^');} + -> '-', expression /* 1ef4:fa2arec <֠ * / ={create_negate();} +*/ + +mapping + -> expression, ',', expression + -> "MAP", '(', expression, ',', expression, ')' ={create_map();} + +function + -> "SIN", '(', expression, ')' ={create_function(MYSIN);} + -> "ASIN", '(', expression, ')' ={create_function(MYASIN);} + -> "COS", '(', expression, ')' ={create_function(MYCOS);} + -> "ACOS", '(', expression, ')' ={create_function(MYACOS);} + -> "TAN", '(', expression, ')' ={create_function(MYTAN);} + -> "ATAN", '(', expression, ')' ={create_function(MYATAN);} + -> "ATAN", '(', expression, ',', expression, ')' ={create_function(MYATAN2);} + -> "EXP", '(', expression, ')' ={create_function(MYEXP);} + -> "LOG", '(', expression, ')' ={create_function(MYLOG);} + -> "SQRT", '(', expression, ')' ={create_function(MYSQRT);} + -> "INT", '(', expression, ')' ={create_function(MYINT);} + -> "FRAC", '(', expression, ')' ={create_function(MYFRAC);} + -> "MOD", '(', expression, ',', expression, ')' ={create_function(MYMOD);} + -> "RAN", '(', expression, ')' ={create_function(MYRAN);} + -> "RAN", '(', ')' ={create_function(MYRAN2);} + -> "MIN", '(', expression, ',', expression, ')' ={create_function(MYMIN);} + -> "MAX", '(', expression, ',', expression, ')' ={create_function(MYMAX);} + -> "XMAP", '(', expression, ')' ={create_function(MYXMAP);} + -> "YMAP", '(', expression, ')' ={create_function(MYYMAP);} + -> "LEN", '(', string expression, ')' ={create_function(MYLEN);} + -> "VAL", '(', string expression, ')' ={create_function(MYVAL);} + -> "ASC", '(', string expression, ')' ={create_function(MYASC);} + -> "INSTR", '(', string expression, ',', string expression, ')' ={create_function(MYINSTR);} + -> "SYSTEM2", '(', string expression, ')' ={create_function(MYSYSTEM2);} + -> "PEEK", '(', string expression, ')' ={create_function(MYPEEK);} + +(double) const + -> number:n =n; + -> '+', number:n =n; + -> '-', number:n =-n; + +/* +number + -> FNUM ={$$=$1;} + -> DIGITS ={$$=atoi($1);} +*/ + +(int) intnum + -> DIGITS:d =atoi(d); + +(char *) symbol_or_lineno + -> DIGITS:s =s; + -> SYMBOL:s =s; + +dimlist + -> SYMBOL:s, '(', !{ +pushcounter();}, + indexlist, ')' ={create_dim(s,'d');} + -> dimlist, ',', SYMBOL:s, '(', !{ +pushcounter();}, + indexlist, ')' ={create_dim(s,'d');} + -> STRSYM:s, '(', !{ +pushcounter();}, + indexlist, ')' ={create_dim(s,'s');} + -> dimlist, ',', STRSYM:s, '(', !{ +pushcounter();}, + indexlist, ')' ={create_dim(s,'s');} + +indexlist + -> expression ={inccounter();} + -> indexlist, ',', expression ={inccounter();} + +for_loop + -> "FOR", SYMBOL:s, '=', expression, !{ +pushname(s);create_popdblsym(s);pushgoto(); + create_pushdblsym(s);}, + "TO", expression, step_part:p, !{ + + create_dblrelop((p>0)?'{':'}'); + create_decide(); + pushlabel();}, +/* + SEP, !{ +yylineno+=$10;}, +*/ SEP, + statement list, !{ + create_pushdbl(p); + create_pushdblsym(s); + create_dblbin('+'); + create_popdblsym(s); + swap();popgoto();poplabel();}, + next_or_eofile, next_symbol ={/* cookie*/} + +next_or_eofile + -> "NEXT" + -> eof ={end_of_file=TRUE; + error(ERROR,"'next'-statement is missing"); PCB.exit_flag = AG_SYNTAX_ERROR_CODE;} + +(double) step_part + -> /* can be omitted */ =1.0; + -> "STEP", const:v =v; + +next_symbol + -> /* can be omitted */ ={pop();} + -> SYMBOL:s ={if (strcmp(pop()->pointer,s)) + {error(ERROR,"'for' and 'next' do not match"); PCB.exit_flag = AG_SYNTAX_ERROR_CODE;} + } + +if_clause + -> "IF", condition, !{ +create_decide();pushlabel();}, + "THEN", statement list, !{ +pushlabel();swap();poplabel();}, + else_part, !{ +poplabel();}, + endif_or_eof + +endif_or_eof + -> "ENDIF" + -> eof ={end_of_file=TRUE; + error(ERROR,"'endif'-statement is missing"); PCB.exit_flag = AG_SYNTAX_ERROR_CODE;} +/* +condition + -> '(', condition, ')' + -> condition, "OR", condition ={create_boole('|');} + -> "NOT", condition ={create_boole('!');} +*/ + +condition + -> and condition + -> condition, "OR", and condition ={create_boole('|');} + + +and condition + -> primary condition + -> and condition, "AND", primary condition ={create_boole('&');} + +primary condition + -> comparison + -> '(', condition, ')' + -> "NOT", primary condition + +comparison + -> string expression, '=', string expression ={create_strrelop('=');} + -> string expression, "<>", string expression ={create_strrelop('!');} + -> string expression, '<', string expression ={create_strrelop('<');} + -> string expression, "<=", string expression ={create_strrelop('{');} + -> string expression, '>', string expression ={create_strrelop('>');} + -> string expression, ">=", string expression ={create_strrelop('}');} + -> expression, '=', expression ={create_dblrelop('=');} + -> expression, "<>", expression ={create_dblrelop('!');} + -> expression, '<', expression ={create_dblrelop('<');} + -> expression, "<=", expression ={create_dblrelop('{');} + -> expression, '>', expression ={create_dblrelop('>');} + -> expression, ">=", expression ={create_dblrelop('}');} + //-> MYEOF, '(', hashed_number, ')' ={create_testeof($3);} + +else_part /* can be omitted */ + -> + -> "ELSE", statement list + +inputlist + -> input + -> input, ',', inputlist + +input + -> SYMBOL:s ={create_myread('d');create_popdblsym(s);} + -> SYMBOL:s, '(', !{ +pushcounter();}, + indexlist, ')' ={create_myread('d');create_doarray(s,ASSIGNARRAY);} + -> STRSYM:s ={create_myread('s');create_popstrsym(s);} + -> STRSYM:s, '(', !{ +pushcounter();}, + indexlist, ')' ={create_myread('s');create_doarray(s,ASSIGNSTRINGARRAY);} + +readlist + -> readitem + -> readlist, ',', readitem + +readitem + -> SYMBOL:s ={create_readdata('d');create_popdblsym(s);} + -> SYMBOL:s, '(', !{ +pushcounter();}, + indexlist, ')' ={create_readdata('d');create_doarray(s,ASSIGNARRAY);} + -> STRSYM:s ={create_readdata('s');create_popstrsym(s);} + -> STRSYM:s, '(', !{ +pushcounter();}, + indexlist, ')' ={create_readdata('s');create_doarray(s,ASSIGNSTRINGARRAY);} + +datalist + -> STRING:s ={create_strdata(s);} + -> const:v ={create_dbldata(v);} + -> datalist, ',', STRING:s ={create_strdata(s);} + -> datalist, ',', const:v ={create_dbldata(v);} + +printlist /* possible empty */ + -> + -> expression ={create_print('d');} + -> printlist, ',', expression ={create_print('d');} + -> string expression ={create_print('s');} + -> printlist, ',', string expression ={create_print('s');} + +inputintro + -> ={create_myswitch(0);create_readline(NULL);} + -> stream + -> position ={create_myswitch(0);create_readline(NULL);} + -> !{ +create_myswitch(0);}, + prompt + -> position, !{ +create_myswitch(0);}, + prompt + +printintro + -> /* can be empty */ ={create_myswitch(0);} + -> stream + -> "REVERSE" ={create_revert(TRUE);create_myswitch(0);} + -> position ={create_myswitch(0);} + -> "REVERSE", position ={create_revert(TRUE);create_myswitch(0);} + +prompt + -> STRING:s ={create_readline(s);} + +position + -> "AT", '(', expression, ',', expression, ')' ={create_mymove();} + +stream + -> '#', intnum:n ={create_myswitch(n);} + +(int) hashed_number + -> '#', intnum:n =n; + -> intnum:n /* need not contain hash */ =n; + +semicolon /* can be left out */ + -> ={create_print('n');} + -> ';' + +goto_list + -> symbol_or_lineno:s ={create_goto(s);create_findnop();} + -> goto_list, ',', symbol_or_lineno:s ={create_goto(s);create_findnop();} + +gosub_list + -> symbol_or_lineno:s ={create_gosub(s);create_findnop();} + -> gosub_list, ',', symbol_or_lineno:s ={create_gosub(s);create_findnop();} + +{ +#define CHAR_STACK_LENGTH 500 + +static char charStack[CHAR_STACK_LENGTH+1]; +static char *charStackTop = charStack; + +/* Define an error record */ +typedef struct { + char *message; /* identifies error */ + int line; /* location of error */ + int column; +} ErrorRecord; + +ErrorRecord errorRecord; /* define an error record */ + +void diagnoseError(char *msg) { + if (parseBasic_pcb.exit_flag == AG_RUNNING_CODE) + parseBasic_pcb.exit_flag = AG_SEMANTIC_ERROR_CODE; /* stop parse */ + errorRecord.message = msg; + errorRecord.line = parseBasic_pcb.line; + errorRecord.column = parseBasic_pcb.column; +} + +void pushChar(int c) { /* append char to name string */ + if (charStackTop < charStack+CHAR_STACK_LENGTH) { + *charStackTop++ = (char) c; + return; + } + /* buffer overflow, kill parse and issue diagnostic */ + diagnoseError("Character Stack Overflow"); +} + +static char *popString(int nChars) { /* get string */ + *charStackTop = 0; + return charStackTop -= nChars; +} + +FILE *parserInputFile; +void switch_to_my_file(FILE *inputfile) /* switches lex input to given file */ +{ + parserInputFile = inputfile; + return; +} + +#define GET_INPUT ((PCB).input_code = fgetc(parserInputFile)) + +int yyparse() { + parseBasic(); + return !(PCB.exit_flag == AG_SUCCESS_CODE); +} + + +}