Mercurial > ~dholland > hg > ag > index.cgi
view tests/agcl/contrib/yabasic.syn @ 8:ec2b657edf13
Add explicit lint-comment-style fallthrough annotations.
GCC now assumes that if you don't have these you're making a mistake,
which is annoying.
XXX: This changeset updates the AG output files only (by hand) and is
XXX: abusive - rebuilding them will erase the change. However, I need
XXX: to get things to build before I can try to get AG to issue the
XXX: annotations itself, so this seems like a reasonable expedient.
author | David A. Holland |
---|---|
date | Mon, 30 May 2022 23:51:43 -0400 |
parents | 13d2b8934445 |
children |
line wrap: on
line source
{ /* 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); } }