bison-patches
[Top][All Lists]
Advanced

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

[PATCH] Round the Java rough edges


From: Paolo Bonzini
Subject: [PATCH] Round the Java rough edges
Date: Thu, 08 Mar 2007 16:58:12 +0100
User-agent: Thunderbird 1.5.0.10 (Macintosh/20070221)

> I'm getting lost.  Is there any way to simplify this?  What about 
> something like the following:

Here is my implementation of "something similar".  I'll alternate your
suggestion with what I actually implemented.

> 1. Always define a YYLexer class.

Always define a public Lexer interface.

> 2. Provide "%code lexer" to add code to YYLexer.

If "%code lexer" is given, define a YYLexer class that includes the content
of "%code lexer".

> 3. Always provide a parser class constructor that takes an object of type 
> YYLexer as an argument.

Done (the type of course is the Lexer interface), but it is only public
if "%code lexer" is not used.  If "%code lexer" is not used, it is protected.

> (If the user wishes, he can easily write a 
> convenient second constructor that just constructs a YYLexer and passes it 
> to the first constructor.  Bison shouldn't provide this one automatically 
> since YYLexer might not be concrete.)

This second constructor instead is provided when "%code lexer" is used,
because YYLexer in this case is concrete, and it can use additional parameters
fetched from %lex-param directives.

yylex is always declared with no parameters, because %lex-param is used
for this case.

> 4. Provide "%define parser_class_modifiers" and "%define 
> lexer_class_modifiers" to specify abstract, interface, final, or other 
> modifiers on these classes.  Contains just public by default?

The "%code lexer" class is always private.  If your needs are more complex,
you probably want to define a full-fledged class rather than stick it into
the grammar.

For the parser, I'm still using "%define public" and "%define abstract"
because I don't like the long name "%define parser_class_modifiers", but
I'm open to suggestions for a better name.

The new interface is simpler (especially, adding locations to scanners
always uses the same interface) to the point that I could add four more
tests and still reduce the number of lines of code in java.at.  :-)

Ok to commit?

Paolo
2007-03-07  Paolo Bonzini  <address@hidden>

        * data/java.m4 (b4_single_class_if): Remove.
        (b4_abstract_if): Look at "%define abstract".
        (b4_lexer_if): New.
        (b4_union_name): Rename...
        (b4_yystype): ... to this.  Map to "%define stype".
        (b4_rhs_value, b4_parse_param_decl, b4_lex_param_decl,
        b4_maybe_throws): Fix quoting.
        (b4_lex_param_call): Move below to keep b4_*_param_decl close.
        * data/lalr1.java (Lexer interface): Always define.
        (Lexer interface within parser class): Remove.
        (YYLexer class): New, used when "%code lexer" is present.
        (constructor): When "%code lexer" is used, pass %lex-param
        to the lexer constructor.
        (yylex, yyparse): Remove %lex-param from method invocations
        (YYStack, yyaction, yyparse): Rename b4_union_name to b4_yystype.

        * doc/bison.texinfo (Java Bison Interface): Mention "%define
        abstract".  Rename "%define union_name" to "%define stype".
        Rename method names according to previous patch.
        (Java Scanner Interface): Describe "%code lexer" instead of
        "%pure-parser" and "%define single_class".
        (Java Differences): Mention "%code lexer".

        * tests/java.at (_AT_DATA_JAVA_CALC_Y): Remove final argument.
        Include scanner here, using macros from tests/local.at.
        (AT_DATA_CALC_Y): Remove final argument.
        (_AT_CHECK_JAVA_CALC): Likewise.
        (AT_CHECK_JAVA_CALC): Likewise.  Test all four combinations
        of %locations and %error-verbose.
        (main): Test with and without %lex-param.
        * tests/local.at (_AT_BISON_OPTION_PUSHDEFS): Push AT_LEXPARAM_IF.
        (AT_BISON_OPTION_POPDEFS): Pop it.
        

Index: data/java.m4
===================================================================
RCS file: /sources/bison/bison/data/java.m4,v
retrieving revision 1.2
diff -u -r1.2 java.m4
--- data/java.m4        30 Jan 2007 08:01:29 -0000      1.2
+++ data/java.m4        8 Mar 2007 15:09:27 -0000
@@ -38,17 +38,18 @@
 m4_define([b4_public_if],
 [b4_percent_define_flag_if([public], [$1], [$2])])
 
-# b4_single_class_if(TRUE, FALSE)
-# -------------------------------
-b4_percent_define_default([[single_class]], [[false]])
-m4_define([b4_single_class_if],
-[b4_percent_define_flag_if([single_class], [$1], [$2])])
-
 
 # b4_abstract_if(TRUE, FALSE)
 # ---------------------------
+b4_percent_define_default([[abstract]], [[false]])
 m4_define([b4_abstract_if],
-[b4_pure_if([$2], [b4_single_class_if([$2], [$1])])])
+[b4_percent_define_flag_if([abstract], [$1], [$2])])
+
+
+# b4_lexer_if(TRUE, FALSE)
+# ------------------------
+m4_define([b4_lexer_if],
+[b4_percent_code_ifdef([[lexer]], [$1], [$2])])
 
 
 # b4_identification
@@ -126,8 +127,8 @@
 ## Default values.  ##
 ## ---------------- ##
 
-m4_define([b4_union_name], [b4_percent_define_get([[union_name]])])
-b4_percent_define_default([[union_name]], [[Object]])])
+m4_define([b4_yystype], [b4_percent_define_get([[stype]])])
+b4_percent_define_default([[stype]], [[Object]])])
 
 m4_define_default([[b4_prefix]], [[YY]])])
 b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser])])
@@ -165,7 +166,7 @@
 # In this simple implementation, %token and %type have class names
 # between the angle brackets.
 m4_define([b4_rhs_value],
-[(m4_ifval([$3], [($3)])[](yystack.valueAt ($1-($2))))])
+[(m4_ifval($3, [($3)])[](yystack.valueAt ($1-($2))))])
 
 # b4_lhs_location()
 # -----------------
@@ -199,25 +200,14 @@
 m4_define([b4_lex_param_decl],
 [m4_ifset([b4_lex_param],
           [b4_remove_comma([$1],
-                          [m4_map([b4_lex_param_decl_1], [b4_lex_param])])],
+                          b4_param_decls(b4_lex_param))],
          [$1])])
 
-m4_define([b4_lex_param_decl_1], [, $1])
-m4_define([b4_remove_comma], [m4_ifval([$1], [$1, ], [])m4_cdr([m4_cdr($@)])])
+m4_define([b4_param_decls],
+         [m4_map([b4_param_decl], address@hidden)])
+m4_define([b4_param_decl], [, $1])
 
-
-
-# b4_lex_param_call
-# -------------------
-# Extra initialisations of the constructor.
-m4_define([b4_lex_param_call],
-          [m4_ifset([b4_lex_param],
-                   [b4_remove_comma([$1],
-                                    [b4_lex_param_calls(b4_lex_param)])],
-                   [$1])])
-m4_define([b4_lex_param_calls],
-         [m4_map([b4_lex_param_call_1], address@hidden)])
-m4_define([b4_lex_param_call_1], [, $2])
+m4_define([b4_remove_comma], [m4_ifval($1, [$1, ], [])m4_shiftn(2, $@)])
 
 
 
@@ -227,11 +217,22 @@
 m4_define([b4_parse_param_decl],
 [m4_ifset([b4_parse_param],
           [b4_remove_comma([$1],
-                          [m4_map([b4_parse_param_decl_1],
-                                  [b4_parse_param])])],
+                          b4_param_decls(b4_parse_param))],
          [$1])])
 
-m4_define([b4_parse_param_decl_1], [, $1])
+
+
+# b4_lex_param_call
+# -------------------
+# Delegating the lexer parameters to the lexer constructor.
+m4_define([b4_lex_param_call],
+          [m4_ifset([b4_lex_param],
+                   [b4_remove_comma([$1],
+                                    b4_param_calls(b4_lex_param))],
+                   [$1])])
+m4_define([b4_param_calls],
+         [m4_map([b4_param_call], address@hidden)])
+m4_define([b4_param_call], [, $2])
 
 
 
@@ -241,12 +242,15 @@
 m4_define([b4_parse_param_cons],
           [m4_ifset([b4_parse_param],
                    [b4_constructor_calls(b4_parse_param)])])
+
 m4_define([b4_constructor_calls],
          [m4_map([b4_constructor_call], address@hidden)])
 m4_define([b4_constructor_call],
          [this.$2 = $2;
          ])
 
+
+
 # b4_parse_param_vars
 # -------------------
 # Extra instance variables.
@@ -255,14 +259,17 @@
                    [
     /* User arguments.  */
 b4_var_decls(b4_parse_param)])])
+
 m4_define([b4_var_decls],
          [m4_map_sep([b4_var_decl], [
 ], address@hidden)])
 m4_define([b4_var_decl],
          [    protected final $1;])
 
+
+
 # b4_maybe_throws(THROWS)
 # -----------------------
 # Expand to either an empty string or "throws THROWS".
 m4_define([b4_maybe_throws],
-         [m4_ifval([$1], [throws $1])])
+         [m4_ifval($1, [throws $1])])
Index: data/lalr1.java
===================================================================
RCS file: /sources/bison/bison/data/lalr1.java,v
retrieving revision 1.3
diff -u -r1.3 lalr1.java
--- data/lalr1.java     27 Feb 2007 07:31:19 -0000      1.3
+++ data/lalr1.java     8 Mar 2007 15:09:27 -0000
@@ -103,7 +103,7 @@
       return new ]b4_location_type[ (rhs.locationAt (0).end);
   }]])
 
-  b4_pure_if([[/**
+  /**
    * Communication interface between the scanner and the Bison-generated
    * parser <tt>]b4_parser_class_name[</tt>.
    */
@@ -121,30 +121,15 @@
     /**
      * Method to retrieve the semantic value of the last scanned token.
      * @@return the semantic value of the last scanned token.  */
-    ]b4_union_name[ getLVal ();]], [[
-
-    /**
-     * A place where the scanner can store the beginning position of the
-     * last scanned token.  */
-    ]b4_locations_if([b4_position_type[ yystartpos;]])[
-
-    /**
-     * A place where the scanner can store the ending position of the last
-     * scanned token, i.e. the first position beyond the last scanned token.  
*/
-    ]b4_locations_if([b4_position_type[ yyendpos;]])[
+    ]b4_yystype[ getLVal ();]
 
     /**
-     * A place where the scanner can store the semantic value of the
-     * last scanned token.  */
-    protected ]b4_union_name[ yylval;]])
-
-    b4_single_class_if([], [[/**
      * Entry point for the scanner.  Returns the token identifier corresponding
      * to the next token and ]b4_pure_if([prepares to return], [stores])[
      * the semantic value]b4_locations_if([ and beginning/ending positions])[
      * of the token. 
      * @@return the token identifier corresponding to the next token. */
-    abstract int yylex (]b4_lex_param_decl) b4_maybe_throws([b4_lex_throws])[;
+    int yylex () ]b4_maybe_throws([b4_lex_throws])[;
 
     /**
      * Entry point for error reporting.  Emits an error
@@ -154,20 +139,35 @@
      * ]b4_locations_if([loc], [[The location of the element to which the
      *                error message is related]])[
      * @@param s The string for the error message.  */
-     abstract void yyerror (]b4_locations_if([b4_location_type[ loc, 
]])[String s);]])
-  b4_pure_if([}
+     void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s);]
+  }
 
-  /** The object doing lexical analysis for us.  */
-  private Lexer yylex;])
-  b4_parse_param_vars[
+  b4_lexer_if([[private final class YYLexer implements Lexer {
+]b4_percent_code_get([[lexer]])[
+  }
 
+  ]])[/** The object doing lexical analysis for us.  */
+  private Lexer yylex;
+  ]
+  b4_parse_param_vars
+
+b4_lexer_if([[
   /**
-   * Instantiates the Bison-generated parser.  ]b4_pure_if([
-   * @@param yylex The scanner that will supply tokens to the parser.])[
+   * Instantiates the Bison-generated parser.
    */
-  public ]b4_parser_class_name[ (]b4_parse_param_decl([b4_pure_if([Lexer 
yylex])])[) {
-    ]b4_pure_if(this.yylex = yylex;)
-    b4_parse_param_cons[
+  public ]b4_parser_class_name (b4_parse_param_decl([b4_lex_param_decl])[) {
+    this.yylex = new YYLexer(]b4_lex_param_call[);
+    ]b4_parse_param_cons[
+  }
+]])
+
+  /**
+   * Instantiates the Bison-generated parser.
+   * @@param yylex The scanner that will supply tokens to the parser.
+   */
+  b4_lexer_if([[protected]], [[public]]) b4_parser_class_name[ 
(]b4_parse_param_decl([[Lexer yylex]])[) {
+    this.yylex = yylex;
+    ]b4_parse_param_cons[
   }
 
   private java.io.PrintStream yyDebugStream = System.err;
@@ -199,19 +199,19 @@
    */
   public final void setDebugLevel(int level) { yydebug = level; }
 
-  ]b4_pure_if([[
-  private final int yylex (]b4_lex_param_decl) 
b4_maybe_throws([b4_lex_throws]) [{
-    return yylex.yylex (]b4_lex_param_call[);
+  private final int yylex () ]b4_maybe_throws([b4_lex_throws]) [{
+    return yylex.yylex ();
   }
   protected final void yyerror (]b4_locations_if([b4_location_type[ loc, 
]])[String s) {
     yylex.yyerror (]b4_locations_if([loc, ])[s);
-  }]])
-  b4_locations_if([
+  }
+
+  ]b4_locations_if([
   protected final void yyerror (String s) {
-    yyerror ((Location)null, s);
+    yylex.yyerror ((Location)null, s);
   }
   protected final void yyerror (]b4_position_type[ loc, String s) {
-    yyerror (new ]b4_location_type[ (loc), s);
+    yylex.yyerror (new ]b4_location_type[ (loc), s);
   }])
 
   [protected final void yycdebug (String s) {
@@ -222,12 +222,12 @@
   private final class YYStack {
     private int[] stateStack = new int[16];
     ]b4_locations_if([[private ]b4_location_type[[] locStack = new 
]b4_location_type[[16];]])[
-    private ]b4_union_name[[] valueStack = new ]b4_union_name[[16];
+    private ]b4_yystype[[] valueStack = new ]b4_yystype[[16];
 
     public int size = 16;
     public int height = -1;
     
-    public final void push (int state, ]b4_union_name[ value]dnl
+    public final void push (int state, ]b4_yystype[ value]dnl
                            b4_locations_if([, ]b4_location_type[ loc])[) {
       height++;
       if (size == height) 
@@ -240,7 +240,7 @@
          System.arraycopy (locStack, 0, newLocStack, 0, height);
          locStack = newLocStack;]])
          
-         b4_union_name[[] newValueStack = new ]b4_union_name[[size * 2];
+         b4_yystype[[] newValueStack = new ]b4_yystype[[size * 2];
          System.arraycopy (valueStack, 0, newValueStack, 0, height);
          valueStack = newValueStack;
 
@@ -273,7 +273,7 @@
       return locStack[height - i];
     }
 
-    ]])[public final ]b4_union_name[ valueAt (int i) {
+    ]])[public final ]b4_yystype[ valueAt (int i) {
       return valueStack[height - i];
     }
 
@@ -330,7 +330,7 @@
 
   private int yyaction (int yyn, YYStack yystack, int yylen)
   {
-    ]b4_union_name[ yyval;
+    ]b4_yystype[ yyval;
     ]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[
 
     /* If YYLEN is nonzero, implement the default value of the action:
@@ -410,7 +410,7 @@
   `--------------------------------*/
 
   private void yy_symbol_print (String s, int yytype,
-                                ]b4_union_name[ yyvaluep]dnl
+                                ]b4_yystype[ yyvaluep]dnl
                                 b4_locations_if([, Object yylocationp])[)
   {
     if (yydebug > 0)
@@ -452,7 +452,7 @@
     ]b4_location_type[ yyloc;])
 
     /// Semantic value of the lookahead.
-    b4_union_name[ yylval = null;
+    b4_yystype[ yylval = null;
 
     int yyresult;
 
@@ -497,13 +497,11 @@
         if (yychar == yyempty_)
           {
            yycdebug ("Reading a token: ");
-           yychar = yylex (]b4_lex_param_call[);]
-            b4_locations_if([
-           b4_pure_if([yylloc = new ]b4_location_type[(yylex.getStartPos (),
-                                                       yylex.getEndPos ());],
-                      [yylloc = new ]b4_location_type[(this.yystartpos,
-                                                       this.yyendpos);]);])
-            b4_pure_if([yylval = yylex.getLVal ()], [yylval = this.yylval]);[
+           yychar = yylex.yylex ();]
+            b4_locations_if([[
+           yylloc = new ]b4_location_type[(yylex.getStartPos (),
+                                           yylex.getEndPos ());]])
+            yylval = yylex.getLVal ();[
           }
     
         /* Convert token to internal form.  */
Index: doc/bison.texinfo
===================================================================
RCS file: /sources/bison/bison/doc/bison.texinfo,v
retrieving revision 1.229
diff address@hidden -u -r1.229 bison.texinfo
--- doc/bison.texinfo   2 Mar 2007 06:26:28 -0000       1.229
+++ doc/bison.texinfo   8 Mar 2007 15:38:32 -0000
@@ -8380,7 +8380,10 @@ @node Java Bison Interface
 of the @file{.java} file should match the name of the class in this
 case.
 
-All these files are documented using Javadoc.
+Similarly, a declaration @samp{%define "abstract"} will make your
+class abstract.
+
+You can create documentation for generated parsers using Javadoc.
 
 @node Java Semantic Values
 @subsection Java Semantic Values
@@ -8404,7 +8407,7 @@ @node Java Semantic Values
 For example, after the following declaration:
 
 @example
-%define "union_name" "ASTNode"
+%define "stype" "ASTNode"
 @end example
 
 @noindent
@@ -8483,7 +8486,7 @@ @node Java Parser Interface
 @code{false} otherwise.
 @end deftypemethod
 
address@hidden {YYParser} {boolean} yyrecovering ()
address@hidden {YYParser} {boolean} recovering ()
 During the syntactic analysis, return @code{true} if recovering
 from a syntax error.  @xref{Error Recovery}.
 @end deftypemethod
@@ -8510,33 +8513,39 @@ @node Java Parser Interface
 
 @node Java Scanner Interface
 @subsection Java Scanner Interface
address@hidden - prefix for yylex.
address@hidden - Pure interface to yylex
address@hidden - %code lexer
 @c - %lex-param
address@hidden - Lexer interface
 
-There are two possible ways to interface a Bison-generated Java parser
-with a scanner.
-
address@hidden pure parser, in Java
 Contrary to C parsers, Java parsers do not use global variables; the
 state of the parser is always local to an instance of the parser class.
-Therefore, all Java parsers are ``pure'' in the C sense.  The
address@hidden directive can still be used in Java, and it
-will control whether the lexer resides in a separate class than the
-Bison-generated parser (therefore, Bison generates a class that is
-``purely'' a parser), or in the same class.  The interface to the scanner
-is similar, though the two cases present a slightly different naming.
-
-For the @code{%pure-parser} case, the scanner implements an interface
-called @code{Lexer} and defined within the parser class (e.g.,
address@hidden  The constructor of the parser object accepts
-an object implementing the interface.  The interface specifies
-the following methods.
+Therefore, all Java parsers are ``pure'', and the @code{%pure-parser}
+directive does not do anything when used in Java.
+
+The scanner always resides in a separate class than the parser.
+Still, Java also two possible ways to interface a Bison-generated Java
+parser with a scanner, that is, the scanner may reside in a separate file
+than the Bison grammar, or in the same file.  The interface
+to the scanner is similar in the two cases.
+
+In the first case, where the scanner in the same file as the grammar, the
+scanner code has to be placed in @code{%code lexer} blocks.  If you want
+to pass parameters from the parser constructor to the scanner constructor,
+specify them with @code{%lex-param}; they are passed before
address@hidden to the constructor.
+
+In the second case, the scanner has to implement interface @code{Lexer},
+which is defined within the parser class (e.g., @code{YYParser.Lexer}).
+The constructor of the parser object will then accept an object
+implementing the interface; @code{%lex-param} is not used in this
+case.
 
address@hidden {Lexer} {void} error (Location @var{l}, String @var{m})
+In both cases, the scanner has to implement the following methods.
+
address@hidden {Lexer} {void} yyerror (Location @var{l}, String @var{m})
 As explained in @pxref{Java Parser Interface}, this method is defined
-by the user to emit an error message.  The first parameter is not used
-unless location tracking is active.  Its type can be changed using
+by the user to emit an error message.  The first parameter is omitted
+if location tracking is not active.  Its type can be changed using
 @samp{%define "location_type" "@var{class-name}".}
 @end deftypemethod
 
@@ -8549,9 +8558,9 @@ @node Java Scanner Interface
 
 @deftypemethod {Lexer} {Position} getStartPos ()
 @deftypemethodx {Lexer} {Position} getEndPos ()
-Return respectively the first position of the last token that yylex
-returned, and the first position beyond it.  These methods are not
-needed unless location tracking is active.
+Return respectively the first position of the last token that
address@hidden returned, and the first position beyond it.  These
+methods are not needed unless location tracking is active.
 
 The return type can be changed using @samp{%define "position_type"
 "@var{class-name}".}
@@ -8561,7 +8570,7 @@ @node Java Scanner Interface
 Return respectively the first position of the last token that yylex
 returned, and the first position beyond it.
 
-The return type can be changed using @samp{%define "union_name"
+The return type can be changed using @samp{%define "stype"
 "@var{class-name}".}
 @end deftypemethod
 
@@ -8599,19 +8608,10 @@ @node Java Scanner Interface
 Return respectively the first position of the last token that yylex
 returned, and the first position beyond it.
 
-The field's type can be changed using @samp{%define "union_name"
+The field's type can be changed using @samp{%define "stype"
 "@var{class-name}".}
 @end deftypecv
 
-By default the class generated for a non-pure Java parser is abstract,
-and the methods @code{yylex} and @code{yyerror} shall be placed in a
-subclass (possibly defined in the additional code section).  It is
-also possible, using the @code{%define "single_class"} declaration, to
-define the scanner in the same class as the parser; when this
-declaration is present, the class is not declared as abstract.
-In order to place the declarations for the scanner inside the
-parser class, you should use @code{%code} sections.
-
 @node Java Differences
 @subsection Differences between C/C++ and Java Grammars
 
@@ -8621,10 +8621,10 @@ @node Java Differences
 
 @itemize
 @item
-Since Java lacks a preprocessor, the @code{YYERROR}, @code{YYACCEPT},
+Java lacks a preprocessor, so the @code{YYERROR}, @code{YYACCEPT},
 @code{YYABORT} symbols (@pxref{Table of Symbols}) cannot obviously be
-macros.  Instead, they should be preceded in an action with
address@hidden  The actual definition of these symbols should be
+macros.  Instead, they should be preceded by @code{return} when they
+appear in an action.  The actual definition of these symbols is
 opaque to the Bison grammar, and it might change in the future.  The
 only meaningful operation that you can do, is to return them.
 
@@ -8636,19 +8636,25 @@ @node Java Differences
 
 @item
 The prolog declarations have a different meaning than in C/C++ code.
address@hidden @code
address@hidden %code
address@hidden imports} blocks are placed at the beginning of the Java
-source code.  They may include copyright notices.  For a @code{package}
-declarations, it is suggested to use @code{%define package} instead.
-
address@hidden blocks are placed inside the parser class.  If @code{%define
-single_class} is being used, the definitions of @code{yylex} and
address@hidden should be placed here.  Subroutines for the parser actions
-may be included in this kind of block.
address@hidden @asis
address@hidden @code{%code imports}
+blocks are placed at the beginning of the Java source code.  They may
+include copyright notices.  For a @code{package} declarations, it is
+suggested to use @code{%define package} instead.
+
address@hidden unqualified @code{%code}
+blocks are placed inside the parser class.
+
address@hidden @code{%code lexer}
+blocks, if specified, should include the implementation of the
+scanner.  If there is no such block, the scanner can be any class
+that implements the appropriate interface (see @pxref{Java Scanner
+Interface}).
address@hidden item
 
 Other @code{%code} blocks are not supported in Java parsers.
address@hidden table
+The epilogue has the same meaning as in C/C++ code and it can
+be used to define other classes used by the parser.
 @end itemize
 
 @c ================================================= FAQ
Index: tests/java.at
===================================================================
RCS file: /sources/bison/bison/tests/java.at,v
retrieving revision 1.2
diff -u -r1.2 java.at
--- tests/java.at       7 Feb 2007 17:03:10 -0000       1.2
+++ tests/java.at       8 Mar 2007 15:09:29 -0000
@@ -25,7 +25,7 @@
 # ------------------------- #
 
 
-# _AT_DATA_JAVA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES], [BISON-EPILOGUE])
+# _AT_DATA_JAVA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
 # ----------------------------------------------------------------------
 # Produce `calc.y'.  Don't call this macro directly, because it contains
 # some occurrences of `$1' etc. which will be interpreted by m4.  So
@@ -37,11 +37,12 @@
 AT_DATA([Calc.y],
 [[/* Infix notation calculator--calc */
 %language "Java"
-%name-prefix "Calc"]
+%name-prefix "Calc"
 %define parser_class_name "Calc"
 %define public
 
-$4[
+]$4[
+
 %code imports {
   import java.io.StreamTokenizer;
   import java.io.InputStream;
@@ -93,52 +94,130 @@
 | '!'                { $$ = new Integer (0); return YYERROR;                }
 | '-' error          { $$ = new Integer (0); return YYERROR;                }
 ;
+
+]AT_LEXPARAM_IF([[
+%code lexer {
+]],
+[[
 %%
+class CalcLexer implements Calc.Lexer {
+]])[
+  StreamTokenizer st;
 
-  class Position {
-    public int line;
+  public ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]]) (InputStream is)
+  {
+    st = new StreamTokenizer (new InputStreamReader (is));
+    st.resetSyntax ();
+    st.eolIsSignificant (true);
+    st.whitespaceChars (9, 9);
+    st.whitespaceChars (32, 32);
+    st.wordChars (48, 57);
+  }
+
+AT_LOCATION_IF([[
+  Position yystartpos;
+  Position yyendpos = new Position (1);
 
-    public Position ()
-    {
-      line = 0;
-    }
-
-    public Position (int l)
-    {
-      line = l;
-    }
-
-    public long getHashCode ()
-    {
-      return line;
-    }
-
-    public boolean equals (Position l)
-    {
-      return l.line == line;
-    }
-
-    public String toString ()
-    {
-      return Integer.toString (line);
-    }
-
-    public int lineno ()
-    {
-      return line;
-    }
+  public Position getStartPos() {
+    return yystartpos;
   }
 
-]$5
-])
+  public Position getEndPos() {
+    return yyendpos;
+  }
+
+  public void yyerror (Calc.Location l, String s)
+  {
+    if (l == null)
+      System.err.println (s);
+    else
+      System.err.println (l.begin + ": " + s);
+  }
+]], [[
+  public void yyerror (String s)
+  {
+    System.err.println (s); 
+  }
+]])[
+
+  Integer yylval;
+
+  public Object getLVal() {
+    return yylval;
+  }
+
+  public int yylex () throws IOException {
+    int ttype = st.nextToken ();
+    ]AT_LOCATION_IF([[yystartpos = yyendpos;]])[
+    if (ttype == st.TT_EOF)
+      return Calc.EOF;
+
+    else if (ttype == st.TT_EOL)
+      {
+        ]AT_LOCATION_IF([[yyendpos = new Position (yyendpos.lineno () + 1);]])[
+        return (int) '\n';
+      }
+
+    else if (ttype == st.TT_WORD)
+      {
+        yylval = new Integer (st.sval);
+        return Calc.NUM;
+      }
+
+    else
+      return st.ttype;
+  }
+
+
+]AT_LEXPARAM_IF([[
+};
+%%]], [[
+}]])
+
+[
+class Position {
+  public int line;
+
+  public Position ()
+  {
+    line = 0;
+  }
+
+  public Position (int l)
+  {
+    line = l;
+  }
+
+  public long getHashCode ()
+  {
+    return line;
+  }
+
+  public boolean equals (Position l)
+  {
+    return l.line == line;
+  }
+
+  public String toString ()
+  {
+    return Integer.toString (line);
+  }
+
+  public int lineno ()
+  {
+    return line;
+  }
+}
+
+]])
 ])# _AT_DATA_JAVA_CALC_Y
 
 
-# AT_DATA_CALC_Y([BISON-OPTIONS], [BISON-EPILOGUE])
+# AT_DATA_CALC_Y([BISON-OPTIONS])
 # -------------------------------------------------
 # Produce `calc.y'.
 m4_define([AT_DATA_JAVA_CALC_Y],
-[_AT_DATA_JAVA_CALC_Y($[1], $[2], $[3], [$1], [$2])
+[_AT_DATA_JAVA_CALC_Y($[1], $[2], $[3], [$1])
 ])
 
 
@@ -196,7 +275,7 @@
 AT_CHECK([cat stderr], 0, [expout])
 ])
 
-# _AT_CHECK_JAVA_CALC([BISON-DIRECTIVES], [BISON-CODE], [BISON-EPILOGUE])
+# _AT_CHECK_JAVA_CALC([BISON-DIRECTIVES], [BISON-CODE])
 # -----------------------------------------------------------------------
 # Start a testing chunk which compiles `calc' grammar with
 # BISON-DIRECTIVES, and performs several tests over the parser.
@@ -209,7 +288,7 @@
 AT_DATA_JAVA_CALC_Y([$1
 %code {
 $2
-}], [$3])
+}])
 
 AT_CHECK([bison -o Calc.java Calc.y])
 AT_JAVA_COMPILE([Calc.java])
@@ -288,14 +367,16 @@
 ])# _AT_CHECK_JAVA_CALC
 
 
-# AT_CHECK_JAVA_CALC([BISON-DIRECTIVES], [BISON-EPILOGUE])
+# AT_CHECK_JAVA_CALC([BISON-DIRECTIVES])
 # --------------------------------------------------------
 # Start a testing chunk which compiles `calc' grammar with
 # BISON-DIRECTIVES, and performs several tests over the parser.
 # Run the test with and without %error-verbose.
 m4_define([AT_CHECK_JAVA_CALC],
-[_AT_CHECK_JAVA_CALC([$1], [$2], [$3])
-_AT_CHECK_JAVA_CALC([%error-verbose $1], [$2], [$3])
+[_AT_CHECK_JAVA_CALC([$1], [$2])
+_AT_CHECK_JAVA_CALC([%error-verbose $1], [$2])
+_AT_CHECK_JAVA_CALC([%locations $1], [$2])
+_AT_CHECK_JAVA_CALC([%error-verbose %locations $1], [$2])
 ])# AT_CHECK_JAVA_CALC
 
 
@@ -303,113 +384,18 @@
 # Simple LALR Calculator.  #
 # ------------------------ #
 
-dnl AT_CHECK_JAVA_CALC([], [])
-
-AT_CHECK_JAVA_CALC([%define single_class %locations], [[
-  StreamTokenizer st;
-
-  public Calc (InputStream is)
-  {
-    Reader r = new InputStreamReader (is);
-    st = new StreamTokenizer(r);
-    st.resetSyntax ();
-    st.eolIsSignificant (true);
-    st.whitespaceChars (9, 9);
-    st.whitespaceChars (32, 32);
-    st.wordChars (48, 57);
-
-    yyendpos = new Position (1);
-  }
-
-  public int yylex () throws IOException {
-    int ttype = st.nextToken ();
-    yystartpos = yyendpos;
-    if (ttype == st.TT_EOF)
-      return EOF;
-
-    else if (ttype == st.TT_EOL)
-      {
-        yyendpos = new Position (yyendpos.lineno () + 1);
-        return (int) '\n';
-      }
-
-    else if (ttype == st.TT_WORD)
-      {
-        yylval = new Integer (st.sval);
-        return NUM;
-      }
-
-    else
-      return st.ttype;
-  }
-
-  public void yyerror (Location l, String s)
-  {
-    if (l == null)
-      System.err.println (s);
-    else
-      System.err.println (l.begin + ": " + s);
-  }
-
-  public static void main (String args[]) throws IOException
-  {
-    new Calc (System.in).parse ();
-  }
-]])
-
-AT_CHECK_JAVA_CALC([%pure-parser], [[
+AT_CHECK_JAVA_CALC([], [[
   public static void main (String args[]) throws IOException
   {
     CalcLexer l = new CalcLexer (System.in);
     Calc p = new Calc (l);
     p.parse ();
   }
-]], [[
-class CalcLexer implements Calc.Lexer {
-  Integer yylval;
-
-  StreamTokenizer st;
-  
-  public Object getLVal ()
-  {
-    return yylval;
-  }
-  
-  public CalcLexer (InputStream is)
-  {
-    Reader r = new InputStreamReader (is);
-    st = new StreamTokenizer(r);
-    st.resetSyntax ();
-    st.eolIsSignificant (true);
-    st.whitespaceChars (9, 9);
-    st.whitespaceChars (32, 32);
-    st.wordChars (48, 57);
-  }
-  
-  public int yylex () throws IOException {
-    int ttype = st.nextToken ();
-    if (ttype == st.TT_EOF)
-      return Calc.EOF;
-        
-    else if (ttype == st.TT_EOL)
-      return (int) '\n';
-        
-    else if (ttype == st.TT_WORD)
-      {
-        yylval = new Integer (st.sval);
-        return Calc.NUM;
-      }
-        
-    else
-      return st.ttype;
-  }
+]])
 
-  
-  public void yyerror (String s)
+AT_CHECK_JAVA_CALC([%lex-param { InputStream is } ], [[
+  public static void main (String args[]) throws IOException
   {
-    System.err.println (s); 
+    new Calc (System.in).parse ();
   }
-}
 ]])
-
-dnl AT_CHECK_JAVA_CALC([%pure-parser %locations], [])
Index: tests/local.at
===================================================================
RCS file: /sources/bison/bison/tests/local.at,v
retrieving revision 1.25
diff -u -r1.25 local.at
--- tests/local.at      17 Jan 2007 08:36:07 -0000      1.25
+++ tests/local.at      8 Mar 2007 15:09:29 -0000
@@ -52,6 +52,8 @@
 # Using yacc.c?
 m4_pushdef([AT_YACC_IF],
 [m4_bmatch([$3], [%language\|%glr-parser\|%skeleton], [$2], [$1])])
+m4_pushdef([AT_LEXPARAM_IF],
+[m4_bmatch([$3], [%lex-param], [$1], [$2])])
 m4_pushdef([AT_PARAM_IF],
 [m4_bmatch([$3], [%parse-param], [$1], [$2])])
 m4_pushdef([AT_LOCATION_IF],
@@ -128,6 +130,7 @@
 m4_popdef([AT_PURE_AND_LOC_IF])
 m4_popdef([AT_LOCATION_IF])
 m4_popdef([AT_PARAM_IF])
+m4_popdef([AT_LEXPARAM_IF])
 m4_popdef([AT_YACC_IF])
 m4_popdef([AT_GLR_IF])
 m4_popdef([AT_SKEL_CC_IF])

reply via email to

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