view tests/agcl/contrib/bug-I158.syn @ 21:1c9dac05d040

Add lint-style FALLTHROUGH annotations to fallthrough cases. (in the parse engine and thus the output code) Document this, because the old output causes warnings with gcc10.
author David A. Holland
date Mon, 13 Jun 2022 00:04:38 -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);

}

/* float number *//* integer number *//* token of command *//* number of newlines *//* quoted string *//* general symbol *//* string of digits *//* string symbol */
(double ) step_part

(double ) const

(double ) number

(int ) intnum

(char *) symbol_or_lineno

(int ) hashed_number

(int ) SEP

(int ) EOFILE


FNUM
 -> simple real
 -> simple real:x, 'e'+'E', '+'?,exponent:e            =x*pow(10,e);
 -> simple real:x, 'e'+'E', '-',exponent:e            =x*pow(10,-e);

simple real
 -> integer part:i, '.', fraction part:f                      = i+f;
 -> integer part, '.'?
 -> '.', fraction part:f                                        = f;

integer part
 -> digit:d                                                 = d-'0';
 -> integer part:x, digit:d                          = 10*x + d-'0';

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));

GOSUB, LABEL, ON

INTERRUPT, BREAK, CONTINUE, SEP, EOFILE

IF, THEN, ELSE, ENDIF

PRINT, INPUT, LINE, RETURN, DIM, END, AT, SCREEN, REVERSE

AND, OR, NOT

NE, LE, GE, LT, GT, EQ

READ, DATA, RESTORE

OPEN, CLOSE

WINDOW, DOT, LINE, CIRCLE, TEXT, CLEAR, PRINTER

WAIT, BELL, MAP, XMAP, YMAP, ARROW, XTICK, YTICK


SIN, ASIN, COS, ACOS, TAN, ATAN, EXP, LOG, SQRT, MYEOF

INT, FRAC, MOD, RAN, LEN, VAL, LEFT, RIGHT, MID, LEN, MIN, MAX

STR, INKEY, CHR, ASC, UPPER, LOWER, TRIM, LTRIM, RTRIM, INSTR

SYSTEM, SYSTEM2, PEEK, PEEK2, POKE, DATE, TIME



[
  left {OR}
  left {AND}
  left {NOT}
  left {'-', '+'}
  left {'*', '/'}
  left {'^'}
  nonassoc {UMINUS}
]

letter = 'a-z' + 'A-Z'
digit  = '0-9'
eof = 0 + -1

NAME
 -> letter
 -> NAME, letter+digit


program $
 -> statement list, eof

statement list
 ->
 -> statement_list, !{
if (errorlevel<=ERROR) {YYABORT;}},
   SEP, !{
yylineno+=$3;},
   statement

statement  /* empty */
 ->
 -> string_assignment
 -> assignment
 -> for_loop
 -> if_clause
 -> "GOTO", symbol_or_lineno ={create_goto($2);}
 -> "GOSUB", symbol_or_lineno ={create_gosub($2);}
 -> 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, ',', string_expression, ',', string_expression ={create_myopen($2,'+');}
 -> OPEN, hashed_number, ',', string_expression ={create_myopen($2,'-');}
 -> CLOSE, hashed_number ={create_myclose($2);}
 -> PRINT, printintro, printlist, !{
create_revert(FALSE);},
   semicolon
 -> INPUT, inputintro, inputlist ={lastinput->args=0;}
 -> READ, readlist
 -> DATA, datalist
 -> RESTORE ={create_restore("");}
 -> RESTORE, symbol_or_lineno ={create_restore($2);}
 -> 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, EQ, string_expression ={create_popstrsym($1);}
 -> MID, '(', STRSYM, !{
create_pushstrptr($3);},
   ',', expression, ',', expression, ')', EQ, string_expression ={create_changestring(MYMID);}
 -> LEFT, '(', STRSYM, !{
create_pushstrptr($3);},
   ',', expression, ')', EQ, string_expression ={create_changestring(MYLEFT);}
 -> RIGHT, '(', STRSYM, !{
create_pushstrptr($3);},
   ',', expression, ')', EQ, string_expression ={create_changestring(MYRIGHT);}
 -> STRSYM, '(', !{
pushcounter();},
   indexlist, ')', EQ, string_expression ={create_doarray($1,ASSIGNSTRINGARRAY);}
 -> MID, '(', STRSYM, '(', !{
pushcounter();},
   indexlist, ')', !{
create_doarray($3,GETSTRINGPOINTER);},
   ',', expression, ',', expression, ')', EQ, string_expression ={create_changestring(MYMID);}
 -> LEFT, '(', STRSYM, '(', !{
pushcounter();},
   indexlist, ')', !{
create_doarray($3,GETSTRINGPOINTER);},
   ',', expression, ')', EQ, string_expression ={create_changestring(MYLEFT);}
 -> RIGHT, '(', STRSYM, '(', !{
pushcounter();},
   indexlist, ')', !{
create_doarray($3,GETSTRINGPOINTER);},
   ',', expression, ')', EQ, string_expression ={create_changestring(MYRIGHT);}

string_expression
 -> STRSYM ={create_pushstrsym($1);}
 -> string_function
 -> STRING ={if ($1==NULL) {error(ERROR,"String not terminated");create_pushstr("");} else {create_pushstr($1);}}
 -> string_expression, '+', string_expression ={create_concat();}
 -> STRSYM, '(', !{
pushcounter();},
   indexlist, ')' ={create_doarray($1,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, EQ, expression ={create_popdblsym($1);}
 -> SYMBOL, '(', !{
pushcounter();},
   indexlist, ')', EQ, expression ={create_doarray($1,ASSIGNARRAY);}

expression
 -> number ={create_pushdbl($1);}
 -> function
 -> SYMBOL ={create_pushdblsym($1);}
 -> SYMBOL, '(', !{
pushcounter();},
   indexlist, ')' ={create_doarray($1,CALLARRAY);}
 -> '(', expression, ')'
 -> 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);}

const
 -> number ={$$=$1;}
 -> '+', number ={$$=$2;}
 -> '-', number ={$$=-$2;}

number
 -> FNUM ={$$=$1;}
 -> DIGITS ={$$=atoi($1);}

intnum
 -> DIGITS ={$$=atoi($1);}

symbol_or_lineno
 -> DIGITS ={$$=$1;}
 -> SYMBOL ={$$=$1;}

dimlist
 -> SYMBOL, '(', !{
pushcounter();},
   indexlist, ')' ={create_dim($1,'d');}
 -> dimlist, ',', SYMBOL, '(', !{
pushcounter();},
   indexlist, ')' ={create_dim($3,'d');}
 -> STRSYM, '(', !{
pushcounter();},
   indexlist, ')' ={create_dim($1,'s');}
 -> dimlist, ',', STRSYM, '(', !{
pushcounter();},
   indexlist, ')' ={create_dim($3,'s');}

indexlist
 -> expression ={inccounter();}
 -> indexlist, ',', expression ={inccounter();}

for_loop
 -> "FOR", SYMBOL, EQ, expression, !{
pushname($2);create_popdblsym($2);pushgoto();
             create_pushdblsym($2);},
   "TO", expression, step_part, !{

	     create_dblrelop(($8>0)?'{':'}');
             create_decide();
             pushlabel();},
   SEP, !{
yylineno+=$10;},
   statement_list, !{

             create_pushdbl($8);
	     create_pushdblsym($2);
             create_dblbin('+');
	     create_popdblsym($2);
             swap();popgoto();poplabel();},
   next_or_eofile, next_symbol

next_or_eofile
 -> "NEXT"
 -> EOFILE ={end_of_file=TRUE;
	    error(ERROR,"'next'-statement is missing"); YYABORT;}
step_part
 ->  /* can be omitted */ ={$$=1.0;}
 -> "STEP", const ={$$=$2;}

next_symbol
 -> /* can be omitted */ ={pop();}
 -> SYMBOL ={if (strcmp(pop()->pointer,$1))
             {error(ERROR,"'for' and 'next' do not match"); YYABORT;}
           }

if_clause
 -> IF, condition, !{
create_decide();pushlabel();},
   THEN, statement_list, !{
pushlabel();swap();poplabel();},
   else_part, !{
poplabel();},
   endif_or_eof

endif_or_eof
 -> ENDIF
 -> EOFILE ={end_of_file=TRUE;
            error(ERROR,"'endif'-statement is missing"); YYABORT;}

condition
 -> '(', condition, ')'
 -> condition, OR, condition ={create_boole('|');}
 -> condition, AND, condition ={create_boole('&');}
 -> NOT, condition ={create_boole('!');}
 -> string_expression, EQ, string_expression ={create_strrelop('=');}
 -> string_expression, NE, string_expression ={create_strrelop('!');}
 -> string_expression, LT, string_expression ={create_strrelop('<');}
 -> string_expression, LE, string_expression ={create_strrelop('{');}
 -> string_expression, GT, string_expression ={create_strrelop('>');}
 -> string_expression, GE, string_expression ={create_strrelop('}');}
 -> expression, EQ, expression ={create_dblrelop('=');}
 -> expression, NE, expression ={create_dblrelop('!');}
 -> expression, LT, expression ={create_dblrelop('<');}
 -> expression, LE, expression ={create_dblrelop('{');}
 -> expression, GT, expression ={create_dblrelop('>');}
 -> expression, GE, expression ={create_dblrelop('}');}
 -> MYEOF, '(', hashed_number, ')' ={create_testeof($3);}

else_part /* can be omitted */
 ->
 -> ELSE, statement_list

inputlist
 -> input
 -> input, ',', inputlist

input
 -> SYMBOL ={create_myread('d');create_popdblsym($1);}
 -> SYMBOL, '(', !{
pushcounter();},
   indexlist, ')' ={create_myread('d');create_doarray($1,ASSIGNARRAY);}
 -> STRSYM ={create_myread('s');create_popstrsym($1);}
 -> STRSYM, '(', !{
pushcounter();},
   indexlist, ')' ={create_myread('s');create_doarray($1,ASSIGNSTRINGARRAY);}

readlist
 -> readitem
 -> readlist, ',', readitem

readitem
 -> SYMBOL ={create_readdata('d');create_popdblsym($1);}
 -> SYMBOL, '(', !{
pushcounter();},
   indexlist, ')' ={create_readdata('d');create_doarray($1,ASSIGNARRAY);}
 -> STRSYM ={create_readdata('s');create_popstrsym($1);}
 -> STRSYM, '(', !{
pushcounter();},
   indexlist, ')' ={create_readdata('s');create_doarray($1,ASSIGNSTRINGARRAY);}

datalist
 -> STRING ={create_strdata($1);}
 -> const ={create_dbldata($1);}
 -> datalist, ',', STRING ={create_strdata($3);}
 -> datalist, ',', const ={create_dbldata($3);}

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 ={create_readline($1);}

position
 -> AT, '(', expression, ',', expression, ')' ={create_mymove();}

stream
 -> '#', intnum ={create_myswitch($2);}

hashed_number
 -> '#', intnum ={$$=$2;}
 -> intnum /* need not contain hash */ ={$$=$1;}

semicolon /* can be left out */
 ->  ={create_print('n');}
 -> ';'

goto_list
 -> symbol_or_lineno ={create_goto($1);create_findnop();}
 -> goto_list, ',', symbol_or_lineno ={create_goto($3);create_findnop();}

gosub_list
 -> symbol_or_lineno ={create_gosub($1);create_findnop();}
 -> gosub_list, ',', symbol_or_lineno ={create_gosub($3);create_findnop();}