Make the selection parser exception-proof.
authorTeemu Murtola <teemu.murtola@gmail.com>
Wed, 20 Jun 2012 03:47:36 +0000 (06:47 +0300)
committerTeemu Murtola <teemu.murtola@gmail.com>
Wed, 20 Jun 2012 17:52:55 +0000 (20:52 +0300)
The parser now catches and stores any exception that occurs during
parsing, terminates the parser cleanly, and rethrows the exception.

The functions called from the parser are still not exception-safe, and
would require quite some work to make so, because they are code written
originally in C and do a lot of dynamic memory allocation, returning
some of the allocated memory to the caller.  But the generated code
should now work with exceptions.

Fixes #880.

Change-Id: I2d534d106a6fe20d949b3f24b0d7f9980c545fcf

src/gromacs/selection/parser.cpp
src/gromacs/selection/parser.h
src/gromacs/selection/parser.y
src/gromacs/selection/parsetree.cpp
src/gromacs/selection/parsetree.h
src/gromacs/selection/scanner.h
src/gromacs/selection/scanner_internal.cpp
src/gromacs/selection/scanner_internal.h
src/gromacs/selection/selectioncollection.cpp

index e64669f4c575b5fdbe574bedb763ac4567a436a6..70e143220d8a98973fcdd68fc13cb3a03616fdab 100644 (file)
@@ -93,7 +93,9 @@
 #include <config.h>
 #endif
 
-#include <string2.h>
+#include <exception>
+
+#include "gromacs/legacyheaders/string2.h"
 
 #include "parsetree.h"
 #include "selelem.h"
@@ -112,9 +114,30 @@ yyerror(yyscan_t, char const *s);
 #pragma warning(disable: 4065)
 #endif
 
+/* These macros should be used at the beginning and end of each semantic action
+ * that may throw an exception. For robustness, it's best to wrap all actions
+ * that call functions declared outside parser.y should be wrapped.
+ * These macros take care to catch any exceptions, store the exception (or
+ * handle it and allow the parser to continue), and terminate the parser
+ * cleanly if necessary.
+ * The code calling the parser should use
+ * _gmx_sel_lexer_rethrow_exception_if_occurred() to rethrow any exceptions.
+ */
+#define BEGIN_ACTION \
+    try {
+#define END_ACTION \
+    } \
+    catch(const std::exception &ex) \
+    { \
+        if (_gmx_selparser_handle_exception(scanner, ex)) \
+            YYERROR; \
+        else \
+            YYABORT; \
+    }
+
 
 /* Line 268 of yacc.c  */
-#line 118 "parser.cpp"
+#line 141 "parser.cpp"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
@@ -184,7 +207,7 @@ typedef union YYSTYPE
 {
 
 /* Line 293 of yacc.c  */
-#line 72 "parser.y"
+#line 95 "parser.y"
 
     int                         i;
     real                        r;
@@ -199,7 +222,7 @@ typedef union YYSTYPE
 
 
 /* Line 293 of yacc.c  */
-#line 203 "parser.cpp"
+#line 226 "parser.cpp"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -235,7 +258,7 @@ void yypstate_delete ();
 
 
 /* Line 343 of yacc.c  */
-#line 239 "parser.cpp"
+#line 262 "parser.cpp"
 
 #ifdef short
 # undef short
@@ -534,16 +557,16 @@ static const yytype_int8 yyrhs[] =
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   188,   188,   189,   198,   199,   219,   223,   224,   233,
-     243,   245,   247,   249,   251,   257,   261,   262,   270,   271,
-     276,   277,   289,   290,   294,   295,   298,   299,   302,   303,
-     311,   317,   323,   335,   339,   347,   353,   361,   362,   366,
-     371,   376,   384,   396,   403,   413,   418,   426,   428,   430,
-     432,   434,   436,   438,   445,   452,   464,   469,   473,   481,
-     492,   496,   500,   509,   511,   516,   517,   522,   529,   530,
-     531,   535,   536,   538,   543,   544,   548,   549,   551,   555,
-     557,   559,   561,   563,   567,   572,   577,   582,   586,   591,
-     596
+       0,   211,   211,   212,   223,   224,   246,   252,   253,   264,
+     276,   282,   288,   294,   300,   310,   318,   319,   329,   330,
+     337,   338,   352,   353,   357,   358,   361,   362,   365,   366,
+     374,   382,   390,   398,   402,   412,   420,   430,   431,   435,
+     442,   449,   459,   473,   482,   494,   501,   511,   517,   523,
+     529,   535,   541,   547,   554,   563,   577,   586,   590,   600,
+     613,   621,   629,   642,   644,   649,   650,   655,   664,   665,
+     666,   670,   671,   673,   678,   679,   683,   684,   686,   690,
+     696,   702,   708,   714,   718,   725,   732,   739,   743,   750,
+     757
 };
 #endif
 
@@ -1337,218 +1360,218 @@ yydestruct (yymsg, yytype, yyvaluep, scanner)
       case 5: /* "HELP_TOPIC" */
 
 /* Line 1391 of yacc.c  */
-#line 167 "parser.y"
+#line 190 "parser.y"
        { free((yyvaluep->str));                     };
 
 /* Line 1391 of yacc.c  */
-#line 1345 "parser.cpp"
+#line 1368 "parser.cpp"
        break;
       case 8: /* "STR" */
 
 /* Line 1391 of yacc.c  */
-#line 167 "parser.y"
+#line 190 "parser.y"
        { free((yyvaluep->str));                     };
 
 /* Line 1391 of yacc.c  */
-#line 1354 "parser.cpp"
+#line 1377 "parser.cpp"
        break;
       case 9: /* "IDENTIFIER" */
 
 /* Line 1391 of yacc.c  */
-#line 167 "parser.y"
+#line 190 "parser.y"
        { free((yyvaluep->str));                     };
 
 /* Line 1391 of yacc.c  */
-#line 1363 "parser.cpp"
+#line 1386 "parser.cpp"
        break;
       case 25: /* "PARAM" */
 
 /* Line 1391 of yacc.c  */
-#line 168 "parser.y"
+#line 191 "parser.y"
        { if((yyvaluep->str)) free((yyvaluep->str));              };
 
 /* Line 1391 of yacc.c  */
-#line 1372 "parser.cpp"
+#line 1395 "parser.cpp"
        break;
       case 28: /* "CMP_OP" */
 
 /* Line 1391 of yacc.c  */
-#line 167 "parser.y"
+#line 190 "parser.y"
        { free((yyvaluep->str));                     };
 
 /* Line 1391 of yacc.c  */
-#line 1381 "parser.cpp"
+#line 1404 "parser.cpp"
        break;
       case 51: /* "command" */
 
 /* Line 1391 of yacc.c  */
-#line 169 "parser.y"
+#line 192 "parser.y"
        { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
 
 /* Line 1391 of yacc.c  */
-#line 1390 "parser.cpp"
+#line 1413 "parser.cpp"
        break;
       case 52: /* "cmd_plain" */
 
 /* Line 1391 of yacc.c  */
-#line 169 "parser.y"
+#line 192 "parser.y"
        { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
 
 /* Line 1391 of yacc.c  */
-#line 1399 "parser.cpp"
+#line 1422 "parser.cpp"
        break;
       case 54: /* "help_topic" */
 
 /* Line 1391 of yacc.c  */
-#line 175 "parser.y"
+#line 198 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
 
 /* Line 1391 of yacc.c  */
-#line 1408 "parser.cpp"
+#line 1431 "parser.cpp"
        break;
       case 55: /* "selection" */
 
 /* Line 1391 of yacc.c  */
-#line 170 "parser.y"
+#line 193 "parser.y"
        { _gmx_selelem_free_chain((yyvaluep->sel));  };
 
 /* Line 1391 of yacc.c  */
-#line 1417 "parser.cpp"
+#line 1440 "parser.cpp"
        break;
       case 59: /* "string" */
 
 /* Line 1391 of yacc.c  */
-#line 167 "parser.y"
+#line 190 "parser.y"
        { free((yyvaluep->str));                     };
 
 /* Line 1391 of yacc.c  */
-#line 1426 "parser.cpp"
+#line 1449 "parser.cpp"
        break;
       case 60: /* "sel_expr" */
 
 /* Line 1391 of yacc.c  */
-#line 171 "parser.y"
+#line 194 "parser.y"
        { _gmx_selelem_free((yyvaluep->sel));        };
 
 /* Line 1391 of yacc.c  */
-#line 1435 "parser.cpp"
+#line 1458 "parser.cpp"
        break;
       case 62: /* "num_expr" */
 
 /* Line 1391 of yacc.c  */
-#line 171 "parser.y"
+#line 194 "parser.y"
        { _gmx_selelem_free((yyvaluep->sel));        };
 
 /* Line 1391 of yacc.c  */
-#line 1444 "parser.cpp"
+#line 1467 "parser.cpp"
        break;
       case 63: /* "str_expr" */
 
 /* Line 1391 of yacc.c  */
-#line 171 "parser.y"
+#line 194 "parser.y"
        { _gmx_selelem_free((yyvaluep->sel));        };
 
 /* Line 1391 of yacc.c  */
-#line 1453 "parser.cpp"
+#line 1476 "parser.cpp"
        break;
       case 64: /* "pos_expr" */
 
 /* Line 1391 of yacc.c  */
-#line 171 "parser.y"
+#line 194 "parser.y"
        { _gmx_selelem_free((yyvaluep->sel));        };
 
 /* Line 1391 of yacc.c  */
-#line 1462 "parser.cpp"
+#line 1485 "parser.cpp"
        break;
       case 65: /* "method_params" */
 
 /* Line 1391 of yacc.c  */
-#line 172 "parser.y"
+#line 195 "parser.y"
        { _gmx_selexpr_free_params((yyvaluep->param)); };
 
 /* Line 1391 of yacc.c  */
-#line 1471 "parser.cpp"
+#line 1494 "parser.cpp"
        break;
       case 66: /* "method_param_list" */
 
 /* Line 1391 of yacc.c  */
-#line 172 "parser.y"
+#line 195 "parser.y"
        { _gmx_selexpr_free_params((yyvaluep->param)); };
 
 /* Line 1391 of yacc.c  */
-#line 1480 "parser.cpp"
+#line 1503 "parser.cpp"
        break;
       case 67: /* "method_param" */
 
 /* Line 1391 of yacc.c  */
-#line 172 "parser.y"
+#line 195 "parser.y"
        { _gmx_selexpr_free_params((yyvaluep->param)); };
 
 /* Line 1391 of yacc.c  */
-#line 1489 "parser.cpp"
+#line 1512 "parser.cpp"
        break;
       case 68: /* "value_list" */
 
 /* Line 1391 of yacc.c  */
-#line 173 "parser.y"
+#line 196 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
 
 /* Line 1391 of yacc.c  */
-#line 1498 "parser.cpp"
+#line 1521 "parser.cpp"
        break;
       case 69: /* "value_list_contents" */
 
 /* Line 1391 of yacc.c  */
-#line 173 "parser.y"
+#line 196 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
 
 /* Line 1391 of yacc.c  */
-#line 1507 "parser.cpp"
+#line 1530 "parser.cpp"
        break;
       case 70: /* "basic_value_list" */
 
 /* Line 1391 of yacc.c  */
-#line 174 "parser.y"
+#line 197 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
 
 /* Line 1391 of yacc.c  */
-#line 1516 "parser.cpp"
+#line 1539 "parser.cpp"
        break;
       case 71: /* "basic_value_list_contents" */
 
 /* Line 1391 of yacc.c  */
-#line 174 "parser.y"
+#line 197 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
 
 /* Line 1391 of yacc.c  */
-#line 1525 "parser.cpp"
+#line 1548 "parser.cpp"
        break;
       case 72: /* "value_item" */
 
 /* Line 1391 of yacc.c  */
-#line 173 "parser.y"
+#line 196 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
 
 /* Line 1391 of yacc.c  */
-#line 1534 "parser.cpp"
+#line 1557 "parser.cpp"
        break;
       case 73: /* "basic_value_item" */
 
 /* Line 1391 of yacc.c  */
-#line 174 "parser.y"
+#line 197 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
 
 /* Line 1391 of yacc.c  */
-#line 1543 "parser.cpp"
+#line 1566 "parser.cpp"
        break;
       case 74: /* "value_item_range" */
 
 /* Line 1391 of yacc.c  */
-#line 173 "parser.y"
+#line 196 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
 
 /* Line 1391 of yacc.c  */
-#line 1552 "parser.cpp"
+#line 1575 "parser.cpp"
        break;
 
       default:
@@ -1897,33 +1920,36 @@ yyreduce:
         case 2:
 
 /* Line 1806 of yacc.c  */
-#line 188 "parser.y"
+#line 211 "parser.y"
     { (yyval.sel) = NULL; }
     break;
 
   case 3:
 
 /* Line 1806 of yacc.c  */
-#line 190 "parser.y"
+#line 213 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_append_selection((yyvsp[(2) - (2)].sel), (yyvsp[(1) - (2)].sel), scanner);
                  if (_gmx_sel_parser_should_finish(scanner))
                      YYACCEPT;
+                 END_ACTION;
              }
     break;
 
   case 4:
 
 /* Line 1806 of yacc.c  */
-#line 198 "parser.y"
+#line 223 "parser.y"
     { (yyval.sel) = (yyvsp[(1) - (2)].sel); }
     break;
 
   case 5:
 
 /* Line 1806 of yacc.c  */
-#line 200 "parser.y"
+#line 225 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = NULL;
                  _gmx_selparser_error(scanner, "invalid selection '%s'",
                                       _gmx_sel_lexer_pselstr(scanner));
@@ -1937,45 +1963,51 @@ yyreduce:
                  {
                      YYABORT;
                  }
+                 END_ACTION;
              }
     break;
 
   case 6:
 
 /* Line 1806 of yacc.c  */
-#line 219 "parser.y"
+#line 246 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = NULL;
                  _gmx_sel_handle_empty_cmd(scanner);
+                 END_ACTION;
              }
     break;
 
   case 7:
 
 /* Line 1806 of yacc.c  */
-#line 223 "parser.y"
+#line 252 "parser.y"
     { (yyval.sel) = NULL; }
     break;
 
   case 8:
 
 /* Line 1806 of yacc.c  */
-#line 225 "parser.y"
+#line 254 "parser.y"
     {
+                 BEGIN_ACTION;
                  t_selelem *s, *p;
                  s = _gmx_sel_init_group_by_id((yyvsp[(1) - (1)].i), scanner);
                  if (s == NULL) YYERROR;
                  p = _gmx_sel_init_position(s, NULL, scanner);
                  if (p == NULL) YYERROR;
                  (yyval.sel) = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+                 END_ACTION;
              }
     break;
 
   case 9:
 
 /* Line 1806 of yacc.c  */
-#line 234 "parser.y"
+#line 265 "parser.y"
     {
+                 BEGIN_ACTION;
                  t_selelem *s, *p;
                  s = _gmx_sel_init_group_by_name((yyvsp[(1) - (1)].str), scanner);
                  free((yyvsp[(1) - (1)].str));
@@ -1983,674 +2015,811 @@ yyreduce:
                  p = _gmx_sel_init_position(s, NULL, scanner);
                  if (p == NULL) YYERROR;
                  (yyval.sel) = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+                 END_ACTION;
              }
     break;
 
   case 10:
 
 /* Line 1806 of yacc.c  */
-#line 244 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_selection(NULL, (yyvsp[(1) - (1)].sel), scanner); }
+#line 277 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_selection(NULL, (yyvsp[(1) - (1)].sel), scanner);
+                 END_ACTION;
+             }
     break;
 
   case 11:
 
 /* Line 1806 of yacc.c  */
-#line 246 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_selection((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].sel), scanner);   }
+#line 283 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_selection((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].sel), scanner);
+                 END_ACTION;
+             }
     break;
 
   case 12:
 
 /* Line 1806 of yacc.c  */
-#line 248 "parser.y"
-    { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  }
+#line 289 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);
+                 END_ACTION;
+             }
     break;
 
   case 13:
 
 /* Line 1806 of yacc.c  */
-#line 250 "parser.y"
-    { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  }
+#line 295 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);
+                 END_ACTION;
+             }
     break;
 
   case 14:
 
 /* Line 1806 of yacc.c  */
-#line 252 "parser.y"
-    { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  }
+#line 301 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);
+                 END_ACTION;
+             }
     break;
 
   case 15:
 
 /* Line 1806 of yacc.c  */
-#line 258 "parser.y"
-    { _gmx_sel_handle_help_cmd(process_value_list((yyvsp[(2) - (2)].val), NULL), scanner); }
+#line 311 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 _gmx_sel_handle_help_cmd(process_value_list((yyvsp[(2) - (2)].val), NULL), scanner);
+                 END_ACTION;
+             }
     break;
 
   case 16:
 
 /* Line 1806 of yacc.c  */
-#line 261 "parser.y"
+#line 318 "parser.y"
     { (yyval.val) = NULL; }
     break;
 
   case 17:
 
 /* Line 1806 of yacc.c  */
-#line 263 "parser.y"
+#line 320 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.val) = _gmx_selexpr_create_value(STR_VALUE);
                  (yyval.val)->u.s = (yyvsp[(2) - (2)].str); (yyval.val)->next = (yyvsp[(1) - (2)].val);
+                 END_ACTION;
              }
     break;
 
   case 18:
 
 /* Line 1806 of yacc.c  */
-#line 270 "parser.y"
+#line 329 "parser.y"
     { (yyval.sel) = (yyvsp[(1) - (1)].sel); }
     break;
 
   case 19:
 
 /* Line 1806 of yacc.c  */
-#line 272 "parser.y"
+#line 331 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_position((yyvsp[(1) - (1)].sel), NULL, scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 20:
 
 /* Line 1806 of yacc.c  */
-#line 276 "parser.y"
+#line 337 "parser.y"
     { (yyval.sel) = (yyvsp[(2) - (3)].sel); }
     break;
 
   case 21:
 
 /* Line 1806 of yacc.c  */
-#line 278 "parser.y"
+#line 339 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_modifier((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].sel), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 22:
 
 /* Line 1806 of yacc.c  */
-#line 289 "parser.y"
+#line 352 "parser.y"
     { (yyval.i) = (yyvsp[(1) - (1)].i); }
     break;
 
   case 23:
 
 /* Line 1806 of yacc.c  */
-#line 290 "parser.y"
+#line 353 "parser.y"
     { (yyval.i) = -(yyvsp[(2) - (2)].i); }
     break;
 
   case 24:
 
 /* Line 1806 of yacc.c  */
-#line 294 "parser.y"
+#line 357 "parser.y"
     { (yyval.r) = (yyvsp[(1) - (1)].r); }
     break;
 
   case 25:
 
 /* Line 1806 of yacc.c  */
-#line 295 "parser.y"
+#line 358 "parser.y"
     { (yyval.r) = -(yyvsp[(2) - (2)].r); }
     break;
 
   case 26:
 
 /* Line 1806 of yacc.c  */
-#line 298 "parser.y"
+#line 361 "parser.y"
     { (yyval.r) = (yyvsp[(1) - (1)].i); }
     break;
 
   case 27:
 
 /* Line 1806 of yacc.c  */
-#line 299 "parser.y"
+#line 362 "parser.y"
     { (yyval.r) = (yyvsp[(1) - (1)].r); }
     break;
 
   case 28:
 
 /* Line 1806 of yacc.c  */
-#line 302 "parser.y"
+#line 365 "parser.y"
     { (yyval.str) = (yyvsp[(1) - (1)].str); }
     break;
 
   case 29:
 
 /* Line 1806 of yacc.c  */
-#line 303 "parser.y"
+#line 366 "parser.y"
     { (yyval.str) = (yyvsp[(1) - (1)].str); }
     break;
 
   case 30:
 
 /* Line 1806 of yacc.c  */
-#line 312 "parser.y"
+#line 375 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
                  (yyval.sel)->u.boolt = BOOL_NOT;
                  (yyval.sel)->child = (yyvsp[(2) - (2)].sel);
+                 END_ACTION;
              }
     break;
 
   case 31:
 
 /* Line 1806 of yacc.c  */
-#line 318 "parser.y"
+#line 383 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
                  (yyval.sel)->u.boolt = BOOL_AND;
                  (yyval.sel)->child = (yyvsp[(1) - (3)].sel); (yyval.sel)->child->next = (yyvsp[(3) - (3)].sel);
+                 END_ACTION;
              }
     break;
 
   case 32:
 
 /* Line 1806 of yacc.c  */
-#line 324 "parser.y"
+#line 391 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
                  (yyval.sel)->u.boolt = BOOL_OR;
                  (yyval.sel)->child = (yyvsp[(1) - (3)].sel); (yyval.sel)->child->next = (yyvsp[(3) - (3)].sel);
+                 END_ACTION;
              }
     break;
 
   case 33:
 
 /* Line 1806 of yacc.c  */
-#line 335 "parser.y"
+#line 398 "parser.y"
     { (yyval.sel) = (yyvsp[(2) - (3)].sel); }
     break;
 
   case 34:
 
 /* Line 1806 of yacc.c  */
-#line 340 "parser.y"
+#line 403 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_comparison((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), (yyvsp[(2) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 35:
 
 /* Line 1806 of yacc.c  */
-#line 348 "parser.y"
+#line 413 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_group_by_name((yyvsp[(2) - (2)].str), scanner);
                  free((yyvsp[(2) - (2)].str));
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 36:
 
 /* Line 1806 of yacc.c  */
-#line 354 "parser.y"
+#line 421 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_group_by_id((yyvsp[(2) - (2)].i), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 37:
 
 /* Line 1806 of yacc.c  */
-#line 361 "parser.y"
+#line 430 "parser.y"
     { (yyval.str) = NULL; }
     break;
 
   case 38:
 
 /* Line 1806 of yacc.c  */
-#line 362 "parser.y"
+#line 431 "parser.y"
     { (yyval.str) = (yyvsp[(1) - (1)].str);   }
     break;
 
   case 39:
 
 /* Line 1806 of yacc.c  */
-#line 367 "parser.y"
+#line 436 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 40:
 
 /* Line 1806 of yacc.c  */
-#line 372 "parser.y"
+#line 443 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 41:
 
 /* Line 1806 of yacc.c  */
-#line 377 "parser.y"
+#line 450 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 42:
 
 /* Line 1806 of yacc.c  */
-#line 385 "parser.y"
+#line 460 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 43:
 
 /* Line 1806 of yacc.c  */
-#line 397 "parser.y"
+#line 474 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_selelem_create(SEL_CONST);
                  _gmx_selelem_set_vtype((yyval.sel), INT_VALUE);
                  _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
                  (yyval.sel)->v.u.i[0] = (yyvsp[(1) - (1)].i);
+                 END_ACTION;
              }
     break;
 
   case 44:
 
 /* Line 1806 of yacc.c  */
-#line 404 "parser.y"
+#line 483 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_selelem_create(SEL_CONST);
                  _gmx_selelem_set_vtype((yyval.sel), REAL_VALUE);
                  _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
                  (yyval.sel)->v.u.r[0] = (yyvsp[(1) - (1)].r);
+                 END_ACTION;
              }
     break;
 
   case 45:
 
 /* Line 1806 of yacc.c  */
-#line 414 "parser.y"
+#line 495 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 46:
 
 /* Line 1806 of yacc.c  */
-#line 419 "parser.y"
+#line 502 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 47:
 
 /* Line 1806 of yacc.c  */
-#line 427 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '+', scanner); }
+#line 512 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '+', scanner);
+                 END_ACTION;
+             }
     break;
 
   case 48:
 
 /* Line 1806 of yacc.c  */
-#line 429 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '-', scanner); }
+#line 518 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '-', scanner);
+                 END_ACTION;
+             }
     break;
 
   case 49:
 
 /* Line 1806 of yacc.c  */
-#line 431 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '*', scanner); }
+#line 524 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '*', scanner);
+                 END_ACTION;
+             }
     break;
 
   case 50:
 
 /* Line 1806 of yacc.c  */
-#line 433 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '/', scanner); }
+#line 530 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '/', scanner);
+                 END_ACTION;
+             }
     break;
 
   case 51:
 
 /* Line 1806 of yacc.c  */
-#line 435 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(2) - (2)].sel), NULL, '-', scanner); }
+#line 536 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(2) - (2)].sel), NULL, '-', scanner);
+                 END_ACTION;
+             }
     break;
 
   case 52:
 
 /* Line 1806 of yacc.c  */
-#line 437 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '^', scanner); }
+#line 542 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '^', scanner);
+                 END_ACTION;
+             }
     break;
 
   case 53:
 
 /* Line 1806 of yacc.c  */
-#line 438 "parser.y"
+#line 547 "parser.y"
     { (yyval.sel) = (yyvsp[(2) - (3)].sel); }
     break;
 
   case 54:
 
 /* Line 1806 of yacc.c  */
-#line 446 "parser.y"
+#line 555 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_selelem_create(SEL_CONST);
                  _gmx_selelem_set_vtype((yyval.sel), STR_VALUE);
                  _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
                  (yyval.sel)->v.u.s[0] = (yyvsp[(1) - (1)].str);
+                 END_ACTION;
              }
     break;
 
   case 55:
 
 /* Line 1806 of yacc.c  */
-#line 453 "parser.y"
+#line 564 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 56:
 
 /* Line 1806 of yacc.c  */
-#line 465 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r)); }
+#line 578 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r));
+                 END_ACTION;
+             }
     break;
 
   case 57:
 
 /* Line 1806 of yacc.c  */
-#line 469 "parser.y"
+#line 586 "parser.y"
     { (yyval.sel) = (yyvsp[(2) - (3)].sel); }
     break;
 
   case 58:
 
 /* Line 1806 of yacc.c  */
-#line 474 "parser.y"
+#line 591 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_method((yyvsp[(1) - (2)].meth), (yyvsp[(2) - (2)].param), NULL, scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 59:
 
 /* Line 1806 of yacc.c  */
-#line 482 "parser.y"
+#line 601 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.sel) = _gmx_sel_init_position((yyvsp[(3) - (3)].sel), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
+                 END_ACTION;
              }
     break;
 
   case 60:
 
 /* Line 1806 of yacc.c  */
-#line 493 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); }
+#line 614 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel));
+                 END_ACTION;
+             }
     break;
 
   case 61:
 
 /* Line 1806 of yacc.c  */
-#line 497 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); }
+#line 622 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel));
+                 END_ACTION;
+             }
     break;
 
   case 62:
 
 /* Line 1806 of yacc.c  */
-#line 501 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); }
+#line 630 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel));
+                 END_ACTION;
+             }
     break;
 
   case 63:
 
 /* Line 1806 of yacc.c  */
-#line 510 "parser.y"
+#line 643 "parser.y"
     { (yyval.param) = process_param_list((yyvsp[(1) - (1)].param)); }
     break;
 
   case 64:
 
 /* Line 1806 of yacc.c  */
-#line 512 "parser.y"
+#line 645 "parser.y"
     { (yyval.param) = process_param_list((yyvsp[(1) - (2)].param)); }
     break;
 
   case 65:
 
 /* Line 1806 of yacc.c  */
-#line 516 "parser.y"
+#line 649 "parser.y"
     { (yyval.param) = NULL;              }
     break;
 
   case 66:
 
 /* Line 1806 of yacc.c  */
-#line 518 "parser.y"
+#line 651 "parser.y"
     { (yyvsp[(2) - (2)].param)->next = (yyvsp[(1) - (2)].param); (yyval.param) = (yyvsp[(2) - (2)].param); }
     break;
 
   case 67:
 
 /* Line 1806 of yacc.c  */
-#line 523 "parser.y"
+#line 656 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.param) = _gmx_selexpr_create_param((yyvsp[(1) - (2)].str));
                  (yyval.param)->value = process_value_list((yyvsp[(2) - (2)].val), &(yyval.param)->nval);
+                 END_ACTION;
              }
     break;
 
   case 68:
 
 /* Line 1806 of yacc.c  */
-#line 529 "parser.y"
+#line 664 "parser.y"
     { (yyval.val) = NULL; }
     break;
 
   case 69:
 
 /* Line 1806 of yacc.c  */
-#line 530 "parser.y"
+#line 665 "parser.y"
     { (yyval.val) = (yyvsp[(1) - (1)].val);   }
     break;
 
   case 70:
 
 /* Line 1806 of yacc.c  */
-#line 531 "parser.y"
+#line 666 "parser.y"
     { (yyval.val) = (yyvsp[(2) - (3)].val);   }
     break;
 
   case 71:
 
 /* Line 1806 of yacc.c  */
-#line 535 "parser.y"
+#line 670 "parser.y"
     { (yyval.val) = (yyvsp[(1) - (1)].val); }
     break;
 
   case 72:
 
 /* Line 1806 of yacc.c  */
-#line 537 "parser.y"
+#line 672 "parser.y"
     { (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); }
     break;
 
   case 73:
 
 /* Line 1806 of yacc.c  */
-#line 539 "parser.y"
+#line 674 "parser.y"
     { (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); }
     break;
 
   case 74:
 
 /* Line 1806 of yacc.c  */
-#line 543 "parser.y"
+#line 678 "parser.y"
     { (yyval.val) = (yyvsp[(1) - (1)].val); }
     break;
 
   case 75:
 
 /* Line 1806 of yacc.c  */
-#line 544 "parser.y"
+#line 679 "parser.y"
     { (yyval.val) = (yyvsp[(2) - (3)].val); }
     break;
 
   case 76:
 
 /* Line 1806 of yacc.c  */
-#line 548 "parser.y"
+#line 683 "parser.y"
     { (yyval.val) = (yyvsp[(1) - (1)].val); }
     break;
 
   case 77:
 
 /* Line 1806 of yacc.c  */
-#line 550 "parser.y"
+#line 685 "parser.y"
     { (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); }
     break;
 
   case 78:
 
 /* Line 1806 of yacc.c  */
-#line 552 "parser.y"
+#line 687 "parser.y"
     { (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); }
     break;
 
   case 79:
 
 /* Line 1806 of yacc.c  */
-#line 556 "parser.y"
-    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); }
+#line 691 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel));
+                 END_ACTION;
+             }
     break;
 
   case 80:
 
 /* Line 1806 of yacc.c  */
-#line 558 "parser.y"
-    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); }
+#line 697 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel));
+                 END_ACTION;
+             }
     break;
 
   case 81:
 
 /* Line 1806 of yacc.c  */
-#line 560 "parser.y"
-    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); }
+#line 703 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel));
+                 END_ACTION;
+             }
     break;
 
   case 82:
 
 /* Line 1806 of yacc.c  */
-#line 562 "parser.y"
-    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); }
+#line 709 "parser.y"
+    {
+                 BEGIN_ACTION;
+                 (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel));
+                 END_ACTION;
+             }
     break;
 
   case 83:
 
 /* Line 1806 of yacc.c  */
-#line 563 "parser.y"
+#line 714 "parser.y"
     { (yyval.val) = (yyvsp[(1) - (1)].val); }
     break;
 
   case 84:
 
 /* Line 1806 of yacc.c  */
-#line 568 "parser.y"
+#line 719 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
                  (yyval.val)->u.i.i1 = (yyval.val)->u.i.i2 = (yyvsp[(1) - (1)].i);
+                 END_ACTION;
              }
     break;
 
   case 85:
 
 /* Line 1806 of yacc.c  */
-#line 573 "parser.y"
+#line 726 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
                  (yyval.val)->u.r.r1 = (yyval.val)->u.r.r2 = (yyvsp[(1) - (1)].r);
+                 END_ACTION;
              }
     break;
 
   case 86:
 
 /* Line 1806 of yacc.c  */
-#line 578 "parser.y"
+#line 733 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.val) = _gmx_selexpr_create_value(STR_VALUE);
                  (yyval.val)->u.s = (yyvsp[(1) - (1)].str);
+                 END_ACTION;
              }
     break;
 
   case 87:
 
 /* Line 1806 of yacc.c  */
-#line 582 "parser.y"
+#line 739 "parser.y"
     { (yyval.val) = (yyvsp[(1) - (1)].val); }
     break;
 
   case 88:
 
 /* Line 1806 of yacc.c  */
-#line 587 "parser.y"
+#line 744 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
                  (yyval.val)->u.i.i1 = (yyvsp[(1) - (3)].i); (yyval.val)->u.i.i2 = (yyvsp[(3) - (3)].i);
+                 END_ACTION;
              }
     break;
 
   case 89:
 
 /* Line 1806 of yacc.c  */
-#line 592 "parser.y"
+#line 751 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
                  (yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].i); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
+                 END_ACTION;
              }
     break;
 
   case 90:
 
 /* Line 1806 of yacc.c  */
-#line 597 "parser.y"
+#line 758 "parser.y"
     {
+                 BEGIN_ACTION;
                  (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
                  (yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].r); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
+                 END_ACTION;
              }
     break;
 
 
 
 /* Line 1806 of yacc.c  */
-#line 2654 "parser.cpp"
+#line 2823 "parser.cpp"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -2884,7 +3053,7 @@ yypushreturn:
 
 
 /* Line 2067 of yacc.c  */
-#line 603 "parser.y"
+#line 766 "parser.y"
 
 
 static t_selexpr_value *
index ba7b184e77e17b3e7af73a7cbb8e1bbe90eb92a4..2ff6e3085f5f151d5990ba00e6a380272d7c21a3 100644 (file)
@@ -80,7 +80,7 @@ typedef union YYSTYPE
 {
 
 /* Line 2068 of yacc.c  */
-#line 72 "parser.y"
+#line 95 "parser.y"
 
     int                         i;
     real                        r;
index 31dd905050c7eb6b2288ba8ee45a38069347e7aa..57ea0b841cef6c8acaa66fb8a12885f7bcf48320 100644 (file)
@@ -49,7 +49,9 @@
 #include <config.h>
 #endif
 
-#include <string2.h>
+#include <exception>
+
+#include "gromacs/legacyheaders/string2.h"
 
 #include "parsetree.h"
 #include "selelem.h"
@@ -67,6 +69,27 @@ yyerror(yyscan_t, char const *s);
 #ifdef _MSC_VER
 #pragma warning(disable: 4065)
 #endif
+
+/* These macros should be used at the beginning and end of each semantic action
+ * that may throw an exception. For robustness, it's best to wrap all actions
+ * that call functions declared outside parser.y should be wrapped.
+ * These macros take care to catch any exceptions, store the exception (or
+ * handle it and allow the parser to continue), and terminate the parser
+ * cleanly if necessary.
+ * The code calling the parser should use
+ * _gmx_sel_lexer_rethrow_exception_if_occurred() to rethrow any exceptions.
+ */
+#define BEGIN_ACTION \
+    try {
+#define END_ACTION \
+    } \
+    catch(const std::exception &ex) \
+    { \
+        if (_gmx_selparser_handle_exception(scanner, ex)) \
+            YYERROR; \
+        else \
+            YYABORT; \
+    }
 %}
 
 %union{
@@ -188,9 +211,11 @@ yyerror(yyscan_t, char const *s);
 commands:    /* empty */        { $$ = NULL; }
            | commands command
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_append_selection($2, $1, scanner);
                  if (_gmx_sel_parser_should_finish(scanner))
                      YYACCEPT;
+                 END_ACTION;
              }
 ;
 
@@ -198,6 +223,7 @@ commands:    /* empty */        { $$ = NULL; }
 command:     cmd_plain CMD_SEP  { $$ = $1; }
            | error CMD_SEP
              {
+                 BEGIN_ACTION;
                  $$ = NULL;
                  _gmx_selparser_error(scanner, "invalid selection '%s'",
                                       _gmx_sel_lexer_pselstr(scanner));
@@ -211,27 +237,33 @@ command:     cmd_plain CMD_SEP  { $$ = $1; }
                  {
                      YYABORT;
                  }
+                 END_ACTION;
              }
 ;
 
 /* Commands can be selections or variable assignments */
 cmd_plain:   /* empty */
              {
+                 BEGIN_ACTION;
                  $$ = NULL;
                  _gmx_sel_handle_empty_cmd(scanner);
+                 END_ACTION;
              }
            | help_request       { $$ = NULL; }
            | TOK_INT
              {
+                 BEGIN_ACTION;
                  t_selelem *s, *p;
                  s = _gmx_sel_init_group_by_id($1, scanner);
                  if (s == NULL) YYERROR;
                  p = _gmx_sel_init_position(s, NULL, scanner);
                  if (p == NULL) YYERROR;
                  $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+                 END_ACTION;
              }
            | string
              {
+                 BEGIN_ACTION;
                  t_selelem *s, *p;
                  s = _gmx_sel_init_group_by_name($1, scanner);
                  free($1);
@@ -239,30 +271,57 @@ cmd_plain:   /* empty */
                  p = _gmx_sel_init_position(s, NULL, scanner);
                  if (p == NULL) YYERROR;
                  $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+                 END_ACTION;
              }
            | selection
-             { $$ = _gmx_sel_init_selection(NULL, $1, scanner); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_selection(NULL, $1, scanner);
+                 END_ACTION;
+             }
            | string selection
-             { $$ = _gmx_sel_init_selection($1, $2, scanner);   }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_selection($1, $2, scanner);
+                 END_ACTION;
+             }
            | IDENTIFIER '=' sel_expr
-             { $$ = _gmx_sel_assign_variable($1, $3, scanner);  }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_assign_variable($1, $3, scanner);
+                 END_ACTION;
+             }
            | IDENTIFIER '=' num_expr
-             { $$ = _gmx_sel_assign_variable($1, $3, scanner);  }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_assign_variable($1, $3, scanner);
+                 END_ACTION;
+             }
            | IDENTIFIER '=' pos_expr
-             { $$ = _gmx_sel_assign_variable($1, $3, scanner);  }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_assign_variable($1, $3, scanner);
+                 END_ACTION;
+             }
 ;
 
 /* Help requests */
 help_request:
              HELP help_topic
-             { _gmx_sel_handle_help_cmd(process_value_list($2, NULL), scanner); }
+             {
+                 BEGIN_ACTION;
+                 _gmx_sel_handle_help_cmd(process_value_list($2, NULL), scanner);
+                 END_ACTION;
+             }
 ;
 
 help_topic:  /* empty */            { $$ = NULL; }
            | help_topic HELP_TOPIC
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selexpr_create_value(STR_VALUE);
                  $$->u.s = $2; $$->next = $1;
+                 END_ACTION;
              }
 ;
 
@@ -270,14 +329,18 @@ help_topic:  /* empty */            { $$ = NULL; }
 selection:   pos_expr           { $$ = $1; }
            | sel_expr
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_position($1, NULL, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
            | '(' selection ')'  { $$ = $2; }
            | selection MODIFIER method_params
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_modifier($2, $3, $1, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
 ;
 
@@ -310,50 +373,56 @@ string:      STR                { $$ = $1; }
 /* Boolean expressions and grouping */
 sel_expr:    NOT sel_expr
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selelem_create(SEL_BOOLEAN);
                  $$->u.boolt = BOOL_NOT;
                  $$->child = $2;
+                 END_ACTION;
              }
            | sel_expr AND sel_expr
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selelem_create(SEL_BOOLEAN);
                  $$->u.boolt = BOOL_AND;
                  $$->child = $1; $$->child->next = $3;
+                 END_ACTION;
              }
            | sel_expr OR  sel_expr
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selelem_create(SEL_BOOLEAN);
                  $$->u.boolt = BOOL_OR;
                  $$->child = $1; $$->child->next = $3;
+                 END_ACTION;
              }
-/*           | sel_expr XOR sel_expr
-             {
-                 $$ = _gmx_selelem_create(SEL_BOOLEAN);
-                 $$->u.boolt = BOOL_XOR;
-                 $$->child = $1; $$->child->next = $3;
-             }*/
            | '(' sel_expr ')'   { $$ = $2; }
 ;
 
 /* Numeric comparisons */
 sel_expr:    num_expr CMP_OP num_expr
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_comparison($1, $3, $2, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
 ;
 
 /* External groups */
 sel_expr:    GROUP string
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_group_by_name($2, scanner);
                  free($2);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
            | GROUP TOK_INT
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_group_by_id($2, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
 ;
 
@@ -365,26 +434,34 @@ pos_mod:     EMPTY_POSMOD       { $$ = NULL; }
 /* Keyword selections */
 sel_expr:    pos_mod KEYWORD_GROUP
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
            | pos_mod KEYWORD_STR basic_value_list
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
            | pos_mod KEYWORD_NUMERIC basic_value_list
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
 ;
 
 /* Custom selection methods */
 sel_expr:    pos_mod METHOD_GROUP method_params
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_method($2, $3, $1, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
 ;
 
@@ -395,46 +472,78 @@ sel_expr:    pos_mod METHOD_GROUP method_params
 /* Basic numerical values */
 num_expr:    TOK_INT
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selelem_create(SEL_CONST);
                  _gmx_selelem_set_vtype($$, INT_VALUE);
                  _gmx_selvalue_reserve(&$$->v, 1);
                  $$->v.u.i[0] = $1;
+                 END_ACTION;
              }
            | TOK_REAL
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selelem_create(SEL_CONST);
                  _gmx_selelem_set_vtype($$, REAL_VALUE);
                  _gmx_selvalue_reserve(&$$->v, 1);
                  $$->v.u.r[0] = $1;
+                 END_ACTION;
              }
 ;
 
 /* Numeric selection methods */
 num_expr:    pos_mod KEYWORD_NUMERIC    %prec NUM_REDUCT
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
            | pos_mod METHOD_NUMERIC method_params
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_method($2, $3, $1, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
 ;
 
 /* Arithmetic evaluation and grouping */
 num_expr:    num_expr '+' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '+', scanner); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_arithmetic($1, $3, '+', scanner);
+                 END_ACTION;
+             }
            | num_expr '-' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '-', scanner); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_arithmetic($1, $3, '-', scanner);
+                 END_ACTION;
+             }
            | num_expr '*' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '*', scanner); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_arithmetic($1, $3, '*', scanner);
+                 END_ACTION;
+             }
            | num_expr '/' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '/', scanner); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_arithmetic($1, $3, '/', scanner);
+                 END_ACTION;
+             }
            | '-' num_expr %prec UNARY_NEG
-             { $$ = _gmx_sel_init_arithmetic($2, NULL, '-', scanner); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_arithmetic($2, NULL, '-', scanner);
+                 END_ACTION;
+             }
            | num_expr '^' num_expr
-             { $$ = _gmx_sel_init_arithmetic($1, $3, '^', scanner); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_arithmetic($1, $3, '^', scanner);
+                 END_ACTION;
+             }
            | '(' num_expr ')'   { $$ = $2; }
 ;
 
@@ -444,15 +553,19 @@ num_expr:    num_expr '+' num_expr
 
 str_expr:    string
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selelem_create(SEL_CONST);
                  _gmx_selelem_set_vtype($$, STR_VALUE);
                  _gmx_selvalue_reserve(&$$->v, 1);
                  $$->v.u.s[0] = $1;
+                 END_ACTION;
              }
            | pos_mod KEYWORD_STR
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
 ;
 
@@ -462,7 +575,11 @@ str_expr:    string
 
 /* Constant position expressions */
 pos_expr:    '[' number ',' number ',' number ']'
-             { $$ = _gmx_sel_init_const_position($2, $4, $6); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_const_position($2, $4, $6);
+                 END_ACTION;
+             }
 ;
 
 /* Grouping of position expressions */
@@ -472,16 +589,20 @@ pos_expr:    '(' pos_expr ')'   { $$ = $2; }
 /* Expressions with a position value */
 pos_expr:    METHOD_POS method_params
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_method($1, $2, NULL, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
 ;
 
 /* Evaluation of positions using a keyword */
 pos_expr:    KEYWORD_POS OF sel_expr    %prec PARAM_REDUCT
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_sel_init_position($3, $1, scanner);
                  if ($$ == NULL) YYERROR;
+                 END_ACTION;
              }
 ;
 
@@ -490,15 +611,27 @@ pos_expr:    KEYWORD_POS OF sel_expr    %prec PARAM_REDUCT
  ********************************************************************/
 
 sel_expr:    VARIABLE_GROUP
-             { $$ = _gmx_sel_init_variable_ref($1); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_variable_ref($1);
+                 END_ACTION;
+             }
 ;
 
 num_expr:    VARIABLE_NUMERIC
-             { $$ = _gmx_sel_init_variable_ref($1); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_variable_ref($1);
+                 END_ACTION;
+             }
 ;
 
 pos_expr:    VARIABLE_POS
-             { $$ = _gmx_sel_init_variable_ref($1); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_sel_init_variable_ref($1);
+                 END_ACTION;
+             }
 ;
 
 /********************************************************************
@@ -521,8 +654,10 @@ method_param_list:
 method_param:
              PARAM value_list
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selexpr_create_param($1);
                  $$->value = process_value_list($2, &$$->nval);
+                 END_ACTION;
              }
 ;
 
@@ -553,31 +688,53 @@ basic_value_list_contents:
 ;
 
 value_item:  sel_expr            %prec PARAM_REDUCT
-             { $$ = _gmx_selexpr_create_value_expr($1); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_selexpr_create_value_expr($1);
+                 END_ACTION;
+             }
            | pos_expr            %prec PARAM_REDUCT
-             { $$ = _gmx_selexpr_create_value_expr($1); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_selexpr_create_value_expr($1);
+                 END_ACTION;
+             }
            | num_expr            %prec PARAM_REDUCT
-             { $$ = _gmx_selexpr_create_value_expr($1); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_selexpr_create_value_expr($1);
+                 END_ACTION;
+             }
            | str_expr            %prec PARAM_REDUCT
-             { $$ = _gmx_selexpr_create_value_expr($1); }
+             {
+                 BEGIN_ACTION;
+                 $$ = _gmx_selexpr_create_value_expr($1);
+                 END_ACTION;
+             }
            | value_item_range    { $$ = $1; }
 ;
 
 basic_value_item:
              integer_number      %prec PARAM_REDUCT
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selexpr_create_value(INT_VALUE);
                  $$->u.i.i1 = $$->u.i.i2 = $1;
+                 END_ACTION;
              }
            | real_number         %prec PARAM_REDUCT
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selexpr_create_value(REAL_VALUE);
                  $$->u.r.r1 = $$->u.r.r2 = $1;
+                 END_ACTION;
              }
            | string              %prec PARAM_REDUCT
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selexpr_create_value(STR_VALUE);
                  $$->u.s = $1;
+                 END_ACTION;
              }
            | value_item_range    { $$ = $1; }
 ;
@@ -585,18 +742,24 @@ basic_value_item:
 value_item_range:
              integer_number TO integer_number
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selexpr_create_value(INT_VALUE);
                  $$->u.i.i1 = $1; $$->u.i.i2 = $3;
+                 END_ACTION;
              }
            | integer_number TO real_number
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selexpr_create_value(REAL_VALUE);
                  $$->u.r.r1 = $1; $$->u.r.r2 = $3;
+                 END_ACTION;
              }
            | real_number TO number
              {
+                 BEGIN_ACTION;
                  $$ = _gmx_selexpr_create_value(REAL_VALUE);
                  $$->u.r.r1 = $1; $$->u.r.r2 = $3;
+                 END_ACTION;
              }
 ;
 
index 0d78f397ef919b6f5142296ccbcf5899666c9813..7d375b320c05cab1bdad53c4ea5c6ba92b9512e3 100644 (file)
 #include <stdio.h>
 #include <stdarg.h>
 
+#include <boost/exception_ptr.hpp>
 #include <boost/shared_ptr.hpp>
 
 #include "futil.h"
@@ -253,6 +254,13 @@ _gmx_selparser_error(yyscan_t scanner, const char *fmt, ...)
     errors->append(buf);
 }
 
+bool
+_gmx_selparser_handle_exception(yyscan_t scanner, const std::exception &/*ex*/)
+{
+    _gmx_sel_lexer_set_exception(scanner, boost::current_exception());
+    return false;
+}
+
 /*!
  * \param[in] type  Type for the new value.
  * \returns   Pointer to the newly allocated value.
@@ -577,39 +585,27 @@ _gmx_selelem_set_method(t_selelem *sel, gmx_ana_selmethod_t *method,
  * \param[in]     scanner Scanner data structure.
  * \returns       0 on success, a non-zero error code on error.
  */
-static int
+static void
 set_refpos_type(gmx::PositionCalculationCollection *pcc, t_selelem *sel,
                 const char *rpost, yyscan_t scanner)
 {
     if (!rpost)
     {
-        return 0;
+        return;
     }
 
     if (sel->u.expr.method->pupdate)
     {
-        /* Need to translate exceptions to error codes because the parser still
-         * uses return codes for error handling.
-         * Temporary solution for Redmine issue #880, exceptions should only
-         * occur here for internal errors... */
-        try
-        {
-            /* By default, use whole residues/molecules. */
-            sel->u.expr.pc
-                = pcc->createCalculationFromEnum(rpost, POS_COMPLWHOLE);
-        }
-        catch (const gmx::GromacsException &ex)
-        {
-            _gmx_selparser_error(scanner, ex.what());
-            return ex.errorCode();
-        }
+        /* By default, use whole residues/molecules. */
+        sel->u.expr.pc
+            = pcc->createCalculationFromEnum(rpost, POS_COMPLWHOLE);
     }
     else
     {
+        // TODO: Should this be treated as a real error?
         _gmx_selparser_error(scanner, "modifier '%s' is not applicable for '%s'",
                              rpost, sel->u.expr.method->name);
     }
-    return 0;
 }
 
 /*!
@@ -717,7 +713,6 @@ _gmx_sel_init_keyword(gmx_ana_selmethod_t *method, t_selexpr_value *args,
     t_selexpr_param   *params, *param;
     t_selexpr_value   *arg;
     int                nargs;
-    int                rc;
 
     gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
     char  buf[128];
@@ -774,10 +769,14 @@ _gmx_sel_init_keyword(gmx_ana_selmethod_t *method, t_selexpr_value *args,
             goto on_error;
         }
     }
-    rc = set_refpos_type(&sc->pcc, child, rpost, scanner);
-    if (rc != 0)
+    try
     {
-        goto on_error;
+        set_refpos_type(&sc->pcc, child, rpost, scanner);
+    }
+    catch (const std::exception &)
+    {
+        _gmx_selelem_free(root);
+        throw;
     }
 
     return root;
@@ -833,11 +832,14 @@ _gmx_sel_init_method(gmx_ana_selmethod_t *method, t_selexpr_param *params,
         _gmx_selelem_free(root);
         return NULL;
     }
-    rc = set_refpos_type(&sc->pcc, root, rpost, scanner);
-    if (rc != 0)
+    try
+    {
+        set_refpos_type(&sc->pcc, root, rpost, scanner);
+    }
+    catch (const std::exception &)
     {
         _gmx_selelem_free(root);
-        return NULL;
+        throw;
     }
 
     return root;
index 402f467bb763a266f508d76f0513118bb69b33be..41e2d1dbe28f687de3e2b2e4df269d10fad79277 100644 (file)
@@ -47,6 +47,8 @@
 #ifndef SELECTION_PARSETREE_H
 #define SELECTION_PARSETREE_H
 
+#include <exception>
+
 #include <types/simple.h>
 
 #include "gromacs/selection/selvalue.h"
@@ -110,6 +112,9 @@ typedef struct t_selexpr_param
 /** Error reporting function for the selection parser. */
 void
 _gmx_selparser_error(void *scanner, const char *fmt, ...);
+/** Handle exceptions caught within the Bison code. */
+bool
+_gmx_selparser_handle_exception(void *scanner, const std::exception &ex);
 
 /** Allocates and initializes a constant \c t_selexpr_value. */
 t_selexpr_value *
index 5c7f62316601f737309f0332d82b9a74ae15b69d..7d3bfa9442ece413c2f47e4a7c72bc62525a2250 100644 (file)
 #ifndef SELECTION_SCANNER_H
 #define SELECTION_SCANNER_H
 
+#include <boost/exception_ptr.hpp>
+
+#include "parser.h"
+
 namespace gmx
 {
 class MessageStringCollector;
 }
 
-#include "parser.h"
-
 struct gmx_ana_indexgrps_t;
 struct gmx_ana_selcollection_t;
 
@@ -65,6 +67,15 @@ _gmx_sel_free_lexer(yyscan_t scanner);
 void
 _gmx_sel_set_lexer_error_reporter(yyscan_t scanner,
                                   gmx::MessageStringCollector *errors);
+/** Stores an exception that is caught during parsing. */
+void
+_gmx_sel_lexer_set_exception(yyscan_t scanner,
+                             const boost::exception_ptr &ex);
+/** Rethrows and clears the stored exception if one is present. */
+// TODO: The semantics is a bit confusing, need to be thought more,
+// but easier to do as part of larger refactoring of the parsing.
+void
+_gmx_sel_lexer_rethrow_exception_if_occurred(yyscan_t scanner);
 
 /** Returns true if the scanner is interactive. */
 bool
index f11b1ed44c76ceabaa8fe33e3860149b42cd4736..615385d7a9ae698293a63a6d78df94ccc98a1a55 100644 (file)
@@ -374,8 +374,6 @@ _gmx_sel_init_lexer(yyscan_t *scannerp, struct gmx_ana_selcollection_t *sc,
                     bool bInteractive, int maxnr, bool bGroups,
                     struct gmx_ana_indexgrps_t *grps)
 {
-    gmx_sel_lexer_t *state;
-
     int rc = _gmx_sel_yylex_init(scannerp);
     if (rc != 0)
     {
@@ -383,7 +381,8 @@ _gmx_sel_init_lexer(yyscan_t *scannerp, struct gmx_ana_selcollection_t *sc,
         GMX_THROW(gmx::InternalError("Lexer initialization failed"));
     }
 
-    snew(state, 1);
+    gmx_sel_lexer_t *state = new gmx_sel_lexer_t;
+
     state->sc        = sc;
     state->errors    = NULL;
     state->bGroups   = bGroups;
@@ -424,7 +423,7 @@ _gmx_sel_free_lexer(yyscan_t scanner)
     {
         _gmx_sel_yy_delete_buffer(state->buffer, scanner);
     }
-    sfree(state);
+    delete state;
     _gmx_sel_yylex_destroy(scanner);
 }
 
@@ -436,6 +435,26 @@ _gmx_sel_set_lexer_error_reporter(yyscan_t scanner,
     state->errors = errors;
 }
 
+void
+_gmx_sel_lexer_set_exception(yyscan_t scanner,
+                             const boost::exception_ptr &ex)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    state->exception = ex;
+}
+
+void
+_gmx_sel_lexer_rethrow_exception_if_occurred(yyscan_t scanner)
+{
+    gmx_sel_lexer_t *state = _gmx_sel_yyget_extra(scanner);
+    if (state->exception)
+    {
+        boost::exception_ptr ex = state->exception;
+        state->exception = boost::exception_ptr();
+        rethrow_exception(ex);
+    }
+}
+
 bool
 _gmx_sel_is_lexer_interactive(yyscan_t scanner)
 {
index e8fe599a00685bda930ef1c30342eccd5f3255f1..1afd5c3b803a87230ef65612fe9e3b01d7ba719b 100644 (file)
 #ifndef SELECTION_SCANNER_INTERNAL_H
 #define SELECTION_SCANNER_INTERNAL_H
 
+#include <boost/exception_ptr.hpp>
+
+#include "parser.h"
+
 namespace gmx
 {
 class MessageStringCollector;
 }
 
-#include "parser.h"
-
 /* These need to be defined before including scanner_flex.h, because it
  * uses YY_EXTRA_TYPE. But we also need to include it before defining
  * gmx_sel_lexer_t; hence the forward declaration. */
@@ -68,6 +70,8 @@ typedef struct gmx_sel_lexer_t
     struct gmx_ana_selcollection_t  *sc;
     //! Error reporter object.
     gmx::MessageStringCollector     *errors;
+    //! Stores an exception that occurred during parsing.
+    boost::exception_ptr             exception;
     //! Whether external index groups have been set.
     bool                             bGroups;
     //! External index groups for resolving \c group keywords.
index 12bd304b5d8b4483ed8dd5c7db49d47288ffc7b5..26acaea4fa2b942e750f9af55efcb841dfd4bc25 100644 (file)
@@ -182,6 +182,7 @@ int runParserLoop(yyscan_t scanner, _gmx_sel_yypstate *parserState,
         status = _gmx_sel_yypush_parse(parserState, token, &value, scanner);
     }
     while (status == YYPUSH_MORE);
+    _gmx_sel_lexer_rethrow_exception_if_occurred(scanner);
     return status;
 }
 
@@ -239,6 +240,7 @@ SelectionList runParser(yyscan_t scanner, bool bStdIn, int maxnr)
             }
             status = _gmx_sel_yypush_parse(parserState.get(), 0, NULL,
                                            scanner);
+            _gmx_sel_lexer_rethrow_exception_if_occurred(scanner);
 early_termination:
             bOk = (status == 0);
         }