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
/// \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;
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));],
-[ yyla.type = yytranslate_ (b4_c_function_call([yylex], [int],
+[ yyla = b4_c_function_call([yylex], [symbol_type],
+ m4_ifdef([b4_lex_param], b4_lex_param));],
+[ yyla.type = yytranslate_ (b4_c_function_call([yylex], [int],
[[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);
}
catch (const syntax_error& yyexc)
{
- error (]b4_args(b4_locations_if([yyexc.location]),
- [[yyexc.what()]])[);
+ error (yyexc);
YYERROR;
}
YY_SYMBOL_PRINT ("-> $$ =", yylhs);
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
@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
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;
}
AT_PARSER_CHECK([[./input]], [[0]], [[]],
[[error: invalid expression
caught error
+error: invalid character
+caught error
]])
AT_CLEANUP