2007-03-07 Paolo Bonzini <bonzini@gnu.org>

* 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.
This commit is contained in:
Paolo Bonzini
2007-03-09 09:13:43 +00:00
parent 7cfc1553a3
commit 01b477c6b6
6 changed files with 311 additions and 276 deletions

View File

@@ -1,3 +1,38 @@
2007-03-07 Paolo Bonzini <bonzini@gnu.org>
* 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.
2007-03-07 Juan Manuel Guerrero <juan.guerrero@gmx.de> 2007-03-07 Juan Manuel Guerrero <juan.guerrero@gmx.de>
DJGPP spefic issue. Inhibit the use of disallowed characters for DJGPP spefic issue. Inhibit the use of disallowed characters for

View File

@@ -38,17 +38,18 @@ b4_percent_define_default([[public]], [[false]])
m4_define([b4_public_if], m4_define([b4_public_if],
[b4_percent_define_flag_if([public], [$1], [$2])]) [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_abstract_if(TRUE, FALSE)
# --------------------------- # ---------------------------
b4_percent_define_default([[abstract]], [[false]])
m4_define([b4_abstract_if], 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 # b4_identification
@@ -126,8 +127,8 @@ m4_define([b4_case], [ case $1:
## Default values. ## ## Default values. ##
## ---------------- ## ## ---------------- ##
m4_define([b4_union_name], [b4_percent_define_get([[union_name]])]) m4_define([b4_yystype], [b4_percent_define_get([[stype]])])
b4_percent_define_default([[union_name]], [[Object]])]) b4_percent_define_default([[stype]], [[Object]])])
m4_define_default([[b4_prefix]], [[YY]])]) m4_define_default([[b4_prefix]], [[YY]])])
b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser])]) b4_percent_define_default([[parser_class_name]], [b4_prefix[]Parser])])
@@ -165,7 +166,7 @@ m4_define([b4_lhs_value], [yyval])
# In this simple implementation, %token and %type have class names # In this simple implementation, %token and %type have class names
# between the angle brackets. # between the angle brackets.
m4_define([b4_rhs_value], m4_define([b4_rhs_value],
[(m4_ifval([$3], [($3)])[](yystack.valueAt ($1-($2))))]) [(m4_ifval($3, [($3)])[](yystack.valueAt ($1-($2))))])
# b4_lhs_location() # b4_lhs_location()
# ----------------- # -----------------
@@ -199,25 +200,14 @@ m4_define([b4_parse_param], b4_parse_param))
m4_define([b4_lex_param_decl], m4_define([b4_lex_param_decl],
[m4_ifset([b4_lex_param], [m4_ifset([b4_lex_param],
[b4_remove_comma([$1], [b4_remove_comma([$1],
[m4_map([b4_lex_param_decl_1], [b4_lex_param])])], b4_param_decls(b4_lex_param))],
[$1])]) [$1])])
m4_define([b4_lex_param_decl_1], [, $1]) m4_define([b4_param_decls],
m4_define([b4_remove_comma], [m4_ifval([$1], [$1, ], [])m4_cdr([m4_cdr($@)])]) [m4_map([b4_param_decl], [$@])])
m4_define([b4_param_decl], [, $1])
m4_define([b4_remove_comma], [m4_ifval($1, [$1, ], [])m4_shiftn(2, $@)])
# 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], [$@])])
m4_define([b4_lex_param_call_1], [, $2])
@@ -227,11 +217,22 @@ m4_define([b4_lex_param_call_1], [, $2])
m4_define([b4_parse_param_decl], m4_define([b4_parse_param_decl],
[m4_ifset([b4_parse_param], [m4_ifset([b4_parse_param],
[b4_remove_comma([$1], [b4_remove_comma([$1],
[m4_map([b4_parse_param_decl_1], b4_param_decls(b4_parse_param))],
[b4_parse_param])])],
[$1])]) [$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], [$@])])
m4_define([b4_param_call], [, $2])
@@ -241,12 +242,15 @@ m4_define([b4_parse_param_decl_1], [, $1])
m4_define([b4_parse_param_cons], m4_define([b4_parse_param_cons],
[m4_ifset([b4_parse_param], [m4_ifset([b4_parse_param],
[b4_constructor_calls(b4_parse_param)])]) [b4_constructor_calls(b4_parse_param)])])
m4_define([b4_constructor_calls], m4_define([b4_constructor_calls],
[m4_map([b4_constructor_call], [$@])]) [m4_map([b4_constructor_call], [$@])])
m4_define([b4_constructor_call], m4_define([b4_constructor_call],
[this.$2 = $2; [this.$2 = $2;
]) ])
# b4_parse_param_vars # b4_parse_param_vars
# ------------------- # -------------------
# Extra instance variables. # Extra instance variables.
@@ -255,14 +259,17 @@ m4_define([b4_parse_param_vars],
[ [
/* User arguments. */ /* User arguments. */
b4_var_decls(b4_parse_param)])]) b4_var_decls(b4_parse_param)])])
m4_define([b4_var_decls], m4_define([b4_var_decls],
[m4_map_sep([b4_var_decl], [ [m4_map_sep([b4_var_decl], [
], [$@])]) ], [$@])])
m4_define([b4_var_decl], m4_define([b4_var_decl],
[ protected final $1;]) [ protected final $1;])
# b4_maybe_throws(THROWS) # b4_maybe_throws(THROWS)
# ----------------------- # -----------------------
# Expand to either an empty string or "throws THROWS". # Expand to either an empty string or "throws THROWS".
m4_define([b4_maybe_throws], m4_define([b4_maybe_throws],
[m4_ifval([$1], [throws $1])]) [m4_ifval($1, [throws $1])])

View File

@@ -103,7 +103,7 @@ b4_token_enums(b4_tokens)
return new ]b4_location_type[ (rhs.locationAt (0).end); return new ]b4_location_type[ (rhs.locationAt (0).end);
}]]) }]])
b4_pure_if([[/** /**
* Communication interface between the scanner and the Bison-generated * Communication interface between the scanner and the Bison-generated
* parser <tt>]b4_parser_class_name[</tt>. * parser <tt>]b4_parser_class_name[</tt>.
*/ */
@@ -121,30 +121,15 @@ b4_token_enums(b4_tokens)
/** /**
* Method to retrieve the semantic value of the last scanned token. * Method to retrieve the semantic value of the last scanned token.
* @@return the semantic value of the last scanned token. */ * @@return the semantic value of the last scanned token. */
]b4_union_name[ getLVal ();]], [[ ]b4_yystype[ 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;]])[
/**
* 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 * Entry point for the scanner. Returns the token identifier corresponding
* to the next token and ]b4_pure_if([prepares to return], [stores])[ * to the next token and ]b4_pure_if([prepares to return], [stores])[
* the semantic value]b4_locations_if([ and beginning/ending positions])[ * the semantic value]b4_locations_if([ and beginning/ending positions])[
* of the token. * of the token.
* @@return the token identifier corresponding to the next 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 * Entry point for error reporting. Emits an error
@@ -154,20 +139,35 @@ b4_token_enums(b4_tokens)
* ]b4_locations_if([loc], [[The location of the element to which the * ]b4_locations_if([loc], [[The location of the element to which the
* error message is related]])[ * error message is related]])[
* @@param s The string for the error message. */ * @@param s The string for the error message. */
abstract void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s);]]) void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s);]
b4_pure_if([} }
/** The object doing lexical analysis for us. */ b4_lexer_if([[private class YYLexer implements Lexer {
private Lexer yylex;]) ]b4_percent_code_get([[lexer]])[
b4_parse_param_vars[ }
]])[/** The object doing lexical analysis for us. */
private Lexer yylexer;
]
b4_parse_param_vars
b4_lexer_if([[
/**
* Instantiates the Bison-generated parser.
*/
public ]b4_parser_class_name (b4_parse_param_decl([b4_lex_param_decl])[) {
this.yylexer = new YYLexer(]b4_lex_param_call[);
]b4_parse_param_cons[
}
]])
/** /**
* Instantiates the Bison-generated parser. ]b4_pure_if([ * Instantiates the Bison-generated parser.
* @@param yylex The scanner that will supply tokens to the parser.])[ * @@param yylex The scanner that will supply tokens to the parser.
*/ */
public ]b4_parser_class_name[ (]b4_parse_param_decl([b4_pure_if([Lexer yylex])])[) { b4_lexer_if([[protected]], [[public]]) b4_parser_class_name[ (]b4_parse_param_decl([[Lexer yylexer]])[) {
]b4_pure_if(this.yylex = yylex;) this.yylexer = yylexer;
b4_parse_param_cons[ ]b4_parse_param_cons[
} }
private java.io.PrintStream yyDebugStream = System.err; private java.io.PrintStream yyDebugStream = System.err;
@@ -199,19 +199,19 @@ b4_token_enums(b4_tokens)
*/ */
public final void setDebugLevel(int level) { yydebug = level; } public final void setDebugLevel(int level) { yydebug = level; }
]b4_pure_if([[ private final int yylex () ]b4_maybe_throws([b4_lex_throws]) [{
private final int yylex (]b4_lex_param_decl) b4_maybe_throws([b4_lex_throws]) [{ return yylexer.yylex ();
return yylex.yylex (]b4_lex_param_call[);
} }
protected final void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s) { protected final void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s) {
yylex.yyerror (]b4_locations_if([loc, ])[s); yylexer.yyerror (]b4_locations_if([loc, ])[s);
}]]) }
b4_locations_if([
]b4_locations_if([
protected final void yyerror (String s) { protected final void yyerror (String s) {
yyerror ((Location)null, s); yylexer.yyerror ((Location)null, s);
} }
protected final void yyerror (]b4_position_type[ loc, String s) { protected final void yyerror (]b4_position_type[ loc, String s) {
yyerror (new ]b4_location_type[ (loc), s); yylexer.yyerror (new ]b4_location_type[ (loc), s);
}]) }])
[protected final void yycdebug (String s) { [protected final void yycdebug (String s) {
@@ -222,12 +222,12 @@ b4_token_enums(b4_tokens)
private final class YYStack { private final class YYStack {
private int[] stateStack = new int[16]; private int[] stateStack = new int[16];
]b4_locations_if([[private ]b4_location_type[[] locStack = new ]b4_location_type[[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 size = 16;
public int height = -1; 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])[) { b4_locations_if([, ]b4_location_type[ loc])[) {
height++; height++;
if (size == height) if (size == height)
@@ -240,7 +240,7 @@ b4_token_enums(b4_tokens)
System.arraycopy (locStack, 0, newLocStack, 0, height); System.arraycopy (locStack, 0, newLocStack, 0, height);
locStack = newLocStack;]]) 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); System.arraycopy (valueStack, 0, newValueStack, 0, height);
valueStack = newValueStack; valueStack = newValueStack;
@@ -273,7 +273,7 @@ b4_token_enums(b4_tokens)
return locStack[height - i]; return locStack[height - i];
} }
]])[public final ]b4_union_name[ valueAt (int i) { ]])[public final ]b4_yystype[ valueAt (int i) {
return valueStack[height - i]; return valueStack[height - i];
} }
@@ -330,7 +330,7 @@ b4_token_enums(b4_tokens)
private int yyaction (int yyn, YYStack yystack, int yylen) 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);]])[ ]b4_locations_if([b4_location_type[ yyloc = yylloc (yystack, yylen);]])[
/* If YYLEN is nonzero, implement the default value of the action: /* If YYLEN is nonzero, implement the default value of the action:
@@ -410,7 +410,7 @@ b4_token_enums(b4_tokens)
`--------------------------------*/ `--------------------------------*/
private void yy_symbol_print (String s, int yytype, private void yy_symbol_print (String s, int yytype,
]b4_union_name[ yyvaluep]dnl ]b4_yystype[ yyvaluep]dnl
b4_locations_if([, Object yylocationp])[) b4_locations_if([, Object yylocationp])[)
{ {
if (yydebug > 0) if (yydebug > 0)
@@ -452,7 +452,7 @@ b4_token_enums(b4_tokens)
]b4_location_type[ yyloc;]) ]b4_location_type[ yyloc;])
/// Semantic value of the lookahead. /// Semantic value of the lookahead.
b4_union_name[ yylval = null; b4_yystype[ yylval = null;
int yyresult; int yyresult;
@@ -497,13 +497,11 @@ m4_popdef([b4_at_dollar])])dnl
if (yychar == yyempty_) if (yychar == yyempty_)
{ {
yycdebug ("Reading a token: "); yycdebug ("Reading a token: ");
yychar = yylex (]b4_lex_param_call[);] yychar = yylex ();]
b4_locations_if([ b4_locations_if([[
b4_pure_if([yylloc = new ]b4_location_type[(yylex.getStartPos (), yylloc = new ]b4_location_type[(yylexer.getStartPos (),
yylex.getEndPos ());], yylexer.getEndPos ());]])
[yylloc = new ]b4_location_type[(this.yystartpos, yylval = yylexer.getLVal ();[
this.yyendpos);]);])
b4_pure_if([yylval = yylex.getLVal ()], [yylval = this.yylval]);[
} }
/* Convert token to internal form. */ /* Convert token to internal form. */

View File

@@ -8380,7 +8380,10 @@ Remember that, according to the Java language specification, the name
of the @file{.java} file should match the name of the class in this of the @file{.java} file should match the name of the class in this
case. 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 @node Java Semantic Values
@subsection Java Semantic Values @subsection Java Semantic Values
@@ -8404,7 +8407,7 @@ superclass of all the semantic values using the @samp{%define} directive.
For example, after the following declaration: For example, after the following declaration:
@example @example
%define "union_name" "ASTNode" %define "stype" "ASTNode"
@end example @end example
@noindent @noindent
@@ -8483,7 +8486,7 @@ Run the syntactic analysis, and return @code{true} on success,
@code{false} otherwise. @code{false} otherwise.
@end deftypemethod @end deftypemethod
@deftypemethod {YYParser} {boolean} yyrecovering () @deftypemethod {YYParser} {boolean} recovering ()
During the syntactic analysis, return @code{true} if recovering During the syntactic analysis, return @code{true} if recovering
from a syntax error. @xref{Error Recovery}. from a syntax error. @xref{Error Recovery}.
@end deftypemethod @end deftypemethod
@@ -8510,33 +8513,39 @@ Interface}); the parser uses it to report a parser error occurring at
@node Java Scanner Interface @node Java Scanner Interface
@subsection Java Scanner Interface @subsection Java Scanner Interface
@c - prefix for yylex. @c - %code lexer
@c - Pure interface to yylex
@c - %lex-param @c - %lex-param
@c - Lexer interface
There are two possible ways to interface a Bison-generated Java parser
with a scanner.
@cindex pure parser, in Java
Contrary to C parsers, Java parsers do not use global variables; the 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. 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 Therefore, all Java parsers are ``pure'', and the @code{%pure-parser}
@code{%pure-parser} directive can still be used in Java, and it directive does not do anything when used in Java.
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 The scanner always resides in a separate class than the parser.
called @code{Lexer} and defined within the parser class (e.g., Still, Java also two possible ways to interface a Bison-generated Java
@code{YYParser.Lexer}. The constructor of the parser object accepts parser with a scanner, that is, the scanner may reside in a separate file
an object implementing the interface. The interface specifies than the Bison grammar, or in the same file. The interface
the following methods. to the scanner is similar in the two cases.
@deftypemethod {Lexer} {void} error (Location @var{l}, String @var{m}) 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
@code{%parse-param}s 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.
In both cases, the scanner has to implement the following methods.
@deftypemethod {Lexer} {void} yyerror (Location @var{l}, String @var{m})
As explained in @pxref{Java Parser Interface}, this method is defined 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 by the user to emit an error message. The first parameter is omitted
unless location tracking is active. Its type can be changed using if location tracking is not active. Its type can be changed using
@samp{%define "location_type" "@var{class-name}".} @samp{%define "location_type" "@var{class-name}".}
@end deftypemethod @end deftypemethod
@@ -8549,9 +8558,9 @@ interface. Invocations of @samp{%lex-param @{@var{type1}
@deftypemethod {Lexer} {Position} getStartPos () @deftypemethod {Lexer} {Position} getStartPos ()
@deftypemethodx {Lexer} {Position} getEndPos () @deftypemethodx {Lexer} {Position} getEndPos ()
Return respectively the first position of the last token that yylex Return respectively the first position of the last token that
returned, and the first position beyond it. These methods are not @code{yylex} returned, and the first position beyond it. These
needed unless location tracking is active. methods are not needed unless location tracking is active.
The return type can be changed using @samp{%define "position_type" The return type can be changed using @samp{%define "position_type"
"@var{class-name}".} "@var{class-name}".}
@@ -8561,7 +8570,7 @@ The return type can be changed using @samp{%define "position_type"
Return respectively the first position of the last token that yylex Return respectively the first position of the last token that yylex
returned, and the first position beyond it. 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}".} "@var{class-name}".}
@end deftypemethod @end deftypemethod
@@ -8599,19 +8608,10 @@ The field's type can be changed using @samp{%define "position_type"
Return respectively the first position of the last token that yylex Return respectively the first position of the last token that yylex
returned, and the first position beyond it. 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}".} "@var{class-name}".}
@end deftypecv @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 @node Java Differences
@subsection Differences between C/C++ and Java Grammars @subsection Differences between C/C++ and Java Grammars
@@ -8621,10 +8621,10 @@ section summarizes this differences.
@itemize @itemize
@item @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 @code{YYABORT} symbols (@pxref{Table of Symbols}) cannot obviously be
macros. Instead, they should be preceded in an action with macros. Instead, they should be preceded by @code{return} when they
@code{return}. The actual definition of these symbols should be appear in an action. The actual definition of these symbols is
opaque to the Bison grammar, and it might change in the future. The opaque to the Bison grammar, and it might change in the future. The
only meaningful operation that you can do, is to return them. only meaningful operation that you can do, is to return them.
@@ -8636,19 +8636,25 @@ corresponds to these C macros.}.
@item @item
The prolog declarations have a different meaning than in C/C++ code. The prolog declarations have a different meaning than in C/C++ code.
@table @code @table @asis
@item %code @item @code{%code imports}
@code{%code imports} blocks are placed at the beginning of the Java blocks are placed at the beginning of the Java source code. They may
source code. They may include copyright notices. For a @code{package} include copyright notices. For a @code{package} declarations, it is
declarations, it is suggested to use @code{%define package} instead. suggested to use @code{%define package} instead.
@code{%code} blocks are placed inside the parser class. If @code{%define @item unqualified @code{%code}
single_class} is being used, the definitions of @code{yylex} and blocks are placed inside the parser class.
@code{yyerror} should be placed here. Subroutines for the parser actions
may be included in this kind of block. @item @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}).
@end item
Other @code{%code} blocks are not supported in Java parsers. Other @code{%code} blocks are not supported in Java parsers.
@end 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 @end itemize
@c ================================================= FAQ @c ================================================= FAQ

View File

@@ -25,7 +25,7 @@ AT_BANNER([[Java Calculator.]])
# ------------------------- # # ------------------------- #
# _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 # Produce `calc.y'. Don't call this macro directly, because it contains
# some occurrences of `$1' etc. which will be interpreted by m4. So # some occurrences of `$1' etc. which will be interpreted by m4. So
@@ -37,11 +37,12 @@ m4_define([_AT_DATA_JAVA_CALC_Y],
AT_DATA([Calc.y], AT_DATA([Calc.y],
[[/* Infix notation calculator--calc */ [[/* Infix notation calculator--calc */
%language "Java" %language "Java"
%name-prefix "Calc"] %name-prefix "Calc"
%define parser_class_name "Calc" %define parser_class_name "Calc"
%define public %define public
$4[ ]$4[
%code imports { %code imports {
import java.io.StreamTokenizer; import java.io.StreamTokenizer;
import java.io.InputStream; import java.io.InputStream;
@@ -93,52 +94,130 @@ exp:
| '!' { $$ = new Integer (0); return YYERROR; } | '!' { $$ = new Integer (0); return YYERROR; }
| '-' error { $$ = 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 ]AT_LEXPARAM_IF([[YYLexer]], [[CalcLexer]]) (InputStream is)
public int line; {
st = new StreamTokenizer (new InputStreamReader (is));
public Position () st.resetSyntax ();
{ st.eolIsSignificant (true);
line = 0; st.whitespaceChars (9, 9);
} st.whitespaceChars (32, 32);
st.wordChars (48, 57);
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;
}
} }
]$5 AT_LOCATION_IF([[
]) Position yystartpos;
Position yyendpos = new Position (1);
public Position getStartPos() {
return yystartpos;
}
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_JAVA_CALC_Y
# AT_DATA_CALC_Y([BISON-OPTIONS], [BISON-EPILOGUE]) # AT_DATA_CALC_Y([BISON-OPTIONS])
# ------------------------------------------------- # -------------------------------------------------
# Produce `calc.y'. # Produce `calc.y'.
m4_define([AT_DATA_JAVA_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 @@ mv at-expout expout]])
AT_CHECK([cat stderr], 0, [expout]) 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 # Start a testing chunk which compiles `calc' grammar with
# BISON-DIRECTIVES, and performs several tests over the parser. # BISON-DIRECTIVES, and performs several tests over the parser.
@@ -209,7 +288,7 @@ AT_BISON_OPTION_PUSHDEFS([$1])
AT_DATA_JAVA_CALC_Y([$1 AT_DATA_JAVA_CALC_Y([$1
%code { %code {
$2 $2
}], [$3]) }])
AT_CHECK([bison -o Calc.java Calc.y]) AT_CHECK([bison -o Calc.java Calc.y])
AT_JAVA_COMPILE([Calc.java]) AT_JAVA_COMPILE([Calc.java])
@@ -288,14 +367,16 @@ AT_CLEANUP
])# _AT_CHECK_JAVA_CALC ])# _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 # Start a testing chunk which compiles `calc' grammar with
# BISON-DIRECTIVES, and performs several tests over the parser. # BISON-DIRECTIVES, and performs several tests over the parser.
# Run the test with and without %error-verbose. # Run the test with and without %error-verbose.
m4_define([AT_CHECK_JAVA_CALC], m4_define([AT_CHECK_JAVA_CALC],
[_AT_CHECK_JAVA_CALC([$1], [$2], [$3]) [_AT_CHECK_JAVA_CALC([$1], [$2])
_AT_CHECK_JAVA_CALC([%error-verbose $1], [$2], [$3]) _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 ])# AT_CHECK_JAVA_CALC
@@ -303,113 +384,18 @@ _AT_CHECK_JAVA_CALC([%error-verbose $1], [$2], [$3])
# Simple LALR Calculator. # # Simple LALR Calculator. #
# ------------------------ # # ------------------------ #
dnl AT_CHECK_JAVA_CALC([], []) 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], [[
public static void main (String args[]) throws IOException public static void main (String args[]) throws IOException
{ {
CalcLexer l = new CalcLexer (System.in); CalcLexer l = new CalcLexer (System.in);
Calc p = new Calc (l); Calc p = new Calc (l);
p.parse (); 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)
{
System.err.println (s);
}
}
]]) ]])
dnl AT_CHECK_JAVA_CALC([%pure-parser %locations], []) AT_CHECK_JAVA_CALC([%lex-param { InputStream is } ], [[
public static void main (String args[]) throws IOException
{
new Calc (System.in).parse ();
}
]])

View File

@@ -52,6 +52,8 @@ m4_pushdef([AT_GLR_CC_IF],
# Using yacc.c? # Using yacc.c?
m4_pushdef([AT_YACC_IF], m4_pushdef([AT_YACC_IF],
[m4_bmatch([$3], [%language\|%glr-parser\|%skeleton], [$2], [$1])]) [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_pushdef([AT_PARAM_IF],
[m4_bmatch([$3], [%parse-param], [$1], [$2])]) [m4_bmatch([$3], [%parse-param], [$1], [$2])])
m4_pushdef([AT_LOCATION_IF], m4_pushdef([AT_LOCATION_IF],
@@ -128,6 +130,7 @@ m4_popdef([AT_GLR_OR_PARAM_IF])
m4_popdef([AT_PURE_AND_LOC_IF]) m4_popdef([AT_PURE_AND_LOC_IF])
m4_popdef([AT_LOCATION_IF]) m4_popdef([AT_LOCATION_IF])
m4_popdef([AT_PARAM_IF]) m4_popdef([AT_PARAM_IF])
m4_popdef([AT_LEXPARAM_IF])
m4_popdef([AT_YACC_IF]) m4_popdef([AT_YACC_IF])
m4_popdef([AT_GLR_IF]) m4_popdef([AT_GLR_IF])
m4_popdef([AT_SKEL_CC_IF]) m4_popdef([AT_SKEL_CC_IF])