From 01b477c6b62a778bafec7b7eec178da39d5258f4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 9 Mar 2007 09:13:43 +0000 Subject: [PATCH] 2007-03-07 Paolo Bonzini * 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. --- ChangeLog | 35 ++++++ data/java.m4 | 67 +++++++----- data/lalr1.java | 98 ++++++++--------- doc/bison.texinfo | 110 ++++++++++--------- tests/java.at | 274 ++++++++++++++++++++++------------------------ tests/local.at | 3 + 6 files changed, 311 insertions(+), 276 deletions(-) diff --git a/ChangeLog b/ChangeLog index f00768ad..ef479356 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2007-03-07 Paolo Bonzini + + * 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 DJGPP spefic issue. Inhibit the use of disallowed characters for diff --git a/data/java.m4 b/data/java.m4 index 38820f0d..4fd76258 100644 --- a/data/java.m4 +++ b/data/java.m4 @@ -38,17 +38,18 @@ b4_percent_define_default([[public]], [[false]]) 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 @@ m4_define([b4_case], [ case $1: ## 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 @@ m4_define([b4_lhs_value], [yyval]) # 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_parse_param], b4_parse_param)) 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], [$@])]) +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], [$@])]) -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_lex_param_call_1], [, $2]) 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], [$@])]) +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_ifset([b4_parse_param], [b4_constructor_calls(b4_parse_param)])]) + m4_define([b4_constructor_calls], [m4_map([b4_constructor_call], [$@])]) m4_define([b4_constructor_call], [this.$2 = $2; ]) + + # b4_parse_param_vars # ------------------- # Extra instance variables. @@ -255,14 +259,17 @@ m4_define([b4_parse_param_vars], [ /* User arguments. */ b4_var_decls(b4_parse_param)])]) + m4_define([b4_var_decls], [m4_map_sep([b4_var_decl], [ ], [$@])]) 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])]) diff --git a/data/lalr1.java b/data/lalr1.java index 6d263752..fc2d8484 100644 --- a/data/lalr1.java +++ b/data/lalr1.java @@ -103,7 +103,7 @@ b4_token_enums(b4_tokens) return new ]b4_location_type[ (rhs.locationAt (0).end); }]]) - b4_pure_if([[/** + /** * Communication interface between the scanner and the Bison-generated * parser ]b4_parser_class_name[. */ @@ -121,30 +121,15 @@ b4_token_enums(b4_tokens) /** * 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_token_enums(b4_tokens) * ]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);] + } + + b4_lexer_if([[private class YYLexer implements Lexer { +]b4_percent_code_get([[lexer]])[ + } - /** The object doing lexical analysis for us. */ - private Lexer yylex;]) - 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. ]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.yylexer = 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 yylexer]])[) { + this.yylexer = yylexer; + ]b4_parse_param_cons[ } private java.io.PrintStream yyDebugStream = System.err; @@ -199,19 +199,19 @@ b4_token_enums(b4_tokens) */ 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 yylexer.yylex (); } protected final void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String s) { - yylex.yyerror (]b4_locations_if([loc, ])[s); - }]]) - b4_locations_if([ + yylexer.yyerror (]b4_locations_if([loc, ])[s); + } + + ]b4_locations_if([ 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) { - yyerror (new ]b4_location_type[ (loc), s); + yylexer.yyerror (new ]b4_location_type[ (loc), s); }]) [protected final void yycdebug (String s) { @@ -222,12 +222,12 @@ b4_token_enums(b4_tokens) 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 @@ b4_token_enums(b4_tokens) 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 @@ b4_token_enums(b4_tokens) 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 @@ b4_token_enums(b4_tokens) 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 @@ b4_token_enums(b4_tokens) `--------------------------------*/ 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_token_enums(b4_tokens) ]b4_location_type[ yyloc;]) /// Semantic value of the lookahead. - b4_union_name[ yylval = null; + b4_yystype[ yylval = null; int yyresult; @@ -497,13 +497,11 @@ m4_popdef([b4_at_dollar])])dnl 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 ();] + b4_locations_if([[ + yylloc = new ]b4_location_type[(yylexer.getStartPos (), + yylexer.getEndPos ());]]) + yylval = yylexer.getLVal ();[ } /* Convert token to internal form. */ diff --git a/doc/bison.texinfo b/doc/bison.texinfo index fe9e4b52..c226a077 100644 --- a/doc/bison.texinfo +++ b/doc/bison.texinfo @@ -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 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 @@ superclass of all the semantic values using the @samp{%define} directive. For example, after the following declaration: @example -%define "union_name" "ASTNode" +%define "stype" "ASTNode" @end example @noindent @@ -8483,7 +8486,7 @@ Run the syntactic analysis, and return @code{true} on success, @code{false} otherwise. @end deftypemethod -@deftypemethod {YYParser} {boolean} yyrecovering () +@deftypemethod {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 @@ Interface}); the parser uses it to report a parser error occurring at @node Java Scanner Interface @subsection Java Scanner Interface -@c - prefix for yylex. -@c - Pure interface to yylex +@c - %code lexer @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 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 -@code{%pure-parser} 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., -@code{YYParser.Lexer}. The constructor of the parser object accepts -an object implementing the interface. The interface specifies -the following methods. - -@deftypemethod {Lexer} {void} error (Location @var{l}, String @var{m}) +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 +@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 -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 @@ interface. Invocations of @samp{%lex-param @{@var{type1} @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 +@code{yylex} 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 @@ The return type can be changed using @samp{%define "position_type" 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 @@ The field's type can be changed using @samp{%define "position_type" 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 @@ section summarizes this 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 -@code{return}. 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 @@ corresponds to these C macros.}. @item The prolog declarations have a different meaning than in C/C++ code. -@table @code -@item %code -@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. +@table @asis +@item @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. -@code{%code} blocks are placed inside the parser class. If @code{%define -single_class} is being used, the definitions of @code{yylex} and -@code{yyerror} should be placed here. Subroutines for the parser actions -may be included in this kind of block. +@item unqualified @code{%code} +blocks are placed inside the parser class. + +@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. -@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 @c ================================================= FAQ diff --git a/tests/java.at b/tests/java.at index b3316492..ca5d180f 100644 --- a/tests/java.at +++ b/tests/java.at @@ -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 # 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], [[/* 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 @@ exp: | '!' { $$ = new Integer (0); return YYERROR; } | '-' error { $$ = new Integer (0); return YYERROR; } ; + +]AT_LEXPARAM_IF([[ +%code lexer { +]], +[[ %% +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 (9, 9); + st.whitespaceChars (32, 32); + st.wordChars (48, 57); + } + +AT_LOCATION_IF([[ + Position yystartpos; + Position yyendpos = new Position (1); - 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; - } + 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 @@ mv at-expout 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 # BISON-DIRECTIVES, and performs several tests over the parser. @@ -209,7 +288,7 @@ AT_BISON_OPTION_PUSHDEFS([$1]) 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_CLEANUP ])# _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 @@ _AT_CHECK_JAVA_CALC([%error-verbose $1], [$2], [$3]) # 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], []) diff --git a/tests/local.at b/tests/local.at index 7c4858ad..ab68cca9 100644 --- a/tests/local.at +++ b/tests/local.at @@ -52,6 +52,8 @@ m4_pushdef([AT_GLR_CC_IF], # 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_GLR_OR_PARAM_IF]) 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]) -- 2.45.2