mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
tests: restructure for clarity
* tests/calc.at (AT_CALC_MAIN, AT_CALC_LEX): Rewrite on top of AT_LANG_DISPATCH.
This commit is contained in:
303
tests/calc.at
303
tests/calc.at
@@ -19,44 +19,13 @@
|
||||
## Compile the grammar described in the documentation. ##
|
||||
## ---------------------------------------------------- ##
|
||||
|
||||
# -------------- #
|
||||
# AT_CALC_MAIN. #
|
||||
# -------------- #
|
||||
|
||||
# ------------------------- #
|
||||
# Helping Autotest macros. #
|
||||
# ------------------------- #
|
||||
m4_pushdef([AT_CALC_MAIN], [AT_LANG_DISPATCH([$0], $@)])
|
||||
|
||||
|
||||
# _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
|
||||
# -----------------------------------------------
|
||||
# Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
|
||||
# 'calc-lex.cc'.
|
||||
#
|
||||
# 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 AT_DATA_CALC_Y does.
|
||||
#
|
||||
# When %defines is not passed, generate a single self-contained file.
|
||||
# Otherwise, generate three: calc.y with the parser, calc-lex.c with
|
||||
# the scanner, and calc-main.c with "main()". This is in order to
|
||||
# stress the use of the generated parser header. To avoid code
|
||||
# duplication, AT_CALC_LEX and AT_CALC_MAIN contain the body of these
|
||||
# two later files.
|
||||
m4_define([_AT_DATA_CALC_Y],
|
||||
[m4_if([$1$2$3], $[1]$[2]$[3], [],
|
||||
[m4_fatal([$0: Invalid arguments: $@])])dnl
|
||||
|
||||
AT_D_IF([m4_pushdef([AT_CALC_MAIN],
|
||||
[[int main (string[] args)
|
||||
{
|
||||
semantic_value result = 0;
|
||||
int count = 0;
|
||||
|
||||
File input = args.length == 2 ? File (args[1], "r") : stdin;
|
||||
auto l = calcLexer (input);
|
||||
auto p = new YYParser (l);
|
||||
return !p.parse ();
|
||||
}
|
||||
]])],
|
||||
[m4_pushdef([AT_CALC_MAIN],
|
||||
m4_define([AT_CALC_MAIN(c)],
|
||||
[[#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -113,9 +82,127 @@ main (int argc, const char **argv)
|
||||
assert (global_count == count); (void) count;
|
||||
return status;
|
||||
}
|
||||
]])])
|
||||
]])
|
||||
|
||||
AT_D_IF([m4_pushdef([AT_CALC_LEX],
|
||||
m4_copy([AT_CALC_MAIN(c)], [AT_CALC_MAIN(c++)])
|
||||
|
||||
m4_define([AT_CALC_MAIN(d)],
|
||||
[[int main (string[] args)
|
||||
{
|
||||
semantic_value result = 0;
|
||||
int count = 0;
|
||||
|
||||
File input = args.length == 2 ? File (args[1], "r") : stdin;
|
||||
auto l = calcLexer (input);
|
||||
auto p = new YYParser (l);
|
||||
return !p.parse ();
|
||||
}
|
||||
]])
|
||||
|
||||
|
||||
|
||||
# --------------- #
|
||||
# AT_CALC_YYLEX. #
|
||||
# --------------- #
|
||||
|
||||
m4_pushdef([AT_CALC_YYLEX], [AT_LANG_DISPATCH([$0], $@)])
|
||||
|
||||
|
||||
m4_define([AT_CALC_YYLEX(c)],
|
||||
[[#include <ctype.h>
|
||||
|
||||
]AT_YYLEX_DECLARE_EXTERN[
|
||||
|
||||
]AT_LOCATION_IF([
|
||||
static AT_YYLTYPE last_yylloc;
|
||||
])[
|
||||
static int
|
||||
get_char (]AT_YYLEX_FORMALS[)
|
||||
{
|
||||
int res = getc (input);
|
||||
]AT_USE_LEX_ARGS[;
|
||||
]AT_LOCATION_IF([
|
||||
last_yylloc = AT_LOC;
|
||||
if (res == '\n')
|
||||
{
|
||||
AT_LOC_LAST_LINE++;
|
||||
AT_LOC_LAST_COLUMN = 1;
|
||||
}
|
||||
else
|
||||
AT_LOC_LAST_COLUMN++;
|
||||
])[
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
|
||||
{
|
||||
]AT_USE_LEX_ARGS[;
|
||||
]AT_LOCATION_IF([
|
||||
/* Wrong when C == '\n'. */
|
||||
AT_LOC = last_yylloc;
|
||||
])[
|
||||
ungetc (c, input);
|
||||
}
|
||||
|
||||
static int
|
||||
read_integer (]AT_YYLEX_FORMALS[)
|
||||
{
|
||||
int c = get_char (]AT_YYLEX_ARGS[);
|
||||
int res = 0;
|
||||
|
||||
]AT_USE_LEX_ARGS[;
|
||||
while (isdigit (c))
|
||||
{
|
||||
res = 10 * res + (c - '0');
|
||||
c = get_char (]AT_YYLEX_ARGS[);
|
||||
}
|
||||
|
||||
unget_char (]AT_YYLEX_PRE_ARGS[ c);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------.
|
||||
| Lexical analyzer returns an integer on the stack and the token |
|
||||
| NUM, or the ASCII character read if not a number. Skips all |
|
||||
| blanks and tabs, returns 0 for EOF. |
|
||||
`---------------------------------------------------------------*/
|
||||
|
||||
]AT_YYLEX_PROTOTYPE[
|
||||
{
|
||||
int c;
|
||||
/* Skip white spaces. */
|
||||
do
|
||||
{
|
||||
]AT_LOCATION_IF(
|
||||
[ AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
|
||||
AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
|
||||
])[
|
||||
}
|
||||
while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
|
||||
|
||||
/* Process numbers. */
|
||||
if (isdigit (c))
|
||||
{
|
||||
unget_char (]AT_YYLEX_PRE_ARGS[ c);
|
||||
]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[);
|
||||
return ]AT_TOKEN_PREFIX[NUM;
|
||||
}
|
||||
|
||||
/* Return end-of-file. */
|
||||
if (c == EOF)
|
||||
return ]AT_TOKEN_PREFIX[CALC_EOF;
|
||||
|
||||
/* Return single chars. */
|
||||
return c;
|
||||
}
|
||||
]])
|
||||
|
||||
m4_copy([AT_CALC_YYLEX(c)], [AT_CALC_YYLEX(c++)])
|
||||
|
||||
m4_define([AT_CALC_YYLEX(d)],
|
||||
[[import std.range.primitives;
|
||||
import std.stdio;
|
||||
|
||||
@@ -216,99 +303,32 @@ class CalcLexer(R) : Lexer
|
||||
return c;
|
||||
}
|
||||
}
|
||||
]])],
|
||||
[m4_pushdef([AT_CALC_LEX],
|
||||
[[#include <ctype.h>
|
||||
|
||||
]AT_YYLEX_DECLARE_EXTERN[
|
||||
|
||||
]AT_LOCATION_IF([
|
||||
static AT_YYLTYPE last_yylloc;
|
||||
])[
|
||||
static int
|
||||
get_char (]AT_YYLEX_FORMALS[)
|
||||
{
|
||||
int res = getc (input);
|
||||
]AT_USE_LEX_ARGS[;
|
||||
]AT_LOCATION_IF([
|
||||
last_yylloc = AT_LOC;
|
||||
if (res == '\n')
|
||||
{
|
||||
AT_LOC_LAST_LINE++;
|
||||
AT_LOC_LAST_COLUMN = 1;
|
||||
}
|
||||
else
|
||||
AT_LOC_LAST_COLUMN++;
|
||||
])[
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
|
||||
{
|
||||
]AT_USE_LEX_ARGS[;
|
||||
]AT_LOCATION_IF([
|
||||
/* Wrong when C == '\n'. */
|
||||
AT_LOC = last_yylloc;
|
||||
])[
|
||||
ungetc (c, input);
|
||||
}
|
||||
|
||||
static int
|
||||
read_integer (]AT_YYLEX_FORMALS[)
|
||||
{
|
||||
int c = get_char (]AT_YYLEX_ARGS[);
|
||||
int res = 0;
|
||||
|
||||
]AT_USE_LEX_ARGS[;
|
||||
while (isdigit (c))
|
||||
{
|
||||
res = 10 * res + (c - '0');
|
||||
c = get_char (]AT_YYLEX_ARGS[);
|
||||
}
|
||||
|
||||
unget_char (]AT_YYLEX_PRE_ARGS[ c);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------.
|
||||
| Lexical analyzer returns an integer on the stack and the token |
|
||||
| NUM, or the ASCII character read if not a number. Skips all |
|
||||
| blanks and tabs, returns 0 for EOF. |
|
||||
`---------------------------------------------------------------*/
|
||||
|
||||
]AT_YYLEX_PROTOTYPE[
|
||||
{
|
||||
int c;
|
||||
/* Skip white spaces. */
|
||||
do
|
||||
{
|
||||
]AT_LOCATION_IF(
|
||||
[ AT_LOC_FIRST_COLUMN = AT_LOC_LAST_COLUMN;
|
||||
AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
|
||||
])[
|
||||
}
|
||||
while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
|
||||
|
||||
/* Process numbers. */
|
||||
if (isdigit (c))
|
||||
{
|
||||
unget_char (]AT_YYLEX_PRE_ARGS[ c);
|
||||
]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[);
|
||||
return ]AT_TOKEN_PREFIX[NUM;
|
||||
}
|
||||
|
||||
/* Return end-of-file. */
|
||||
if (c == EOF)
|
||||
return ]AT_TOKEN_PREFIX[CALC_EOF;
|
||||
|
||||
/* Return single chars. */
|
||||
return c;
|
||||
}
|
||||
]])
|
||||
])
|
||||
|
||||
|
||||
# -------------- #
|
||||
# AT_DATA_CALC. #
|
||||
# -------------- #
|
||||
|
||||
|
||||
# _AT_DATA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
|
||||
# -----------------------------------------------
|
||||
# Produce 'calc.y' and, if %defines was specified, 'calc-lex.c' or
|
||||
# 'calc-lex.cc'.
|
||||
#
|
||||
# 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 AT_DATA_CALC_Y does.
|
||||
#
|
||||
# When %defines is not passed, generate a single self-contained file.
|
||||
# Otherwise, generate three: calc.y with the parser, calc-lex.c with
|
||||
# the scanner, and calc-main.c with "main()". This is in order to
|
||||
# stress the use of the generated parser header. To avoid code
|
||||
# duplication, AT_CALC_YYLEX and AT_CALC_MAIN contain the body of these
|
||||
# two later files.
|
||||
m4_define([_AT_DATA_CALC_Y],
|
||||
[m4_if([$1$2$3], $[1]$[2]$[3], [],
|
||||
[m4_fatal([$0: Invalid arguments: $@])])dnl
|
||||
|
||||
AT_DATA_GRAMMAR([calc.y],
|
||||
[[/* Infix notation calculator--calc */
|
||||
@@ -381,15 +401,15 @@ void location_print (FILE *o, Span s);
|
||||
|
||||
%code
|
||||
{
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#define USE(Var)
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#define USE(Var)
|
||||
|
||||
FILE *input;
|
||||
static int power (int base, int exponent);
|
||||
FILE *input;
|
||||
static int power (int base, int exponent);
|
||||
|
||||
]AT_YYERROR_DECLARE[
|
||||
]AT_YYLEX_DECLARE_EXTERN[
|
||||
]AT_YYERROR_DECLARE[
|
||||
]AT_YYLEX_DECLARE_EXTERN[
|
||||
}
|
||||
]])[
|
||||
|
||||
@@ -484,20 +504,18 @@ location_print (FILE *o, Span s)
|
||||
]])])[
|
||||
]AT_YYERROR_DEFINE[
|
||||
]AT_DEFINES_IF([],
|
||||
[AT_CALC_LEX
|
||||
[AT_CALC_YYLEX
|
||||
AT_CALC_MAIN])])
|
||||
|
||||
AT_DEFINES_IF([AT_DATA_SOURCE([[calc-lex.]AT_LANG_EXT],
|
||||
[[#include "calc.]AT_LANG_HDR["
|
||||
|
||||
]AT_CALC_LEX])
|
||||
]AT_CALC_YYLEX])
|
||||
AT_DATA_SOURCE([[calc-main.]AT_LANG_EXT],
|
||||
[[#include "calc.]AT_LANG_HDR["
|
||||
|
||||
]AT_CALC_MAIN])
|
||||
])
|
||||
m4_popdef([AT_CALC_MAIN])
|
||||
m4_popdef([AT_CALC_LEX])
|
||||
])# _AT_DATA_CALC_Y
|
||||
|
||||
|
||||
@@ -902,3 +920,6 @@ AT_CHECK_CALC_LALR1_D([%define parse.error verbose %debug %verbose])
|
||||
|
||||
#AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %verbose %parse-param {semantic_value *result} %parse-param {int *count}])
|
||||
#AT_CHECK_CALC_LALR1_D([%locations %define parse.error verbose %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result} %parse-param {int *count}])
|
||||
|
||||
m4_popdef([AT_CALC_MAIN])
|
||||
m4_popdef([AT_CALC_YYLEX])
|
||||
|
||||
Reference in New Issue
Block a user