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 Also, it is possible to add code to the parser's constructors using
"%code init" and "%define init_throws". "%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 ** Variable api.tokens.prefix
The variable api.tokens.prefix changes the way tokens are identified in 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. /// \param msg a description of the syntax error.
virtual void error (]b4_locations_if([const location_type& loc, ])[const std::string& msg); 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: private:
/// State numbers. /// State numbers.
typedef int state_type; typedef int state_type;
@@ -734,13 +737,21 @@ m4_popdef([b4_at_dollar])])dnl
if (yyempty) if (yyempty)
{ {
YYCDEBUG << "Reading a token: "; YYCDEBUG << "Reading a token: ";
try
{
]b4_lex_symbol_if( ]b4_lex_symbol_if(
[ yyla = b4_c_function_call([yylex], [symbol_type], [ yyla = b4_c_function_call([yylex], [symbol_type],
m4_ifdef([b4_lex_param], b4_lex_param));], m4_ifdef([b4_lex_param], b4_lex_param));],
[ yyla.type = yytranslate_ (b4_c_function_call([yylex], [int], [ yyla.type = yytranslate_ (b4_c_function_call([yylex], [int],
[[YYSTYPE*], [&yyla.value]][]dnl [[YYSTYPE*], [&yyla.value]][]dnl
b4_locations_if([, [[location*], [&yyla.location]]])dnl b4_locations_if([, [[location*], [&yyla.location]]])dnl
m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
}
catch (const syntax_error& yyexc)
{
error (yyexc);
goto yyerrlab1;
}
yyempty = false; yyempty = false;
} }
YY_SYMBOL_PRINT ("Next token is", yyla); YY_SYMBOL_PRINT ("Next token is", yyla);
@@ -823,8 +834,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
} }
catch (const syntax_error& yyexc) catch (const syntax_error& yyexc)
{ {
error (]b4_args(b4_locations_if([yyexc.location]), error (yyexc);
[[yyexc.what()]])[);
YYERROR; YYERROR;
} }
YY_SYMBOL_PRINT ("-> $$ =", yylhs); YY_SYMBOL_PRINT ("-> $$ =", yylhs);
@@ -971,6 +981,13 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
return yyresult; 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. // Generate an error message.
std::string std::string
]b4_parser_class_name[::yysyntax_error_ (]dnl ]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} @defcv {Type} {parser} {syntax_error}
This class derives from @code{std::runtime_error}. Throw instances of it 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 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. 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 But contrary to @code{YYERROR} which can only be invoked from user actions

View File

@@ -492,9 +492,12 @@ item:
int int
yylex (yy::parser::semantic_type *) 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++) switch (int res = *input++)
{ {
case 'l':
throw yy::parser::syntax_error("invalid character");
default: default:
return res; return res;
} }
@@ -520,6 +523,8 @@ AT_COMPILE_CXX([[input]])
AT_PARSER_CHECK([[./input]], [[0]], [[]], AT_PARSER_CHECK([[./input]], [[0]], [[]],
[[error: invalid expression [[error: invalid expression
caught error caught error
error: invalid character
caught error
]]) ]])
AT_CLEANUP AT_CLEANUP