@@ -283,6 +283,25 @@ class glr_state;
283
283
static std::string symbol_name (symbol_kind_type yysymbol);]])[
284
284
285
285
]b4_token_constructor_define[
286
+ ]b4_parse_error_bmatch([custom\| detailed\| verbose], [[
287
+ class context
288
+ {
289
+ public:
290
+ context (glr_stack& yystack, const symbol_type& yyla);
291
+ const symbol_type& lookahead () const YY_NOEXCEPT { return yyla_; }
292
+ symbol_kind_type token () const YY_NOEXCEPT { return yyla_.kind (); }]b4_locations_if([[
293
+ const location_type& location () const YY_NOEXCEPT { return yyla_.location; }
294
+ ]])[
295
+ /// Put in YYARG at most YYARGN of the expected tokens, and return the
296
+ /// number of tokens stored in YYARG. If YYARG is null, return the
297
+ /// number of expected tokens (guaranteed to be less than YYNTOKENS).
298
+ int expected_tokens (symbol_kind_type yyarg[], int yyargn) const;
299
+
300
+ private:
301
+ glr_stack& yystack_;
302
+ const symbol_type& yyla_;
303
+ };
304
+ ]])[
286
305
# if ]b4_api_PREFIX[DEBUG
287
306
public:
288
307
/// \b rief Report a symbol value on the debug stream.
@@ -304,7 +323,22 @@ class glr_state;
304
323
std::ostream* yycdebug_;
305
324
#endif
306
325
307
- public: // FIXME: Private
326
+ ]b4_parse_error_bmatch(
327
+ [custom], [[
328
+ private:
329
+ /// Report a syntax error
330
+ /// \p aram yyctx the context in which the error occurred.
331
+ void report_syntax_error (const context& yyctx) const;]],
332
+ [detailed\| verbose], [[
333
+ private:
334
+ /// The arguments of the error message.
335
+ int yy_syntax_error_arguments_ (const context& yyctx,
336
+ symbol_kind_type yyarg[], int yyargn) const;
337
+
338
+ /// Generate an error message.
339
+ /// \p aram yyctx the context in which the error occurred.
340
+ virtual std::string yysyntax_error_ (const context& yyctx) const;]])[
341
+
308
342
/// Convert a scanner token kind \a t to a symbol kind.
309
343
/// In theory \a t should be a token_kind_type, but character literals
310
344
/// are valid, yet not members of the token_kind_type enum.
@@ -2020,6 +2054,12 @@ class glr_stack
2020
2054
typedef parser_type::value_type value_type;]b4_locations_if([[
2021
2055
typedef parser_type::location_type location_type;]])[
2022
2056
2057
+ ]b4_parse_error_bmatch([custom\|detailed\|verbose], [[
2058
+ typedef parser_type::context context;
2059
+ // Needs access to yypact_value_is_default, etc.
2060
+ friend context;
2061
+ ]])[
2062
+
2023
2063
glr_stack (size_t yysize, ]b4_namespace_ref[::]b4_parser_class[& yyparser_yyarg]m4_ifset([b4_parse_param], [, b4_parse_param_decl])[)
2024
2064
: yyerrState (0 )
2025
2065
, yystateStack (yysize)
@@ -2293,109 +2333,26 @@ b4_dollar_popdef])[]dnl
2293
2333
yystateStack.dumpStack ();
2294
2334
}
2295
2335
#endif
2336
+
2296
2337
void
2297
2338
yyreportSyntaxError ()
2298
2339
{
2299
2340
if (yyerrState != 0 )
2300
2341
return ;
2301
- ]b4_parse_error_bmatch (
2302
- [simple],
2303
- [[ yyparser.error (]b4_locations_if ([this ->yyla .location , ])[YY_ (" syntax error" ));]],
2304
- [[ {
2305
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
2306
- /* Arguments of yyformat. */
2307
- yysymbol_kind_t yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]
2308
- = { ]b4_symbol (empty, kind)[ };
2309
- /* Number of reported tokens (one for the "unexpected", one per
2310
- "expected"). */
2311
- int yycount = 0 ;
2312
-
2313
- /* There are many possibilities here to consider:
2314
- - If this state is a consistent state with a default action, then
2315
- the only way this function was invoked is if the default action
2316
- is an error action. In that case, don't check for expected
2317
- tokens because there are none.
2318
- - The only way there can be no lookahead present (in yytoken) is if
2319
- this state is a consistent state with a default action. Thus,
2320
- detecting the absence of a lookahead is sufficient to determine
2321
- that there is no unexpected or expected token to report. In that
2322
- case, just report a simple "syntax error".
2323
- - Don't assume there isn't a lookahead just because this state is a
2324
- consistent state with a default action. There might have been a
2325
- previous inconsistent state, consistent state with a non-default
2326
- action, or user semantic action that manipulated yytoken.
2327
- - Of course, the expected token list depends on states to have
2328
- correct lookahead information, and it depends on the parser not
2329
- to perform extra reductions after fetching a lookahead from the
2330
- scanner and before detecting a syntax error. Thus, state merging
2331
- (from LALR or IELR) and default reductions corrupt the expected
2332
- token list. However, the list is correct for canonical LR with
2333
- one exception: it will still contain any token that will not be
2334
- accepted due to an error action in a later state.
2335
- */
2336
- if (!yyla.empty ())
2337
- {
2338
- const int yyn = yypact[firstTopState ()->yylrState ];
2339
- yyarg[yycount++] = yyla.kind ();
2340
- if (!yypact_value_is_default (yyn))
2341
- {
2342
- /* Start YYX at -YYN if negative to avoid negative indexes in
2343
- YYCHECK. In other words, skip the first -YYN actions for this
2344
- state because they are default actions. */
2345
- const int yyxbegin = yyn < 0 ? -yyn : 0 ;
2346
- /* Stay within bounds of both yycheck and yytname. */
2347
- const int yychecklim = YYLAST - yyn + 1 ;
2348
- const int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
2349
- for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
2350
- if (yycheck[yyx + yyn] == yyx && yyx != ]b4_symbol (error, kind)[
2351
- && !yytable_value_is_error (yytable[yyx + yyn]))
2352
- {
2353
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
2354
- {
2355
- yycount = 1 ;
2356
- break ;
2357
- }
2358
- yyarg[yycount++] = static_cast <yysymbol_kind_t >(yyx);
2359
- }
2360
- }
2361
- }
2362
-
2363
- /* Internationalized format string. */
2364
- const char *yyformat = YY_NULLPTR;
2365
- switch (yycount)
2366
- {
2367
- #define YYCASE_ (N, S ) \
2368
- case N: \
2369
- yyformat = S; \
2370
- break
2371
- default : /* Avoid compiler warnings. */
2372
- YYCASE_ (0 , YY_ (" syntax error" ));
2373
- YYCASE_ (1 , YY_ (" syntax error, unexpected %s" ));
2374
- YYCASE_ (2 , YY_ (" syntax error, unexpected %s, expecting %s" ));
2375
- YYCASE_ (3 , YY_ (" syntax error, unexpected %s, expecting %s or %s" ));
2376
- YYCASE_ (4 , YY_ (" syntax error, unexpected %s, expecting %s or %s or %s" ));
2377
- YYCASE_ (5 , YY_ (" syntax error, unexpected %s, expecting %s or %s or %s or %s" ));
2378
- #undef YYCASE_
2379
- }
2380
-
2381
- std::string yymsg;
2382
- // Argument number.
2383
- std::ptrdiff_t yyi = 0 ;
2384
- for (char const * yyp = yyformat; *yyp; ++yyp)
2385
- if (yyp[0 ] == ' %' && yyp[1 ] == ' s' && yyi < yycount)
2386
- {
2387
- yymsg += ]b4_namespace_ref[::]b4_parser_class[::symbol_name (yyarg[yyi++]);
2388
- ++yyp;
2389
- }
2390
- else
2391
- yymsg += *yyp;
2392
- yyparser.error (]b4_locations_if ([[yyla.location , ]])[yymsg);
2393
- }
2394
- ]])[
2342
+ ]b4_parse_error_case (
2343
+ [simple], [[
2344
+ std::string msg = YY_ (" syntax error" );
2345
+ yyparser.error (]b4_join (b4_locations_if ([yyla.location ]), [[YY_MOVE (msg)]])[);]],
2346
+ [custom], [[
2347
+ context yyctx (*this , yyla);
2348
+ yyparser.report_syntax_error (yyctx);]],
2349
+ [[
2350
+ context yyctx (*this , yyla);
2351
+ std::string msg = yyparser.yysyntax_error_ (yyctx);
2352
+ yyparser.error (]b4_join (b4_locations_if ([yyla.location ]), [[YY_MOVE (msg)]])[);]])[
2395
2353
yyerrcnt += 1 ;
2396
2354
}
2397
2355
2398
-
2399
2356
/* Recover from a syntax error on this, assuming that yytoken,
2400
2357
yylval, and yylloc are the syntactic category, semantic value, and location
2401
2358
of the lookahead. */
@@ -3365,6 +3322,120 @@ static void yypdumpstack (const glr_stack& yystack)
3365
3322
#endif
3366
3323
]])[
3367
3324
3325
+ ]b4_parse_error_bmatch ([custom\|detailed\|verbose], [[
3326
+ // ]b4_parser_class[::context.
3327
+ ]b4_parser_class[::context::context (glr_stack& yystack, const symbol_type& yyla)
3328
+ : yystack_ (yystack)
3329
+ , yyla_ (yyla)
3330
+ {}
3331
+
3332
+ int
3333
+ ]b4_parser_class[::context::expected_tokens (symbol_kind_type yyarg[], int yyargn) const
3334
+ {
3335
+ // Actual number of expected tokens
3336
+ int yycount = 0 ;
3337
+ const int yyn = yypact[yystack_.firstTopState ()->yylrState ];
3338
+ if (!yystack_.yypact_value_is_default (yyn))
3339
+ {
3340
+ /* Start YYX at -YYN if negative to avoid negative indexes in
3341
+ YYCHECK. In other words, skip the first -YYN actions for this
3342
+ state because they are default actions. */
3343
+ const int yyxbegin = yyn < 0 ? -yyn : 0 ;
3344
+ /* Stay within bounds of both yycheck and yytname. */
3345
+ const int yychecklim = YYLAST - yyn + 1 ;
3346
+ const int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
3347
+ for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
3348
+ if (yycheck[yyx + yyn] == yyx && yyx != ]b4_symbol (error, kind)[
3349
+ && !yystack_.yytable_value_is_error (yytable[yyx + yyn]))
3350
+ {
3351
+ if (!yyarg)
3352
+ ++yycount;
3353
+ else if (yycount == yyargn)
3354
+ return 0 ;
3355
+ else
3356
+ yyarg[yycount++] = YY_CAST (symbol_kind_type, yyx);
3357
+ }
3358
+ }
3359
+ if (yyarg && yycount == 0 && 0 < yyargn)
3360
+ yyarg[0 ] = ]b4_symbol (empty, kind)[;
3361
+ return yycount;
3362
+ }
3363
+
3364
+ ]])[
3365
+
3366
+ ]b4_parse_error_bmatch ([detailed\|verbose], [[
3367
+ int
3368
+ ]b4_parser_class[::yy_syntax_error_arguments_ (const context& yyctx,
3369
+ symbol_kind_type yyarg[], int yyargn) const
3370
+ {
3371
+ /* There are many possibilities here to consider:
3372
+ - If this state is a consistent state with a default action, then
3373
+ the only way this function was invoked is if the default action
3374
+ is an error action. In that case, don't check for expected
3375
+ tokens because there are none.
3376
+ - The only way there can be no lookahead present (in yyla) is
3377
+ if this state is a consistent state with a default action.
3378
+ Thus, detecting the absence of a lookahead is sufficient to
3379
+ determine that there is no unexpected or expected token to
3380
+ report. In that case, just report a simple "syntax error".
3381
+ - Don't assume there isn't a lookahead just because this state is
3382
+ a consistent state with a default action. There might have
3383
+ been a previous inconsistent state, consistent state with a
3384
+ non-default action, or user semantic action that manipulated
3385
+ yyla. (However, yyla is currently not documented for users.)
3386
+ */
3387
+
3388
+ if (!yyctx.lookahead ().empty ())
3389
+ {
3390
+ if (yyarg)
3391
+ yyarg[0 ] = yyctx.token ();
3392
+ int yyn = yyctx.expected_tokens (yyarg ? yyarg + 1 : yyarg, yyargn - 1 );
3393
+ return yyn + 1 ;
3394
+ }
3395
+ return 0 ;
3396
+ }
3397
+
3398
+ // Generate an error message.
3399
+ std::string
3400
+ ]b4_parser_class[::yysyntax_error_ (const context& yyctx) const
3401
+ {
3402
+ // Its maximum.
3403
+ enum { YYARGS_MAX = 5 };
3404
+ // Arguments of yyformat.
3405
+ symbol_kind_type yyarg[YYARGS_MAX];
3406
+ int yycount = yy_syntax_error_arguments_ (yyctx, yyarg, YYARGS_MAX);
3407
+
3408
+ char const * yyformat = YY_NULLPTR;
3409
+ switch (yycount)
3410
+ {
3411
+ #define YYCASE_ (N, S ) \
3412
+ case N: \
3413
+ yyformat = S; \
3414
+ break
3415
+ default : // Avoid compiler warnings.
3416
+ YYCASE_ (0 , YY_ (" syntax error" ));
3417
+ YYCASE_ (1 , YY_ (" syntax error, unexpected %s" ));
3418
+ YYCASE_ (2 , YY_ (" syntax error, unexpected %s, expecting %s" ));
3419
+ YYCASE_ (3 , YY_ (" syntax error, unexpected %s, expecting %s or %s" ));
3420
+ YYCASE_ (4 , YY_ (" syntax error, unexpected %s, expecting %s or %s or %s" ));
3421
+ YYCASE_ (5 , YY_ (" syntax error, unexpected %s, expecting %s or %s or %s or %s" ));
3422
+ #undef YYCASE_
3423
+ }
3424
+
3425
+ std::string yyres;
3426
+ // Argument number.
3427
+ std::ptrdiff_t yyi = 0 ;
3428
+ for (char const * yyp = yyformat; *yyp; ++yyp)
3429
+ if (yyp[0 ] == ' %' && yyp[1 ] == ' s' && yyi < yycount)
3430
+ {
3431
+ yyres += symbol_name (yyarg[yyi++]);
3432
+ ++yyp;
3433
+ }
3434
+ else
3435
+ yyres += *yyp;
3436
+ return yyres;
3437
+ }]])[
3438
+
3368
3439
void
3369
3440
]b4_parser_class[::yy_destroy_ (const char * yymsg, symbol_kind_type yykind,
3370
3441
value_type& yyval]b4_locations_if ([[,
0 commit comments