]> git.saurik.com Git - bison.git/commitdiff
lalr1.cc: also handle syntax_error when calling yylex.
authorAkim Demaille <demaille@gostai.com>
Thu, 30 Jun 2011 12:10:21 +0000 (14:10 +0200)
committerAkim Demaille <demaille@gostai.com>
Fri, 10 Feb 2012 08:17:45 +0000 (09:17 +0100)
* 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
data/lalr1.cc
doc/bison.texinfo
tests/c++.at

diff --git a/NEWS b/NEWS
index a9922c0994f471eba079e6f0c496ca8f14bfe146..293e2dfda6a20e13191d58702d220fa313f77bcb 100644 (file)
--- 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
index 607d0e3c51d32633602ec143be914c81bca6ae31..4179deafdf691119f2a6c00f07cf63b673da0740 100644 (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,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
index b6604f6193e304cbf25b4a47ac82bc860b99fe2d..836733d00ff4a796f5171d625558ab5c53f3e1b9 100644 (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
index 36c4d992386029d6ceeb7bd7eb6d97a9c173a971..d29b6f6003e235a836774150aea3fa8bed5eafa7 100644 (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