mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-11 05:13:04 +00:00
* data/c.m4 (b4_identification, b4_user_args, b4_parse_param):
New. * data/yacc.m4 (b4_pure_args, b4_Pure_args): New. (b4_parse_param): Remove. Use b4_identification. Propagate b4_pure_args where needed to pass them to yyerror. * data/glr.m4 (b4_parse_param): Remove. (b4_user_formals, b4_pure_args, b4_pure_formals, b4_lpure_args) (b4_lpure_formals): New. Use b4_identification. (YY_USER_FORMALS, YY_USER_ARGS): Remove, replaced by b4_user_formals and b4_user_args. (yyexpandGLRStack, yyFail, yyaddDeferredAction, yyglrShiftDefer) (yyreportAmbiguity): When using a pure parser, also need the location, and the parse-params. Adjust callers. (yyuserAction, yyglrShift, yyreportParseError, yyrecoverParseError): When using a pure parser, also need the parse-params. Adjust callers. * tests/calc.at: Test pure (%pure-parser) and absolutely pure (%pure-parser + %parse-param) LALR and GLR parsers. (AT_CHECK_PUSHDEFS, AT_CHECK_POPDEFS): New, define AT_PARAM_IF, AT_LOCATION_IF, AT_PURE_IF, AT_GLR_IF, AAT_PURE_AND_LOC_IF, AT_GLR_OR_PARAM_IF, AT_YYERROR_ARG_LOC_IF, AT_YYERROR_SEES_LOC_IF. (_AT_DATA_CALC_Y): Equip for purity of yyerror. (_AT_CHECK_CALC_ERROR): Use AT_YYERROR_SEES_LOC_IF. * tests/cxx-type.at (_AT_TEST_GLR_CALC): Equip for yyerror purity. * doc/bison.texinfo: Untabify the whole file. (Parser Function): Document %parse-param, deprecate YYPARSE_PARAM. (Pure Calling): Document %lex-param, deprecate YYLEX_PARAM. (Error Reporting): Adjust to these new directives. Document %error-verbose, deprecate YYERROR_VERBOSE.
This commit is contained in:
145
tests/calc.at
145
tests/calc.at
@@ -26,8 +26,8 @@
|
||||
# ------------------------- #
|
||||
|
||||
|
||||
# _AT_DATA_CALC_Y($1, $2, $3, [CPP-DIRECTIVES])
|
||||
# ---------------------------------------------
|
||||
# _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
|
||||
# -----------------------------------------------
|
||||
# Produce `calc.y'. Don't call this macro directly, because it contains
|
||||
# some occurrences of `$1' etc. which will be interpreted by m4. So
|
||||
# you should call it with $1, $2, and $3 as arguments, which is what
|
||||
@@ -37,7 +37,7 @@ m4_define([_AT_DATA_CALC_Y],
|
||||
[m4_fatal([$0: Invalid arguments: $@])])dnl
|
||||
AT_DATA([calc.y],
|
||||
[[/* Infix notation calculator--calc */
|
||||
|
||||
]$4[
|
||||
%{
|
||||
#include <config.h>
|
||||
/* We don't need perfect functions for these tests. */
|
||||
@@ -63,9 +63,6 @@ int global_count = 0;
|
||||
|
||||
%}
|
||||
|
||||
%parse-param "value_t *result", "result"
|
||||
%parse-param "int *count", "count"
|
||||
|
||||
/* Exercise %union. */
|
||||
%union
|
||||
{
|
||||
@@ -81,16 +78,14 @@ int global_count = 0;
|
||||
# define VAL (yylval)
|
||||
#endif
|
||||
|
||||
#define YYLLOC_FORMAL ]AT_LOCATION_IF([, YYLTYPE *yylloc])[
|
||||
#define YYLLOC_ARG ]AT_LOCATION_IF([, yylloc])[
|
||||
#define USE_YYLLOC ]AT_LOCATION_IF([(void) yylloc;])[
|
||||
|
||||
#if YYPURE
|
||||
# if YYLSP_NEEDED
|
||||
# define LEX_FORMALS YYSTYPE *yylval, YYLTYPE *yylloc
|
||||
# define LEX_ARGS yylval, yylloc
|
||||
# define USE_LEX_ARGS (void) yylval; (void) yylloc;
|
||||
# else
|
||||
# define LEX_FORMALS YYSTYPE *yylval
|
||||
# define LEX_ARGS yylval
|
||||
# define USE_LEX_ARGS (void) yylval
|
||||
# endif
|
||||
# define LEX_FORMALS YYSTYPE *yylval YYLLOC_FORMAL
|
||||
# define LEX_ARGS yylval YYLLOC_ARG
|
||||
# define USE_LEX_ARGS (void) yylval; USE_YYLLOC
|
||||
# define LEX_PRE_FORMALS LEX_FORMALS,
|
||||
# define LEX_PRE_ARGS LEX_ARGS,
|
||||
#else
|
||||
@@ -102,7 +97,13 @@ int global_count = 0;
|
||||
#endif
|
||||
|
||||
static int power (int base, int exponent);
|
||||
static void yyerror (const char *s);
|
||||
/* yyerror receives the location if:
|
||||
- %location & %pure & %glr
|
||||
- %location & %pure & %yacc & %parse-param. */
|
||||
static void yyerror (const char *s
|
||||
]AT_YYERROR_ARG_LOC_IF([, YYLTYPE *yylloc])[
|
||||
]AT_PARAM_IF([, value_t *result, int *count])[
|
||||
);
|
||||
static int yylex (LEX_FORMALS);
|
||||
static int yygetc (LEX_FORMALS);
|
||||
static void yyungetc (LEX_PRE_FORMALS int c);
|
||||
@@ -119,27 +120,25 @@ static void yyungetc (LEX_PRE_FORMALS int c);
|
||||
%left NEG /* negation--unary minus */
|
||||
%right '^' /* exponentiation */
|
||||
|
||||
]$4[
|
||||
|
||||
/* Grammar follows */
|
||||
%%
|
||||
input:
|
||||
line
|
||||
| input line { ++*count; ++global_count; }
|
||||
| input line { ]AT_PARAM_IF([++*count; ++global_count;])[ }
|
||||
;
|
||||
|
||||
line:
|
||||
'\n'
|
||||
| exp '\n' { *result = global_result = $1; }
|
||||
| exp '\n' { ]AT_PARAM_IF([*result = global_result = $1;])[ }
|
||||
;
|
||||
|
||||
exp:
|
||||
NUM { $$ = $1; }
|
||||
| exp '=' exp
|
||||
{
|
||||
if ($1 != $3)
|
||||
fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
|
||||
$$ = $1;
|
||||
if ($1 != $3)
|
||||
fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
|
||||
$$ = $1;
|
||||
}
|
||||
| exp '+' exp { $$ = $1 + $3; }
|
||||
| exp '-' exp { $$ = $1 - $3; }
|
||||
@@ -155,26 +154,28 @@ exp:
|
||||
FILE *yyin;
|
||||
|
||||
static void
|
||||
yyerror (const char *s)
|
||||
yyerror (const char *s
|
||||
]AT_YYERROR_ARG_LOC_IF([, YYLTYPE *yylloc])[
|
||||
]AT_PARAM_IF([, value_t *result, int *count])[)
|
||||
{
|
||||
#if YYLSP_NEEDED
|
||||
]AT_YYERROR_SEES_LOC_IF([
|
||||
fprintf (stderr, "%d.%d-%d.%d: ",
|
||||
LOC.first_line, LOC.first_column,
|
||||
LOC.last_line, LOC.last_column);
|
||||
#endif
|
||||
])[
|
||||
fprintf (stderr, "%s\n", s);
|
||||
}
|
||||
|
||||
|
||||
#if YYLSP_NEEDED
|
||||
]AT_LOCATION_IF([
|
||||
static YYLTYPE last_yylloc;
|
||||
#endif
|
||||
])[
|
||||
static int
|
||||
yygetc (LEX_FORMALS)
|
||||
{
|
||||
int res = getc (yyin);
|
||||
USE_LEX_ARGS;
|
||||
#if YYLSP_NEEDED
|
||||
]AT_LOCATION_IF([
|
||||
last_yylloc = LOC;
|
||||
if (res == '\n')
|
||||
{
|
||||
@@ -183,7 +184,7 @@ yygetc (LEX_FORMALS)
|
||||
}
|
||||
else
|
||||
LOC.last_column++;
|
||||
#endif
|
||||
])[
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -192,10 +193,10 @@ static void
|
||||
yyungetc (LEX_PRE_FORMALS int c)
|
||||
{
|
||||
USE_LEX_ARGS;
|
||||
#if YYLSP_NEEDED
|
||||
]AT_LOCATION_IF([
|
||||
/* Wrong when C == `\n'. */
|
||||
LOC = last_yylloc;
|
||||
#endif
|
||||
])[
|
||||
ungetc (c, yyin);
|
||||
}
|
||||
|
||||
@@ -241,24 +242,24 @@ yylex (LEX_FORMALS)
|
||||
if (init)
|
||||
{
|
||||
init = 0;
|
||||
#if YYLSP_NEEDED
|
||||
]AT_LOCATION_IF([
|
||||
LOC.last_column = 1;
|
||||
LOC.last_line = 1;
|
||||
#endif
|
||||
])[
|
||||
}
|
||||
|
||||
#if YYLSP_NEEDED
|
||||
]AT_LOCATION_IF([
|
||||
LOC.first_column = LOC.last_column;
|
||||
LOC.first_line = LOC.last_line;
|
||||
#endif
|
||||
])[
|
||||
|
||||
/* Skip white space. */
|
||||
while ((c = yygetc (LEX_ARGS)) == ' ' || c == '\t')
|
||||
{
|
||||
#if YYLSP_NEEDED
|
||||
]AT_LOCATION_IF([
|
||||
LOC.first_column = LOC.last_column;
|
||||
LOC.first_line = LOC.last_line;
|
||||
#endif
|
||||
])[
|
||||
}
|
||||
|
||||
/* process numbers */
|
||||
@@ -309,7 +310,7 @@ main (int argc, const char **argv)
|
||||
#if YYDEBUG
|
||||
yydebug = 1;
|
||||
#endif
|
||||
yyparse (&result, &count);
|
||||
yyparse (]AT_PARAM_IF([&result, &count])[);
|
||||
assert (global_result == result);
|
||||
assert (global_count == count);
|
||||
|
||||
@@ -352,8 +353,8 @@ m4_bmatch([$1],
|
||||
|
||||
|
||||
# _AT_CHECK_CALC_ERROR(BISON-OPTIONS, INPUT, [NUM-DEBUG-LINES],
|
||||
# [ERROR-LOCATION], [IF-YYERROR-VERBOSE])
|
||||
# ------------------------------------------------------------
|
||||
# [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
|
||||
# -------------------------------------------------------------
|
||||
# Run `calc' on INPUT, and expect a `parse error' message.
|
||||
#
|
||||
# If INPUT starts with a slash, it is used as absolute input file name,
|
||||
@@ -402,7 +403,7 @@ AT_DATA([[expout]],
|
||||
[$4
|
||||
])
|
||||
# 3. If locations are not used, remove them.
|
||||
m4_bmatch([$1], [%locations], [],
|
||||
AT_YYERROR_SEES_LOC_IF([],
|
||||
[[sed 's/^[-0-9.]*: //' expout >at-expout
|
||||
mv at-expout expout]])
|
||||
# 4. If error-verbose is not used, strip the`, unexpected....' part.
|
||||
@@ -414,6 +415,54 @@ AT_CHECK([cat stderr], 0, [expout])
|
||||
])
|
||||
|
||||
|
||||
# AT_CALC_PUSHDEFS($1, $2, [BISON-OPTIONS])
|
||||
# -----------------------------------------
|
||||
# This macro works around the impossibility to define macros
|
||||
# inside macros, because issuing `[$1]' is not possible in M4 :(.
|
||||
# This sucks hard, GNU M4 should really provide M5 like $$1.
|
||||
m4_define([AT_CHECK_PUSHDEFS],
|
||||
[m4_if([$1$2], $[1]$[2], [],
|
||||
[m4_fatal([$0: Invalid arguments: $@])])dnl
|
||||
m4_pushdef([AT_PARAM_IF],
|
||||
[m4_bmatch([$3], [%parse-param], [$1], [$2])])
|
||||
m4_pushdef([AT_LOCATION_IF],
|
||||
[m4_bmatch([$3], [%locations], [$1], [$2])])
|
||||
m4_pushdef([AT_PURE_IF],
|
||||
[m4_bmatch([$3], [%pure-parser], [$1], [$2])])
|
||||
m4_pushdef([AT_GLR_IF],
|
||||
[m4_bmatch([$3], [%glr-parser], [$1], [$2])])
|
||||
m4_pushdef([AT_PURE_AND_LOC_IF],
|
||||
[m4_bmatch([$3], [%locations.*%pure-parser\|%pure-parser.*%locations],
|
||||
[$1], [$2])])
|
||||
m4_pushdef([AT_GLR_OR_PARAM_IF],
|
||||
[m4_bmatch([$3], [%glr-parser\|%parse-param], [$1], [$2])])
|
||||
|
||||
# yyerror receives the location if %location & %pure & (%glr or %parse-param).
|
||||
m4_pushdef([AT_YYERROR_ARG_LOC_IF],
|
||||
[AT_GLR_OR_PARAM_IF([AT_PURE_AND_LOC_IF([$1], [$2])],
|
||||
[$2])])
|
||||
# yyerror cannot see the locations if !glr & pure.
|
||||
m4_pushdef([AT_YYERROR_SEES_LOC_IF],
|
||||
[AT_LOCATION_IF([AT_GLR_IF([$1],
|
||||
[AT_PURE_IF([$2], [$1])])],
|
||||
[$2])])
|
||||
])
|
||||
|
||||
|
||||
# AT_CALC_POPDEFS
|
||||
# ---------------
|
||||
m4_define([AT_CHECK_POPDEFS],
|
||||
[m4_popdef([AT_YYERROR_SEES_LOC_IF])
|
||||
m4_popdef([AT_YYERROR_ARG_LOC_IF])
|
||||
m4_popdef([AT_GLR_OR_PARAM_IF])
|
||||
m4_popdef([AT_PURE_AND_LOC_IF])
|
||||
m4_popdef([AT_GLR_IF])
|
||||
m4_popdef([AT_LOCATION_IF])
|
||||
m4_popdef([AT_PARAM_IF])
|
||||
])
|
||||
|
||||
|
||||
|
||||
# AT_CHECK_CALC([BISON-OPTIONS])
|
||||
# ------------------------------
|
||||
# Start a testing chunk which compiles `calc' grammar with
|
||||
@@ -422,6 +471,8 @@ m4_define([AT_CHECK_CALC],
|
||||
[# We use integers to avoid dependencies upon the precision of doubles.
|
||||
AT_SETUP([Calculator $1])
|
||||
|
||||
AT_CHECK_PUSHDEFS($[1], $[2], [$1])
|
||||
|
||||
AT_DATA_CALC_Y([$1])
|
||||
|
||||
# Specify the output files to avoid problems on different file systems.
|
||||
@@ -473,6 +524,8 @@ _AT_CHECK_CALC_ERROR([$1], [(1 ++ 2) + (0 0) = 1], [82],
|
||||
1.15-1.16: parse error, unexpected "number"
|
||||
calc: error: 0 != 1])
|
||||
|
||||
AT_CHECK_POPDEFS
|
||||
|
||||
AT_CLEANUP
|
||||
])# AT_CHECK_CALC
|
||||
|
||||
@@ -508,7 +561,9 @@ AT_CHECK_CALC_LALR([%error-verbose %locations %defines %name-prefix="calc" %verb
|
||||
AT_CHECK_CALC_LALR([%debug])
|
||||
AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
|
||||
|
||||
# AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
|
||||
AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
|
||||
|
||||
AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param "value_t *result", "result" %parse-param "int *count", "count"])
|
||||
|
||||
|
||||
# ----------------------- #
|
||||
@@ -541,4 +596,6 @@ AT_CHECK_CALC_GLR([%error-verbose %locations %defines %name-prefix="calc" %verbo
|
||||
AT_CHECK_CALC_GLR([%debug])
|
||||
AT_CHECK_CALC_GLR([%error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
|
||||
|
||||
# AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
|
||||
AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
|
||||
|
||||
AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param "value_t *result", "result" %parse-param "int *count", "count"])
|
||||
|
||||
@@ -36,7 +36,11 @@ $1
|
||||
]m4_bmatch([$2], [stmtMerge],
|
||||
[ static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);])[
|
||||
#define YYINITDEPTH 10
|
||||
int yyerror (const char *s);
|
||||
int yyerror (const char *s
|
||||
#if YYPURE && YYLSP_NEEDED
|
||||
, YYLTYPE *yylocation
|
||||
#endif
|
||||
);
|
||||
|
||||
#if YYPURE
|
||||
]m4_bmatch([$1], [location],
|
||||
@@ -130,7 +134,7 @@ yylex ()
|
||||
break;
|
||||
default:
|
||||
if (isalpha (c))
|
||||
{
|
||||
{
|
||||
i = 0;
|
||||
|
||||
do
|
||||
@@ -153,8 +157,15 @@ yylex ()
|
||||
}
|
||||
|
||||
int
|
||||
yyerror (const char *s)
|
||||
yyerror (const char *s
|
||||
#if YYPURE && YYLSP_NEEDED
|
||||
, YYLTYPE *yylocation
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if YYPURE && YYLSP_NEEDED
|
||||
(void) *yylocation;
|
||||
#endif
|
||||
fprintf (stderr, "%s\n", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user