diff options
author | Akim Demaille <akim.demaille@gmail.com> | 2020-02-02 07:50:50 +0100 |
---|---|---|
committer | Akim Demaille <akim.demaille@gmail.com> | 2020-02-02 11:33:16 +0100 |
commit | fe14fb1c4026b96907efb77fc242a007558b08de (patch) | |
tree | 4509d14c5331fae22368fc4d6163bddb3b3c57d2 /tests/calc.at | |
parent | 88d1ab421a4730504aabd1e61e8380027ec96545 (diff) | |
download | bison-fe14fb1c4026b96907efb77fc242a007558b08de.tar.gz |
java: use the same calc tests as the other skeletons
* tests/local.at (AT_LANG_MATCH): New.
(AT_YYERROR_DECLARE(java), AT_YYERROR_DECLARE_EXTERN(java)): New.
* tests/calc.at: The grammar file for Java is quite different for the
others, and continuing to assemble it from pieces makes the grammar
file hard to understand. Let's also dispatch on the language to
assemble it, and isolate Java from the others.
Most of this comes from java.at.
Diffstat (limited to 'tests/calc.at')
-rw-r--r-- | tests/calc.at | 273 |
1 files changed, 249 insertions, 24 deletions
diff --git a/tests/calc.at b/tests/calc.at index 2884275e..837a4d52 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -112,6 +112,19 @@ m4_define([AT_CALC_MAIN(d)], ]]) +m4_define([AT_CALC_MAIN(java)], +[[public static void main (String args[]) throws IOException + {]AT_LEXPARAM_IF([[ + Calc p = new Calc (System.in);]], [[ + CalcLexer l = new CalcLexer (System.in); + Calc p = new Calc (l);]])AT_DEBUG_IF([[ + p.setDebugLevel (1);]])[ + boolean success = p.parse (); + if (!success) + System.exit (1); + } +]]) + # --------------- # # AT_CALC_YYLEX. # @@ -318,6 +331,66 @@ class CalcLexer(R) : Lexer ]]) +m4_define([AT_CALC_YYLEX(java)], +[AT_LEXPARAM_IF([[%code lexer {]], + [[%code epilogue { class CalcLexer implements Calc.Lexer {]])[ + StreamTokenizer st; + + public ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]])[ (InputStream is) + { + st = new StreamTokenizer (new InputStreamReader (is)); + st.resetSyntax (); + st.eolIsSignificant (true); + st.whitespaceChars ('\t', '\t'); + st.whitespaceChars (' ', ' '); + st.wordChars ('0', '9'); + } + +]AT_LOCATION_IF([[ + Position yypos = new Position (1, 0); + + public Position getStartPos() { + return yypos; + } + + public Position getEndPos() { + return yypos; + } +]])[ + ]AT_YYERROR_DEFINE[ + + Integer yylval; + + public Object getLVal () { + return yylval; + } + + public int yylex () throws IOException { + int ttype = st.nextToken ();]AT_LOCATION_IF([[ + yypos = new Position (yypos.lineno (), yypos.token () + 1);]])[ + if (ttype == st.TT_EOF) + return EOF; + + else if (ttype == st.TT_EOL) + {]AT_LOCATION_IF([[ + yypos = new Position (yypos.lineno () + 1, 0);]])[ + return (int) '\n'; + } + + else if (ttype == st.TT_WORD) + { + yylval = new Integer (st.sval); + return NUM; + } + + else + return st.ttype; + } +]AT_LEXPARAM_IF([], [[}]])[ +}; +]]) + + # -------------- # # AT_DATA_CALC. # # -------------- # @@ -338,19 +411,23 @@ class CalcLexer(R) : Lexer # stress the use of the generated parser header. To avoid code # duplication, AT_CALC_YYLEX and AT_CALC_MAIN contain the body of these # two later files. -m4_define([_AT_DATA_CALC_Y], +m4_pushdef([_AT_DATA_CALC_Y], [m4_if([$1$2$3], $[1]$[2]$[3], [], [m4_fatal([$0: Invalid arguments: $@])])dnl +AT_LANG_DISPATCH([$0], $@)]) -AT_DATA_GRAMMAR([calc.y], +m4_define([_AT_DATA_CALC_Y(c)], +[AT_DATA_GRAMMAR([calc.y], [[/* Infix notation calculator--calc */ ]$4[ ]AT_CXX_IF([%define global_tokens_and_yystype])[ -]AT_D_IF([[ +]AT_LANG_MATCH( +[d], [[ %code imports { alias semantic_value = int; } -]], [[ +]], +[c\|c++], [[ %code requires { ]AT_LOCATION_TYPE_SPAN_IF([[ @@ -399,7 +476,7 @@ void location_print (FILE *o, Span s); %printer { ]AT_CXX_IF([[yyo << $$]], [[fprintf (yyo, "%d", $$)]])[; } <ival>; -]AT_D_IF([], [[ +]AT_LANG_MATCH([c\|c++], [[ %code provides { #include <stdio.h> @@ -448,7 +525,7 @@ void location_print (FILE *o, Span s); }]])[ /* Bison Declarations */ -%token CALC_EOF 0 _("end of input") +%token CALC_EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of input")], ["end of input"])[ %token <ival> NUM "number" %type <ival> exp @@ -480,16 +557,16 @@ exp: ])[ $$ = $1; } -| exp '+' exp { $$ = $1 + $3; } -| exp '-' exp { $$ = $1 - $3; } -| exp '*' exp { $$ = $1 * $3; } -| exp '/' exp { $$ = $1 / $3; } -| '-' exp %prec NEG { $$ = -$2; } +| exp '+' exp { $$ = $1 + $3; } +| exp '-' exp { $$ = $1 - $3; } +| exp '*' exp { $$ = $1 * $3; } +| exp '/' exp { $$ = $1 / $3; } +| '-' exp %prec NEG { $$ = -$2; } | exp '^' exp { $$ = power ($1, $3); } -| '(' exp ')' { $$ = $2; } -| '(' error ')' { $$ = 1111; ]AT_D_IF([], [yyerrok;])[ } -| '!' { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[; } -| '-' error { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[; } +| '(' exp ')' { $$ = $2; } +| '(' error ')' { $$ = 1111; ]AT_D_IF([], [yyerrok;])[ } +| '!' { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[; } +| '-' error { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[; } ; %% @@ -543,10 +620,137 @@ AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT], ]AT_CALC_MAIN]) ]) - ])# _AT_DATA_CALC_Y +m4_copy([_AT_DATA_CALC_Y(c)], [_AT_DATA_CALC_Y(c++)]) +m4_copy([_AT_DATA_CALC_Y(c)], [_AT_DATA_CALC_Y(d)]) + +m4_define([_AT_DATA_CALC_Y(java)], +[AT_DATA_GRAMMAR([Calc.y], +[[/* Infix notation calculator--calc */ +%define api.prefix {Calc} +%define api.parser.class {Calc} +%define public + +]$4[ + +%code imports { + import java.io.StreamTokenizer; + import java.io.InputStream; + import java.io.InputStreamReader; + import java.io.Reader; + import java.io.IOException; +} + +%code { +]AT_CALC_MAIN[ +} + +/* Bison Declarations */ +%token <Integer> NUM "number" +%type <Integer> exp + +%nonassoc '=' /* comparison */ +%left '-' '+' +%left '*' '/' +%precedence NEG /* negation--unary minus */ +%right '^' /* exponentiation */ + +/* Grammar follows */ +%% +input: + line +| input line +; + +line: + '\n' +| exp '\n' +; + +exp: + NUM +| exp '=' exp + { + if ($1.intValue () != $3.intValue ()) + yyerror (]AT_LOCATION_IF([[@$, ]])["calc: error: " + $1 + " != " + $3); + } +| exp '+' exp { $$ = $1 + $3; } +| exp '-' exp { $$ = $1 - $3; } +| exp '*' exp { $$ = $1 * $3; } +| exp '/' exp { $$ = $1 / $3; } +| '-' exp %prec NEG { $$ = -$2; } +| exp '^' exp { $$ = (int) Math.pow ($1, $3); } +| '(' exp ')' { $$ = $2; } +| '(' error ')' { $$ = 1111; } +| '!' { $$ = 0; return YYERROR; } +| '-' error { $$ = 0; return YYERROR; } +; + +]AT_LEXPARAM_IF([[%code lexer {]], + [[%code epilogue { class CalcLexer implements Calc.Lexer {]])[ + StreamTokenizer st; + + public ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]])[ (InputStream is) + { + st = new StreamTokenizer (new InputStreamReader (is)); + st.resetSyntax (); + st.eolIsSignificant (true); + st.whitespaceChars ('\t', '\t'); + st.whitespaceChars (' ', ' '); + st.wordChars ('0', '9'); + } + +]AT_LOCATION_IF([[ + Position yypos = new Position (1, 0); + + public Position getStartPos() { + return yypos; + } + + public Position getEndPos() { + return yypos; + } +]])[ + ]AT_YYERROR_DEFINE[ + + Integer yylval; + + public Object getLVal() { + return yylval; + } + + public int yylex () throws IOException { + int ttype = st.nextToken ();]AT_LOCATION_IF([[ + yypos = new Position (yypos.lineno (), yypos.token () + 1);]])[ + if (ttype == st.TT_EOF) + return EOF; + + else if (ttype == st.TT_EOL) + {]AT_LOCATION_IF([[ + yypos = new Position (yypos.lineno () + 1, 0);]])[ + return (int) '\n'; + } + + else if (ttype == st.TT_WORD) + { + yylval = new Integer (st.sval); + return NUM; + } + + else + return st.ttype; + } +]AT_LEXPARAM_IF([], [[}]])[ +}; +%% +]AT_JAVA_POSITION_DEFINE[ +]]) +])# _AT_DATA_JAVA_CALC_Y + + + # AT_DATA_CALC_Y([BISON-OPTIONS]) # ------------------------------- # Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or @@ -571,8 +775,10 @@ m4_define([_AT_CHECK_CALC], [AT_DATA([[input]], [[$2 ]]) -AT_PARSER_CHECK([calc input], 0, [AT_PARAM_IF([m4_n([$3])])], [stderr]) -AT_D_IF([], +AT_JAVA_IF( + [AT_JAVA_PARSER_CHECK([Calc < input], 0, [AT_PARAM_IF([m4_n([$3])])], [stderr])], + [AT_PARSER_CHECK([calc input], 0, [AT_PARAM_IF([m4_n([$3])])], [stderr])]) +AT_LANG_MATCH([c\|c++], [AT_GLR_IF([], [AT_CHECK([cat stderr | wc -l], [0], [m4_n([AT_DEBUG_IF([$4], [0])])])])]) ]) @@ -597,11 +803,16 @@ AT_D_IF([], # computed from it. m4_define([_AT_CHECK_CALC_ERROR], [m4_bmatch([$3], [^/], - [AT_PARSER_CHECK([calc $3], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])], - [AT_DATA([[input]], + [AT_JAVA_IF( + [AT_JAVA_PARSER_CHECK([Calc < $3], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])], + [AT_PARSER_CHECK([calc $3], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])])], + [AT_DATA([[input]], [[$3 ]]) -AT_PARSER_CHECK([calc input], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])]) + AT_JAVA_IF( + [AT_JAVA_PARSER_CHECK([Calc < input], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])], + [AT_PARSER_CHECK([calc input], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])]) +]) # Normalize the observed and expected error messages, depending upon the # options. @@ -690,8 +901,8 @@ AT_SETUP([Calculator $1 $2]) AT_BISON_OPTION_PUSHDEFS([$1]) AT_DATA_CALC_Y([$1]) -AT_FULL_COMPILE([calc], AT_DEFINES_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated]) -AT_CHECK_SPACES([calc.AT_LANG_EXT AT_DEFINES_IF([calc.AT_LANG_HDR])]) +AT_FULL_COMPILE(AT_JAVA_IF([[Calc]], [[calc]]), AT_DEFINES_IF([[lex], [main]], [[], []]), [$2], [-Wno-deprecated]) +AT_CHECK_SPACES([AT_JAVA_IF([Calc], [calc]).AT_LANG_EXT AT_DEFINES_IF([AT_JAVA_IF([Calc], [calc]).AT_LANG_HDR])]) # Test the precedences. _AT_CHECK_CALC([$1], @@ -812,7 +1023,7 @@ AT_BANNER([[LALR(1) Calculator.]]) m4_define([AT_CHECK_CALC_LALR], [AT_CHECK_CALC($@)]) -AT_CHECK_CALC_LALR() +AT_CHECK_CALC_LALR([%define parse.trace]) AT_CHECK_CALC_LALR([%defines]) AT_CHECK_CALC_LALR([%locations]) @@ -980,6 +1191,20 @@ AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %verbose]) #AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}]) #AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}]) + +# ----------------------- # +# LALR1 Java Calculator. # +# ----------------------- # + +AT_BANNER([[LALR(1) Java Calculator.]]) + +m4_define([AT_CHECK_CALC_LALR1_JAVA], +[AT_CHECK_CALC([%language "Java" $1], [$2])]) + +AT_CHECK_CALC_LALR1_JAVA + + + m4_popdef([AT_TOKEN_TRANSLATE_IF]) m4_popdef([AT_CALC_MAIN]) m4_popdef([AT_CALC_YYLEX]) |