mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
java: demonstrate push parsers
* data/skeletons/lalr1.java (Location): Make it a static class. (Lexer.yylex, Lexer.getLVal, Lexer.getStartPos, Lexer.getEndPos): These are not needed in push parsers. * examples/java/calc/Calc.y: Demonstrate push parsers in the Java. * doc/bison.texi: Push parsers have been supported for a long time, remove incorrect statements stating the opposite.
This commit is contained in:
4
NEWS
4
NEWS
@@ -216,8 +216,8 @@ GNU Bison NEWS
|
||||
|
||||
*** Examples
|
||||
|
||||
There are now two examples in examples/java: a very simple calculator, and
|
||||
one that tracks locations to provide accurate error messages.
|
||||
There are now examples/java: a very simple calculator, and a more complete
|
||||
one (push-parser, location tracking, and debug traces).
|
||||
|
||||
The lexcalc example (a simple example in C based on Flex and Bison) now
|
||||
also demonstrates location tracking.
|
||||
|
||||
3
TODO
3
TODO
@@ -25,9 +25,6 @@ should be updated to not use YYERRCODE. Returning an undef token is good
|
||||
enough.
|
||||
|
||||
** Java
|
||||
*** Examples
|
||||
Have an example with a push parser. Use autocompletion in that case.
|
||||
|
||||
*** calc.at
|
||||
Stop hard-coding "Calc". Adjust local.at (look for FIXME).
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ import java.text.MessageFormat;
|
||||
* Locations represent a part of the input through the beginning
|
||||
* and ending positions.
|
||||
*/
|
||||
public class ]b4_location_type[ {
|
||||
public static class ]b4_location_type[ {
|
||||
/**
|
||||
* The first, inclusive, position in the range.
|
||||
*/
|
||||
@@ -182,8 +182,7 @@ import java.text.MessageFormat;
|
||||
]b4_token_enums[
|
||||
/** Deprecated, use ]b4_symbol(0, id)[ instead. */
|
||||
public static final int EOF = ]b4_symbol(0, id)[;
|
||||
|
||||
]b4_locations_if([[
|
||||
]b4_pull_if([b4_locations_if([[
|
||||
/**
|
||||
* Method to retrieve the beginning position of the last scanned token.
|
||||
* @@return the position at which the last scanned token starts.
|
||||
@@ -209,7 +208,7 @@ import java.text.MessageFormat;
|
||||
* @@return the token identifier corresponding to the next token.
|
||||
*/
|
||||
int yylex()]b4_maybe_throws([b4_lex_throws])[;
|
||||
|
||||
]])[
|
||||
/**
|
||||
* Emit an error]b4_locations_if([ referring to the given location])[in a user-defined way.
|
||||
*
|
||||
@@ -832,7 +831,7 @@ b4_dollar_popdef[]dnl
|
||||
this.push_parse_initialized = true;
|
||||
|
||||
}
|
||||
]b4_locations_if([
|
||||
]b4_locations_if([[
|
||||
/**
|
||||
* Push parse given input from an external lexer.
|
||||
*
|
||||
@@ -842,11 +841,10 @@ b4_dollar_popdef[]dnl
|
||||
*
|
||||
* @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
|
||||
*/
|
||||
public int push_parse(int yylextoken, b4_yystype yylexval, b4_position_type yylexpos)b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])
|
||||
{
|
||||
return push_parse(yylextoken, yylexval, new b4_location_type (yylexpos));
|
||||
public int push_parse(int yylextoken, ]b4_yystype[ yylexval, ]b4_position_type[ yylexpos)]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[ {
|
||||
return push_parse(yylextoken, yylexval, new ]b4_location_type[(yylexpos));
|
||||
}
|
||||
])[]])[
|
||||
]])])[
|
||||
|
||||
]b4_both_if([[
|
||||
/**
|
||||
@@ -857,21 +855,18 @@ b4_dollar_popdef[]dnl
|
||||
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not
|
||||
* imply that there were no syntax errors.
|
||||
*/
|
||||
public boolean parse()]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[
|
||||
{
|
||||
if (yylexer == null)
|
||||
throw new NullPointerException("Null Lexer");
|
||||
int status;
|
||||
do {
|
||||
int token = yylexer.yylex();
|
||||
]b4_yystype[ lval = yylexer.getLVal();
|
||||
]b4_locations_if([dnl
|
||||
b4_location_type yyloc = new b4_location_type (yylexer.getStartPos (),
|
||||
yylexer.getEndPos ());])[]b4_locations_if([[
|
||||
status = push_parse(token,lval,yyloc);]], [[
|
||||
status = push_parse(token,lval);]])[
|
||||
} while (status == YYPUSH_MORE);
|
||||
return (status == YYACCEPT);
|
||||
public boolean parse()]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[ {
|
||||
if (yylexer == null)
|
||||
throw new NullPointerException("Null Lexer");
|
||||
int status;
|
||||
do {
|
||||
int token = yylexer.yylex();
|
||||
]b4_yystype[ lval = yylexer.getLVal();]b4_locations_if([[
|
||||
]b4_location_type[ yyloc = new ]b4_location_type[(yylexer.getStartPos(), yylexer.getEndPos());
|
||||
status = push_parse(token, lval, yyloc);]], [[
|
||||
status = push_parse(token, lval);]])[
|
||||
} while (status == YYPUSH_MORE);
|
||||
return status == YYACCEPT;
|
||||
}
|
||||
]])[
|
||||
|
||||
|
||||
@@ -13341,9 +13341,9 @@ changed using @code{%define api.location.type @{@var{class-name}@}}.
|
||||
@end deftypemethod
|
||||
|
||||
@deftypemethod {Lexer} {int} yylex ()
|
||||
Return the next token. Its type is the return value, its semantic
|
||||
value and location are saved and returned by the their methods in the
|
||||
interface.
|
||||
Return the next token. Its type is the return value, its semantic value and
|
||||
location are saved and returned by the their methods in the interface. Not
|
||||
needed for push-only parsers.
|
||||
|
||||
Use @samp{%define lex_throws} to specify any uncaught exceptions.
|
||||
Default is @code{java.io.IOException}.
|
||||
@@ -13353,7 +13353,7 @@ Default is @code{java.io.IOException}.
|
||||
@deftypemethodx {Lexer} {Position} getEndPos ()
|
||||
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.
|
||||
unless location tracking and pull parsing are active.
|
||||
|
||||
They should return new objects for each call, to avoid that all the symbol
|
||||
share the same Position boundaries.
|
||||
@@ -13363,7 +13363,8 @@ The return type can be changed using @code{%define api.position.type
|
||||
@end deftypemethod
|
||||
|
||||
@deftypemethod {Lexer} {Object} getLVal ()
|
||||
Return the semantic value of the last token that yylex returned.
|
||||
Return the semantic value of the last token that yylex returned. Not needed
|
||||
for push-only parsers.
|
||||
|
||||
The return type can be changed using @samp{%define api.value.type
|
||||
@{@var{class-name}@}}.
|
||||
|
||||
@@ -9,7 +9,7 @@ afterwards.
|
||||
The usual calculator, a very simple version.
|
||||
|
||||
## calc/Calc.y
|
||||
The calculator, but with location tracking and debug traces.
|
||||
The calculator, but with location tracking, debug traces, and a push parser.
|
||||
|
||||
<!---
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
%define api.parser.class {Calc}
|
||||
%define api.parser.public
|
||||
%define api.push-pull push
|
||||
|
||||
%define parse.error custom
|
||||
%define parse.trace
|
||||
@@ -20,12 +21,19 @@
|
||||
|
||||
%code {
|
||||
public static void main(String[] args) throws IOException {
|
||||
CalcLexer l = new CalcLexer(System.in);
|
||||
Calc p = new Calc(l);
|
||||
CalcLexer scanner = new CalcLexer(System.in);
|
||||
Calc parser = new Calc(scanner);
|
||||
for (String arg : args)
|
||||
if (arg.equals("-p"))
|
||||
p.setDebugLevel(1);
|
||||
if (!p.parse())
|
||||
parser.setDebugLevel(1);
|
||||
int status;
|
||||
do {
|
||||
int token = scanner.getToken();
|
||||
Object lval = scanner.getValue();
|
||||
Calc.Location yyloc = scanner.getLocation();
|
||||
status = parser.push_parse(token, lval, yyloc);
|
||||
} while (status == Calc.YYPUSH_MORE);
|
||||
if (status != Calc.YYACCEPT)
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
@@ -105,12 +113,12 @@ class CalcLexer implements Calc.Lexer {
|
||||
Position start = new Position(1, 0);
|
||||
Position end = new Position(1, 0);
|
||||
|
||||
public Position getStartPos() {
|
||||
return new Position(start);
|
||||
}
|
||||
|
||||
public Position getEndPos() {
|
||||
return new Position(end);
|
||||
/**
|
||||
* The location of the last token read.
|
||||
* Implemented with getStartPos and getEndPos in pull parsers.
|
||||
*/
|
||||
public Calc.Location getLocation() {
|
||||
return new Calc.Location(new Position(start), new Position(end));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,11 +158,17 @@ class CalcLexer implements Calc.Lexer {
|
||||
|
||||
Integer yylval;
|
||||
|
||||
public Object getLVal() {
|
||||
/**
|
||||
* The value of the last token read. Called getLVal in pull parsers.
|
||||
*/
|
||||
public Object getValue() {
|
||||
return yylval;
|
||||
}
|
||||
|
||||
public int yylex() throws IOException {
|
||||
/**
|
||||
* Fetch the next token. Called yylex in pull parsers.
|
||||
*/
|
||||
public int getToken() throws IOException {
|
||||
start.set(reader.getPosition());
|
||||
int ttype = st.nextToken();
|
||||
end.set(reader.getPosition());
|
||||
@@ -170,7 +184,7 @@ class CalcLexer implements Calc.Lexer {
|
||||
end.set(reader.getPreviousPosition());
|
||||
return NUM;
|
||||
case ' ': case '\t':
|
||||
return yylex();
|
||||
return getToken();
|
||||
case '!':
|
||||
return BANG;
|
||||
case '+':
|
||||
|
||||
Reference in New Issue
Block a user