bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 9/9] java: use the same calc tests as the other skeletons


From: Akim Demaille
Subject: [PATCH 9/9] java: use the same calc tests as the other skeletons
Date: Sun, 2 Feb 2020 15:26:27 +0100

* 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.
---
 data/skeletons/lalr1.java |   4 +-
 tests/calc.at             | 273 ++++++++++++++++++++++++++++++++++----
 tests/local.at            |   9 ++
 3 files changed, 260 insertions(+), 26 deletions(-)

diff --git a/data/skeletons/lalr1.java b/data/skeletons/lalr1.java
index de912383..e9da8cc5 100644
--- a/data/skeletons/lalr1.java
+++ b/data/skeletons/lalr1.java
@@ -565,7 +565,7 @@ m4_define([b4_define_state],[[
     ]b4_location_type[ yyloc;]])[
 ]b4_push_if([],[[
 ]b4_define_state[]b4_parse_trace_if([[
-    yycdebug ("Starting parse\n");]])[
+    yycdebug ("Starting parse");]])[
     yyerrstatus_ = 0;
     yynerrs = 0;
 
@@ -599,7 +599,7 @@ b4_dollar_popdef[]dnl
         /* New state.  Unlike in the C/C++ skeletons, the state is already
            pushed when we come here.  */
       case YYNEWSTATE:]b4_parse_trace_if([[
-        yycdebug ("Entering state " + yystate + "\n");
+        yycdebug ("Entering state " + yystate);
         if (0 < yydebug)
           yystack.print (yyDebugStream);]])[
 
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])
diff --git a/tests/local.at b/tests/local.at
index 20c7cd0d..307e341f 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -442,6 +442,12 @@ m4_define([AT_LANG_CASE],
 [m4_case(AT_LANG, $@)])
 
 
+# AT_LANG_MATCH(LANG1, IF-LANG1, LANG2, IF-LANG2, ..., DEFAULT)
+# ------------------------------------------------------------
+m4_define([AT_LANG_MATCH],
+[m4_bmatch(AT_LANG, $@)])
+
+
 # _AT_LANG_DISPATCH(LANG, MACRO, ARGS)
 # ------------------------------------
 # Call the specialization of MACRO for LANG with ARGS.  Complain if
@@ -818,6 +824,9 @@ m4_define([AT_MAIN_DEFINE(d)],
 # ------------------------------
 m4_copy([AT_DATA], [AT_DATA_GRAMMAR(java)])
 
+# No need to declare, it's part of the class interface.
+m4_define([AT_YYERROR_DECLARE(java)],        [])
+m4_define([AT_YYERROR_DECLARE_EXTERN(java)], [])
 
 # AT_JAVA_POSITION_DEFINE
 # -----------------------
-- 
2.25.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]