summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkim Demaille <demaille@gostai.com>2011-06-30 14:10:21 +0200
committerAkim Demaille <demaille@gostai.com>2012-02-10 09:17:45 +0100
commita6552c5d2a559399b2ca2619159e3de14cff4468 (patch)
tree0639090eaa684ee3479ad3af1df1343b6d845431
parent199a2d6d729f596ed3652a5ac0185c5afa025023 (diff)
downloadbison-a6552c5d2a559399b2ca2619159e3de14cff4468.tar.gz
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.
-rw-r--r--NEWS9
-rw-r--r--data/lalr1.cc27
-rw-r--r--doc/bison.texinfo3
-rw-r--r--tests/c++.at7
4 files changed, 39 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index a9922c09..293e2dfd 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/data/lalr1.cc b/data/lalr1.cc
index 607d0e3c..4179deaf 100644
--- a/data/lalr1.cc
+++ b/data/lalr1.cc
@@ -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,13 +737,21 @@ 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));],
-[ 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);
@@ -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
diff --git a/doc/bison.texinfo b/doc/bison.texinfo
index b6604f61..836733d0 100644
--- a/doc/bison.texinfo
+++ b/doc/bison.texinfo
@@ -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
diff --git a/tests/c++.at b/tests/c++.at
index 36c4d992..d29b6f60 100644
--- a/tests/c++.at
+++ b/tests/c++.at
@@ -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