From a6552c5d2a559399b2ca2619159e3de14cff4468 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 30 Jun 2011 14:10:21 +0200 Subject: 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. --- NEWS | 9 +++++++++ data/lalr1.cc | 27 ++++++++++++++++++++++----- doc/bison.texinfo | 3 ++- tests/c++.at | 7 ++++++- 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 -- cgit v1.2.1