* data/glr.c (YYERROR): Update definition.

(yyrecoverSyntaxError): Correct yyerrState logic. Correct comment.
Allow states with only a default reduction.

Fixes to avoid problem that $-N rules in GLR parsers can cause
buffer overruns, corrupting state.

* src/output.c (prepare_rules): Output max_left_semantic_context.
* src/reader.h (max_left_semantic_context): New
* src/scan-gram.l (max_left_semantic_context): Define.
(handle_action_dollar): Update max_left_semantic_context.
* data/glr.c (YYMAXLEFT): New.
(yydoAction): Increase yyrhsVals size.
(yyresolveAction): Ditto.

Fixes to problems with location handling in GLR parsers reported by
Frank Heckenbach (2003/06/05).

* data/glr.c (YYLTYPE): Make trivial if locations not used.
(YYRHSLOC): Add parentheses, make depend on whether locations used.
(YYLLOC_DEFAULT): Ditto.
(yyuserAction): Use YYLLOC_DEFAULT.
(yydoAction): Remove redundant code.

* tests/cxx-type.at: Exercise location information.
(yylex): Track locations.
(stmtMerge): Return value rather than printing.
This commit is contained in:
Paul Hilfinger
2003-06-10 02:44:58 +00:00
parent 144c1e767a
commit 25005f6ab0
6 changed files with 240 additions and 144 deletions

View File

@@ -1,3 +1,46 @@
2003-06-09 Paul Hilfinger <Hilfinger@CS.Berkeley.EDU>
* data/glr.c (YYERROR): Update definition to reset yyerrState to 0
first.
(yyrecoverSyntaxError): Correct the logic for setting and testing
yyerrState.
Correct comment on handling EOF.
Allow states with only a default reduction, rather than failing
(I can't quite reconstruct why these were not allowed before).
Fixes to avoid problem that $-N rules in GLR parsers can cause
buffer overruns, corrupting state.
* src/output.c (prepare_rules): Output max_left_semantic_context
definition.
* src/reader.h (max_left_semantic_context): New variable declaration.
* src/scan-gram.l (max_left_semantic_context): Define.
(handle_action_dollar): Update max_left_semantic_context.
* data/glr.c (YYMAXLEFT): New definition.
(yydoAction): Increase size of yyrhsVals by YYMAXLEFT.
(yyresolveAction): Ditto.
Fixes to problems with location handling in GLR parsers reported by
Frank Heckenbach (2003/06/05).
* data/glr.c (YYLTYPE): Make trivial if locations not used.
(YYRHSLOC): Add parentheses, and define only if locations used.
(YYLLOC_DEFAULT): Add parentheses, and give trivial definition if
locations not used.
(yyuserAction): Use YYLLOC_DEFAULT to set *yylocp.
(yydoAction): Remove redundant initialization of *yyvalp and *yylocp.
* tests/cxx-type.at: Exercise location information; update tests
to differentiate output with and without locations.
Remove forward declarations of yylex and yyerror---caused errors
because default YYLTYPE not yet defined.
Change semantic actions to compute strings, rather than printing
them directly (to test proper passing of semantics values). Change
output to prefix notation and update test data and expected results.
(yylex): Track locations.
(stmtMerge): Return value rather than printing, and include arguments
in value.
2003-06-03 Paul Eggert <eggert@twinsun.com>
Avoid warnings generated by GCC 2.95.4 when Bison is

View File

@@ -192,10 +192,12 @@ b4_syncline([@oline@], [@ofile@])],
#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED)
typedef struct YYLTYPE
{
]b4_location_if([
int first_line;
int first_column;
int last_line;
int last_column;
])[
} YYLTYPE;
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
@@ -254,6 +256,9 @@ b4_syncline([@oline@], [@ofile@])
#define YYNSTATES ]b4_states_number[
/* YYMAXRHS -- Maximum number of symbols on right-hand side of rule. */
#define YYMAXRHS ]b4_r2_max[
/* YYMAXLEFT -- Maximum number of symbols to the left of a handle
accessed by $0, $-1, etc., in any rule. */
#define YYMAXLEFT ]b4_max_left_semantic_context[
/* YYTRANSLATE(X) -- Bison symbol number corresponding to X. */
#define YYUNDEFTOK ]b4_undef_token_number[
@@ -402,15 +407,22 @@ static const ]b4_int_type_for([b4_stos])[ yystos[] =
/* YYLLOC_DEFAULT -- Compute the default location (before the actions
are run). */
#define YYRHSLOC(yyRhs,YYK) (yyRhs[YYK].yystate.yyloc)
]b4_location_if([[
#define YYRHSLOC(yyRhs,YYK) ((yyRhs)[YYK].yystate.yyloc)
#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(yyCurrent, yyRhs, YYN) \
yyCurrent.first_line = YYRHSLOC(yyRhs,1).first_line; \
yyCurrent.first_column = YYRHSLOC(yyRhs,1).first_column; \
yyCurrent.last_line = YYRHSLOC(yyRhs,YYN).last_line; \
yyCurrent.last_column = YYRHSLOC(yyRhs,YYN).last_column;
(yyCurrent).first_line = YYRHSLOC(yyRhs,1).first_line; \
(yyCurrent).first_column = YYRHSLOC(yyRhs,1).first_column; \
(yyCurrent).last_line = YYRHSLOC(yyRhs,YYN).last_line; \
(yyCurrent).last_column = YYRHSLOC(yyRhs,YYN).last_column;
#endif
]],[
#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(yyCurrent, yyRhs, YYN)
#endif
])[
/* YYLEX -- calling `yylex' with the right arguments. */
#define YYLEX ]b4_c_function_call([yylex], [int], b4_lex_param)[
@@ -663,16 +675,6 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
yybool yynormal ATTRIBUTE_UNUSED = (yystack->yysplitPoint == NULL);
int yylow;
if (yyrhslen == 0)
{
*yyvalp = yyval_default;
*yylocp = yyloc_default;
}
else
{
*yyvalp = yyvsp[1-yyrhslen].yystate.yysemantics.yysval;
*yylocp = yyvsp[1-yyrhslen].yystate.yyloc;
}
# undef yyerrok
# define yyerrok (yystack->yyerrState = 0)
# undef YYACCEPT
@@ -680,7 +682,7 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
# undef YYABORT
# define YYABORT return yyabort
# undef YYERROR
# define YYERROR return yyerr
# define YYERROR do { yystack->yyerrState = 0; return yyerr; } while (0)
# undef YYRECOVERING
# define YYRECOVERING (yystack->yyerrState != 0)
# undef yyclearin
@@ -694,14 +696,25 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
YYERROR; \
} while (0)
]
yylow = 1;
switch (yyn)
{
b4_actions
}
yylow = 1;
if (yyrhslen == 0)
{
*yyvalp = yyval_default;
*yylocp = yyloc_default;
}
else
{
*yyvalp = yyvsp[YYFILL (1-yyrhslen)].yystate.yysemantics.yysval;
YYLLOC_DEFAULT (*yylocp, yyvsp - yyrhslen, yyrhslen);
}
return yyok;
]
switch (yyn)
{
b4_actions
}
return yyok;
# undef yyerrok
# undef YYABORT
# undef YYACCEPT
@@ -1080,16 +1093,6 @@ yydoAction (yyGLRStack* yystack, int yyk, yyRuleNum yyrule,
yystack->yynextFree -= yynrhs;
yystack->yyspaceLeft += yynrhs;
yystack->yytops.yystates[0] = & yystack->yynextFree[-1].yystate;
if (yynrhs == 0)
{
*yyvalp = yyval_default;
*yylocp = yyloc_default;
}
else
{
*yyvalp = rhs[1-yynrhs].yystate.yysemantics.yysval;
*yylocp = rhs[1-yynrhs].yystate.yyloc;
}
return yyuserAction (yyrule, yynrhs, rhs,
yyvalp, yylocp, yystack]b4_user_args[);
}
@@ -1097,8 +1100,9 @@ yydoAction (yyGLRStack* yystack, int yyk, yyRuleNum yyrule,
{
int yyi;
yyGLRState* yys;
yyGLRStackItem yyrhsVals[YYMAXRHS+1];
yys = yyrhsVals[YYMAXRHS].yystate.yypred = yystack->yytops.yystates[yyk];
yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
yys = yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred
= yystack->yytops.yystates[yyk];
for (yyi = 0; yyi < yynrhs; yyi += 1)
{
yys = yys->yypred;
@@ -1107,17 +1111,7 @@ yydoAction (yyGLRStack* yystack, int yyk, yyRuleNum yyrule,
}
yyupdateSplit (yystack, yys);
yystack->yytops.yystates[yyk] = yys;
if (yynrhs == 0)
{
*yyvalp = yyval_default;
*yylocp = yyloc_default;
}
else
{
*yyvalp = yyrhsVals[1].yystate.yysemantics.yysval;
*yylocp = yyrhsVals[1].yystate.yyloc;
}
return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS - 1,
return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
yyvalp, yylocp, yystack]b4_user_args[);
}
}
@@ -1348,13 +1342,14 @@ static YYRESULTTAG
yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystack,
YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
{
yyGLRStackItem yyrhsVals[YYMAXRHS+1];
yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
int yynrhs;
yynrhs = yyrhsLength (yyopt->yyrule);
YYCHK (yyresolveStates (yyopt->yystate, yynrhs, yystack]b4_user_args[));
yyrhsVals[YYMAXRHS].yystate.yypred = yyopt->yystate;
return yyuserAction (yyopt->yyrule, yynrhs, yyrhsVals + YYMAXRHS - 1,
yyrhsVals[YYMAXRHS + YYMAXLEFT].yystate.yypred = yyopt->yystate;
return yyuserAction (yyopt->yyrule, yynrhs,
yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
yyvalp, yylocp, yystack]b4_user_args[);
}
@@ -1687,17 +1682,14 @@ yyrecoverSyntaxError (yyGLRStack* yystack,
size_t yyk;
int yyj;
if (yystack->yyerrState == 0)
yystack->yyerrState = 3;
else if (yystack->yyerrState == 3)
if (yystack->yyerrState == 3)
/* We just shifted the error token and (perhaps) took some
reductions. Skip tokens until we can proceed. */
while (yytrue)
{
if (*yytokenp == YYEOF)
{
/* Now pop stack until we find a state that shifts the
error token. */
/* Now pop stack until empty and fail. */
while (yystack->yytops.yystates[0] != NULL)
{
yyGLRState *yys = yystack->yytops.yystates[0];
@@ -1723,8 +1715,7 @@ yyrecoverSyntaxError (yyGLRStack* yystack,
YYDSYMPRINTF ("Next token is", *yytokenp, yylvalp, yyllocp);
yyj = yypact[yystack->yytops.yystates[0]->yylrState];
if (yyis_pact_ninf (yyj))
/* Something's not right; we shouldn't be here. */
yyFail (yystack][]b4_lpure_args[, NULL);
return;
yyj += *yytokenp;
if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != *yytokenp)
{
@@ -1747,6 +1738,7 @@ yyrecoverSyntaxError (yyGLRStack* yystack,
yycompressStack (yystack);
/* Now pop stack until we find a state that shifts the error token. */
yystack->yyerrState = 3;
while (yystack->yytops.yystates[0] != NULL)
{
yyGLRState *yys = yystack->yytops.yystates[0];
@@ -2016,20 +2008,21 @@ b4_syncline([@oline@], [@ofile@])],
b4_pure_if([],
[extern YYSTYPE b4_prefix[]lval;])
b4_location_if(
[#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED)
#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED)
typedef struct YYLTYPE
{
b4_location_if([
int first_line;
int first_column;
int last_line;
int last_column;
])
} YYLTYPE;
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
#endif
m4_if(b4_pure, [0],
b4_location_if([m4_if(b4_pure, [0],
[extern YYLTYPE b4_prefix[]lloc;])
])
])

View File

@@ -253,6 +253,7 @@ prepare_rules (void)
muscle_insert_short_table ("merger", merger, 0, 0, nrules);
MUSCLE_INSERT_INT ("rules_number", nrules);
MUSCLE_INSERT_INT ("max_left_semantic_context", max_left_semantic_context);
free (rhs);
free (prhs);

View File

@@ -38,6 +38,7 @@ typedef struct merger_list
extern FILE *gram_in;
extern int gram__flex_debug;
extern boundary scanner_cursor;
extern int max_left_semantic_context;
void scanner_initialize (void);
void scanner_free (void);
void scanner_last_string_free (void);

View File

@@ -649,6 +649,11 @@ splice (\\[ \f\t\v]*\n)*
%%
/* Keeps track of the maximum number of semantic values to the left of
a handle (those referenced by $0, $-1, etc.) are required by the
semantic actions of this grammar. */
int max_left_semantic_context = 0;
/* Set *LOC and adjust scanner cursor to account for token TOKEN of
size SIZE. */
@@ -781,6 +786,8 @@ handle_action_dollar (char *text, location loc)
if (INT_MIN <= num && num <= rule_length && ! get_errno ())
{
int n = num;
if (1-n > max_left_semantic_context)
max_left_semantic_context = 1-n;
if (!type_name && n > 0)
type_name = symbol_list_n_type_name_get (current_rule, loc, n);
if (!type_name && typed)

View File

@@ -24,7 +24,10 @@ AT_BANNER([[C++ Type Syntax (GLR).]])
# and with RESOLVE1 and RESOLVE2 as annotations on the conflicted rule for
# stmt. Then compile the result.
m4_define([_AT_TEST_GLR_CXXTYPES],
[AT_DATA_GRAMMAR([types.y],
[
AT_BISON_OPTION_PUSHDEFS([$1])
AT_DATA_GRAMMAR([types.y],
[[/* Simplified C++ Type and Expression Grammar. */
$1
@@ -32,24 +35,10 @@ $1
%{
#include <stdio.h>
#define YYSTYPE const char*
#define YYLTYPE int
]m4_bmatch([$2], [stmtMerge],
[ static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);])[
#define YYINITDEPTH 10
int yyerror (
#if YYPURE && YYLSP_NEEDED
YYLTYPE *yylocation,
#endif
const char *s
);
#if YYPURE
]m4_bmatch([$1], [location],
[ int yylex (YYSTYPE *lvalp, YYLTYPE *llocp);],
[ int yylex (YYSTYPE *lvalp);])[
#else
int yylex (void);
#endif
static char* format (const char*, ...);
%}
@@ -63,30 +52,35 @@ $1
%%
prog :
| prog stmt { printf ("\n"); }
| prog stmt {
]AT_LOCATION_IF([
printf ("%d.%d-%d.%d: ",
@2.first_line, @2.first_column,
@2.last_line, @2.last_column);])[
printf ("%s\n", ]$[2);
}
;
stmt : expr ';' $2
stmt : expr ';' $2 { $$ = ]$[1; }
| decl $3
| error ';'
| '@' { YYACCEPT; }
| error ';' { $$ = "<error>"; }
| '@' { YYACCEPT; }
;
expr : ID { printf ("%s ", ]$[1); }
| TYPENAME '(' expr ')'
{ printf ("%s <cast> ", ]$[1); }
| expr '+' expr { printf ("+ "); }
| expr '=' expr { printf ("= "); }
expr : ID
| TYPENAME '(' expr ')' { $$ = format ("<cast>(%s,%s)", ]$[3, ]$[1); }
| expr '+' expr { $$ = format ("+(%s,%s)", ]$[1, ]$[3); }
| expr '=' expr { $$ = format ("=(%s,%s)", ]$[1, ]$[3); }
;
decl : TYPENAME declarator ';'
{ printf ("%s <declare> ", ]$[1); }
{ $$ = format ("<declare>(%s,%s)", ]$[1, ]$[2); }
| TYPENAME declarator '=' expr ';'
{ printf ("%s <init-declare> ", ]$[1); }
{ $$ = format ("<init-declare>(%s,%s,%s)", ]$[1, ]$[2, ]$[4); }
;
declarator : ID { printf ("\"%s\" ", ]$[1); }
| '(' declarator ')'
declarator : ID
| '(' declarator ')' { $$ = ]$[2; }
;
%%
@@ -94,6 +88,7 @@ declarator : ID { printf ("\"%s\" ", ]$[1); }
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
int
main (int argc, char** argv)
@@ -105,23 +100,25 @@ main (int argc, char** argv)
exit (yyparse ());
}
#if YYPURE
int
]m4_bmatch([$1], [location],
[yylex (YYSTYPE *lvalp, YYLTYPE *llocp)],
[yylex (YYSTYPE *lvalp)])[
#if YYPURE && YYLSP_NEEDED
yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
#elif YYPURE
yylex (YYSTYPE *lvalp)
#else
int
yylex ()
yylex ()
#endif
{
char buffer[256];
int c;
unsigned int i;
static int lineNum = 1;
static int colNum = 1;
#if YYPURE
# define yylloc (*llocp)
# define yylval (*lvalp)
]m4_bmatch([$1], [location],[ (void) llocp;])[
#endif
while (1)
@@ -131,28 +128,53 @@ yylex ()
{
case EOF:
return 0;
case ' ': case '\t': case '\n': case '\f':
case '\t':
colNum = 1 + ((colNum + 7) & ~7);
break;
case ' ': case '\f':
colNum += 1;
break;
case '\n':
lineNum += 1;
colNum = 1;
break;
default:
if (isalpha (c))
{
i = 0;
{
int tok;
#if YYLSP_NEEDED
yylloc.first_line = yylloc.last_line = lineNum;
yylloc.first_column = colNum;
#endif
if (isalpha (c))
{
i = 0;
do
{
buffer[i++] = c;
if (i == sizeof buffer - 1)
abort ();
c = getchar ();
}
while (isalnum (c) || c == '_');
do
{
buffer[i++] = c;
colNum += 1;
if (i == sizeof buffer - 1)
abort ();
c = getchar ();
}
while (isalnum (c) || c == '_');
ungetc (c, stdin);
buffer[i++] = 0;
yylval = strcpy (malloc (i), buffer);
return isupper ((unsigned char) buffer[0]) ? TYPENAME : ID;
}
return c;
ungetc (c, stdin);
buffer[i++] = 0;
tok = isupper ((unsigned char) buffer[0]) ? TYPENAME : ID;
yylval = strcpy (malloc (i), buffer);
}
else
{
colNum += 1;
tok = c;
yylval = "";
}
#if YYLSP_NEEDED
yylloc.last_column = colNum-1;
#endif
return tok;
}
}
}
}
@@ -160,28 +182,32 @@ yylex ()
int
yyerror (
#if YYPURE && YYLSP_NEEDED
YYLTYPE *yylocation,
YYLTYPE *llocp,
#endif
const char *s
)
{
#if YYPURE && YYLSP_NEEDED
(void) *yylocation;
#endif
fprintf (stderr, "%s\n", s);
return 0;
}
static char* format (const char* form, ...)
{
char buffer[1024];
va_list args;
va_start (args, form);
vsprintf (buffer, form, args);
va_end (args);
return strcpy (malloc (strlen (buffer) + 1), buffer);
}
]]
m4_bmatch([$2], [stmtMerge],
[[static YYSTYPE
stmtMerge (YYSTYPE x0, YYSTYPE x1)
{
/* Use the arguments. */
(void) x0;
(void) x1;
printf ("<OR> ");
return "";
return format ("<OR>(%s,%s)", x0, x1);
}
]])
)
@@ -214,30 +240,55 @@ This is total garbage, but it should be ignored.
AT_CHECK([bison -o types.c types.y], 0, [], ignore)
AT_COMPILE([types])
AT_BISON_OPTION_POPDEFS
])
m4_define([_AT_RESOLVED_GLR_OUTPUT],
[[z q +
"x" T <declare>
"x" y T <init-declare>
x y =
x T <cast> y +
"x" T <declare>
"y" z q + T <init-declare>
y
z q +
[[+(z,q)
<declare>(T,x)
<init-declare>(T,x,y)
=(x,y)
+(<cast>(x,T),y)
<declare>(T,x)
<init-declare>(T,y,+(z,q))
<error>
+(z,q)
]])
m4_define([_AT_RESOLVED_GLR_OUTPUT_WITH_LOC],
[[3.1-3.6: +(z,q)
5.1-5.4: <declare>(T,x)
7.1-7.8: <init-declare>(T,x,y)
9.1-9.6: =(x,y)
11.1-11.10: +(<cast>(x,T),y)
13.1-13.6: <declare>(T,x)
15.1-15.14: <init-declare>(T,y,+(z,q))
17.6-17.16: <error>
19.1-19.6: +(z,q)
]])
m4_define([_AT_AMBIG_GLR_OUTPUT],
[[z q +
"x" T <declare>
"x" y T <init-declare>
x y =
x T <cast> y +
"x" T <declare> x T <cast> <OR>
"y" z q + T <init-declare> y T <cast> z q + = <OR>
y
z q +
[[+(z,q)
<declare>(T,x)
<init-declare>(T,x,y)
=(x,y)
+(<cast>(x,T),y)
<OR>(<declare>(T,x),<cast>(x,T))
<OR>(<init-declare>(T,y,+(z,q)),=(<cast>(y,T),+(z,q)))
<error>
+(z,q)
]])
m4_define([_AT_AMBIG_GLR_OUTPUT_WITH_LOC],
[[3.1-3.6: +(z,q)
5.1-5.4: <declare>(T,x)
7.1-7.8: <init-declare>(T,x,y)
9.1-9.6: =(x,y)
11.1-11.10: +(<cast>(x,T),y)
13.1-13.6: <OR>(<declare>(T,x),<cast>(x,T))
15.1-15.14: <OR>(<init-declare>(T,y,+(z,q)),=(<cast>(y,T),+(z,q)))
17.6-17.16: <error>
19.1-19.6: +(z,q)
]])
m4_define([_AT_GLR_STDERR],
@@ -262,7 +313,7 @@ AT_CLEANUP
AT_SETUP([GLR: Resolve ambiguity, impure, locations])
_AT_TEST_GLR_CXXTYPES([%locations],[%dprec 1],[%dprec 2])
AT_PARSER_CHECK([[./types test-input | sed 's/ *$//']], 0,
_AT_RESOLVED_GLR_OUTPUT, _AT_GLR_STDERR)
_AT_RESOLVED_GLR_OUTPUT_WITH_LOC, _AT_GLR_STDERR)
AT_CLEANUP
AT_SETUP([GLR: Resolve ambiguity, pure, no locations])
@@ -276,7 +327,7 @@ AT_SETUP([GLR: Resolve ambiguity, pure, locations])
_AT_TEST_GLR_CXXTYPES([%pure-parser %locations],
[%dprec 1], [%dprec 2])
AT_PARSER_CHECK([[./types test-input | sed 's/ *$//']], 0,
_AT_RESOLVED_GLR_OUTPUT, _AT_GLR_STDERR)
_AT_RESOLVED_GLR_OUTPUT_WITH_LOC, _AT_GLR_STDERR)
AT_CLEANUP
AT_SETUP([GLR: Merge conflicting parses, impure, no locations])
@@ -290,7 +341,7 @@ AT_SETUP([GLR: Merge conflicting parses, impure, locations])
_AT_TEST_GLR_CXXTYPES([%locations],
[%merge <stmtMerge>], [%merge <stmtMerge>])
AT_PARSER_CHECK([[./types test-input | sed 's/ *$//']], 0,
_AT_AMBIG_GLR_OUTPUT, _AT_GLR_STDERR)
_AT_AMBIG_GLR_OUTPUT_WITH_LOC, _AT_GLR_STDERR)
AT_CLEANUP
AT_SETUP([GLR: Merge conflicting parses, pure, no locations])
@@ -303,7 +354,7 @@ AT_SETUP([GLR: Merge conflicting parses, pure, locations])
_AT_TEST_GLR_CXXTYPES([%pure-parser %locations],
[%merge <stmtMerge>],[%merge <stmtMerge>])
AT_PARSER_CHECK([[./types test-input | sed 's/ *$//']], 0,
_AT_AMBIG_GLR_OUTPUT, _AT_GLR_STDERR)
_AT_AMBIG_GLR_OUTPUT_WITH_LOC, _AT_GLR_STDERR)
AT_CLEANUP
AT_SETUP([GLR: Verbose messages, resolve ambiguity, impure, no locations])