lalr1.cc: also handle syntax_error when calling yylex.

* data/lalr1.cc (parse): Catch syntax_error around yylex and
	forward them to errlab1.
	* tests/c++.at (Syntax error as exception): Check support for
	syntax exceptions raised by the scanner.
	* NEWS, doc/bison.texinfo: Document it.
This commit is contained in:
Akim Demaille
2011-06-30 14:10:21 +02:00
parent 199a2d6d72
commit a6552c5d2a
4 changed files with 39 additions and 7 deletions

9
NEWS
View File

@@ -24,6 +24,15 @@ Bison News
Also, it is possible to add code to the parser's constructors using
"%code init" and "%define init_throws".
** C++ skeleton improvements
The C++ parser features a syntax_error exception, which can be
thrown from the scanner or from user rules to raise syntax errors.
This facilitates reporting errors caught in sub-functions (e.g.,
rejecting too large integral literals from a conversion function
used by the scanner, or rejecting invalid combinations from a
factory invoked by the user actions).
** Variable api.tokens.prefix
The variable api.tokens.prefix changes the way tokens are identified in

View File

@@ -209,6 +209,9 @@ b4_namespace_close])[
/// \param msg a description of the syntax error.
virtual void error (]b4_locations_if([const location_type& loc, ])[const std::string& msg);
/// Report a syntax error.
void error (const syntax_error& err);
private:
/// State numbers.
typedef int state_type;
@@ -734,6 +737,8 @@ m4_popdef([b4_at_dollar])])dnl
if (yyempty)
{
YYCDEBUG << "Reading a token: ";
try
{
]b4_lex_symbol_if(
[ yyla = b4_c_function_call([yylex], [symbol_type],
m4_ifdef([b4_lex_param], b4_lex_param));],
@@ -741,6 +746,12 @@ m4_popdef([b4_at_dollar])])dnl
[[YYSTYPE*], [&yyla.value]][]dnl
b4_locations_if([, [[location*], [&yyla.location]]])dnl
m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
}
catch (const syntax_error& yyexc)
{
error (yyexc);
goto yyerrlab1;
}
yyempty = false;
}
YY_SYMBOL_PRINT ("Next token is", yyla);
@@ -823,8 +834,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
}
catch (const syntax_error& yyexc)
{
error (]b4_args(b4_locations_if([yyexc.location]),
[[yyexc.what()]])[);
error (yyexc);
YYERROR;
}
YY_SYMBOL_PRINT ("-> $$ =", yylhs);
@@ -971,6 +981,13 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
return yyresult;
}
void
]b4_parser_class_name[::error (const syntax_error& yyexc)
{
error (]b4_args(b4_locations_if([yyexc.location]),
[[yyexc.what()]])[);
}
// Generate an error message.
std::string
]b4_parser_class_name[::yysyntax_error_ (]dnl

View File

@@ -9270,7 +9270,8 @@ scanner should use @code{yy::parser::token::FOO}. The scanner can use
@defcv {Type} {parser} {syntax_error}
This class derives from @code{std::runtime_error}. Throw instances of it
from user actions to raise parse errors. This is equivalent with first
from the scanner or from the user actions to raise parse errors. This is
equivalent with first
invoking @code{error} to report the location and message of the syntax
error, and then to invoke @code{YYERROR} to enter the error-recovery mode.
But contrary to @code{YYERROR} which can only be invoked from user actions

View File

@@ -492,9 +492,12 @@ item:
int
yylex (yy::parser::semantic_type *)
{
static char const *input = "as";
// 's': syntax error, 'l': lexical error.
static char const *input = "asal";
switch (int res = *input++)
{
case 'l':
throw yy::parser::syntax_error("invalid character");
default:
return res;
}
@@ -520,6 +523,8 @@ AT_COMPILE_CXX([[input]])
AT_PARSER_CHECK([[./input]], [[0]], [[]],
[[error: invalid expression
caught error
error: invalid character
caught error
]])
AT_CLEANUP