dlang: initial changes to run the calc tests on it

* configure.ac (DCFLAGS): Define.
* tests/atlocal.in: Receive it.
* data/skeletons/d.m4 (api.parser.class): Remove spurious YY.
* data/skeletons/lalr1.d (yylex): Return an int instead of a
YYTokenType, so that we can use characters as tokens.
* examples/d/calc.y: Adjust.
* tests/local.at: Initial support for D.
(AT_D_IF, AT_DATA_GRAMMAR(D), AT_YYERROR_DECLARE(d))
(AT_YYERROR_DECLARE_EXTERN(d), AT_YYERROR_DEFINE(d))
(AT_MAIN_DEFINE(d), AT_COMPILE_D, AT_LANG_COMPILE(d), AT_LANG_EXT(d)):
New.
* tests/calc.at: Initial support for D.
* tests/headers.at
This commit is contained in:
Akim Demaille
2019-02-18 18:42:41 +01:00
parent 575b814119
commit b12f9c76e2
7 changed files with 222 additions and 18 deletions

View File

@@ -192,6 +192,7 @@ BISON_CXX_COMPILER_POSIXLY_CORRECT
# D. # D.
AC_CHECK_PROGS([DC], [dmd]) AC_CHECK_PROGS([DC], [dmd])
AC_CHECK_PROGS([DCFLAGS], [])
AM_CONDITIONAL([ENABLE_D], [test x"$DC" != x]) AM_CONDITIONAL([ENABLE_D], [test x"$DC" != x])
# Java. # Java.

View File

@@ -190,7 +190,7 @@ b4_percent_define_default([[stype]], [[YYSemanticType]])])
# %name-prefix # %name-prefix
m4_define_default([b4_prefix], [[YY]]) m4_define_default([b4_prefix], [[YY]])
b4_percent_define_default([[api.parser.class]], [b4_prefix[]YYParser])]) b4_percent_define_default([[api.parser.class]], [b4_prefix[]Parser])])
m4_define([b4_parser_class], [b4_percent_define_get([[api.parser.class]])]) m4_define([b4_parser_class], [b4_percent_define_get([[api.parser.class]])])
#b4_percent_define_default([[location_type]], [Location])]) #b4_percent_define_default([[location_type]], [Location])])

View File

@@ -69,7 +69,7 @@ public interface Lexer
* to the next token and prepares to return the semantic value * to the next token and prepares to return the semantic value
* ]b4_locations_if([and beginning/ending positions ])[of the token. * ]b4_locations_if([and beginning/ending positions ])[of the token.
* @@return the token identifier corresponding to the next token. */ * @@return the token identifier corresponding to the next token. */
YYTokenType yylex (); int yylex ();
/** /**
* Entry point for error reporting. Emits an error * Entry point for error reporting. Emits an error

View File

@@ -108,7 +108,7 @@ class CalcLexer : Lexer {
return semanticVal_; return semanticVal_;
} }
YYTokenType yylex () int yylex ()
{ {
int c; int c;
/* Skip white spaces. */ /* Skip white spaces. */

View File

@@ -118,6 +118,9 @@ fi
## Other. ## ## Other. ##
## ------- ## ## ------- ##
: ${DC='@DC@'}
: ${DCFLAGS='@DCFLAGS@'}
# Empty if no javac was found # Empty if no javac was found
: ${CONF_JAVAC='@CONF_JAVAC@'} : ${CONF_JAVAC='@CONF_JAVAC@'}

View File

@@ -44,11 +44,28 @@ m4_define([_AT_DATA_CALC_Y],
[m4_if([$1$2$3], $[1]$[2]$[3], [], [m4_if([$1$2$3], $[1]$[2]$[3], [],
[m4_fatal([$0: Invalid arguments: $@])])dnl [m4_fatal([$0: Invalid arguments: $@])])dnl
m4_pushdef([AT_CALC_MAIN], AT_D_IF([m4_pushdef([AT_CALC_MAIN],
[#include <assert.h> [[int main (string[] args)
{
semantic_value result = 0;
int count = 0;
if (args.length == 2)
input = File (args[1], "r");
else
input = stdin;
CalcLexer l = new CalcLexer ();
YYParser p = new YYParser (l);
int status = !p.parse ();
return status;
}
]])],
[m4_pushdef([AT_CALC_MAIN],
[[#include <assert.h>
#include <unistd.h> #include <unistd.h>
AT_CXX_IF([[ ]AT_CXX_IF([[
namespace namespace
{ {
/* A C++ ]AT_NAME_PREFIX[parse that simulates the C signature. */ /* A C++ ]AT_NAME_PREFIX[parse that simulates the C signature. */
@@ -101,10 +118,103 @@ main (int argc, const char **argv)
assert (global_count == count); (void) count; assert (global_count == count); (void) count;
return status; return status;
} }
]]) ]])])
AT_D_IF([m4_pushdef([AT_CALC_LEX],
[[File input;
m4_pushdef([AT_CALC_LEX], class CalcLexer : Lexer {
int prev_char = -1;
int
get_char ()
{
if (prev_char != -1)
{
auto res = prev_char;
prev_char = -1;
return res;
}
else
{
auto res = input.rawRead (new char[1]);
if (res.length == 0)
return -1;
else
return res[0];
}
}
void
unget_char (int c)
{
prev_char = c;
}
public void yyerror (string s)
{
stderr.writeln (s);
}
int
read_signed_integer ()
{
int c = get_char ();
int sign = 1;
int n = 0;
if (c == '-')
{
c = get_char ();
sign = -1;
}
while (isDigit (c))
{
n = 10 * n + (c - '0');
c = get_char ();
}
unget_char (c);
return sign * n;
}
YYSemanticType semanticVal_;
public final @property YYSemanticType semanticVal()
{
return semanticVal_;
}
int yylex ()
{
int c;
/* Skip white spaces. */
do
{}
while ((c = get_char ()) == ' ' || c == '\t');
/* process numbers */
if (c == '.' || isDigit (c))
{
unget_char (c);
semanticVal_.ival = read_signed_integer ();
return YYTokenType.NUM;
}
/* Return end-of-file. */
if (c == EOF)
{
return YYTokenType.EOF;
}
/* Return single chars. */
return c;
}
}
]])],
[m4_pushdef([AT_CALC_LEX],
[[#include <ctype.h> [[#include <ctype.h>
]AT_YYLEX_DECLARE_EXTERN[ ]AT_YYLEX_DECLARE_EXTERN[
@@ -202,12 +312,19 @@ read_signed_integer (]AT_YYLEX_FORMALS[)
return c; return c;
} }
]]) ]])
])
AT_DATA_GRAMMAR([calc.y], AT_DATA_GRAMMAR([calc.y],
[[/* Infix notation calculator--calc */ [[/* Infix notation calculator--calc */
]$4 ]$4[
AT_CXX_IF( ]AT_CXX_IF([%define global_tokens_and_yystype])[
[%define global_tokens_and_yystype])[ ]AT_D_IF([[
%code imports {
import std.ascii;
import std.stdio;
alias semantic_value = int;
}
]], [[
%code requires %code requires
{ {
]AT_LOCATION_TYPE_SPAN_IF([[ ]AT_LOCATION_TYPE_SPAN_IF([[
@@ -241,6 +358,7 @@ AT_CXX_IF(
/* Exercise pre-prologue dependency to %union. */ /* Exercise pre-prologue dependency to %union. */
typedef int semantic_value; typedef int semantic_value;
} }
]])[
/* Exercise %union. */ /* Exercise %union. */
%union %union
@@ -250,6 +368,7 @@ AT_CXX_IF(
%printer { ]AT_CXX_IF([[yyo << $$]], %printer { ]AT_CXX_IF([[yyo << $$]],
[[fprintf (yyo, "%d", $$)]])[; } <ival>; [[fprintf (yyo, "%d", $$)]])[; } <ival>;
]AT_D_IF([], [[
%code provides %code provides
{ {
#include <stdio.h> #include <stdio.h>
@@ -271,6 +390,7 @@ static int power (int base, int exponent);
]AT_YYERROR_DECLARE[ ]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE_EXTERN[ ]AT_YYLEX_DECLARE_EXTERN[
} }
]])[
]AT_LOCATION_TYPE_SPAN_IF([[ ]AT_LOCATION_TYPE_SPAN_IF([[
%initial-action %initial-action
@@ -299,15 +419,17 @@ input:
line: line:
'\n' '\n'
| exp '\n' { ]AT_PARAM_IF([*result = global_result = $1], [USE ($1)])[; } | exp '\n' { ]AT_PARAM_IF([*result = global_result = $1;], [AT_D_IF([], [USE ($1);])])[ }
; ;
exp: exp:
NUM NUM
| exp '=' exp | exp '=' exp
{ {
if ($1 != $3) if ($1 != $3)]AT_D_IF([
fprintf (stderr, "calc: error: %d != %d\n", $1, $3); stderr.writefln ("calc: error: %d != %d", $1, $3);], [
fprintf (stderr, "calc: error: %d != %d\n", $1, $3);], [
])[
$$ = $1; $$ = $1;
} }
| exp '+' exp { $$ = $1 + $3; } | exp '+' exp { $$ = $1 + $3; }
@@ -317,9 +439,9 @@ exp:
| '-' exp %prec NEG { $$ = -$2; } | '-' exp %prec NEG { $$ = -$2; }
| exp '^' exp { $$ = power ($1, $3); } | exp '^' exp { $$ = power ($1, $3); }
| '(' exp ')' { $$ = $2; } | '(' exp ')' { $$ = $2; }
| '(' error ')' { $$ = 1111; yyerrok; } | '(' error ')' { $$ = 1111; ]AT_D_IF([], [yyerrok;])[ }
| '!' { $$ = 0; YYERROR; } | '!' { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[; }
| '-' error { $$ = 0; YYERROR; } | '-' error { $$ = 0; ]AT_D_IF([return YYERROR], [YYERROR])[; }
; ;
%% %%
@@ -730,3 +852,23 @@ AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %de
AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}]) AT_CHECK_CALC_GLR_CC([%locations %defines %define parse.error verbose %debug %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# --------------------------- #
# Simple LALR1 D Calculator. #
# --------------------------- #
AT_BANNER([[Simple LALR(1) D Calculator.]])
# First let's try using %skeleton
AT_CHECK_CALC([%skeleton "lalr1.d"])
# AT_CHECK_CALC_LALR1_D([BISON-OPTIONS])
# ---------------------------------------
# Start a testing chunk which compiles 'calc' grammar with
# the C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_LALR1_D],
[AT_CHECK_CALC([%language "D" $1], [$2])])
AT_CHECK_CALC_LALR1_D([])

View File

@@ -147,13 +147,16 @@ m4_pushdef([AT_DEBUG_IF],
[m4_bmatch([$3], [%debug\|%define parse.trace], [$1], [$2])]) [m4_bmatch([$3], [%debug\|%define parse.trace], [$1], [$2])])
m4_pushdef([AT_CXX_IF], m4_pushdef([AT_CXX_IF],
[m4_bmatch([$3], [%language "[Cc]\+\+"\|%skeleton "[a-z0-9]+\.cc"], [$1], [$2])]) [m4_bmatch([$3], [%language "[Cc]\+\+"\|%skeleton "[a-z0-9]+\.cc"], [$1], [$2])])
m4_pushdef([AT_D_IF],
[m4_bmatch([$3], [%language "[Dd]"\|%skeleton "[a-z0-9]+\.d"], [$1], [$2])])
m4_pushdef([AT_JAVA_IF], m4_pushdef([AT_JAVA_IF],
[m4_bmatch([$3], [%language "[Jj][Aa][Vv][Aa]"\|%skeleton "[a-z0-9]+\.java"], [$1], [$2])]) [m4_bmatch([$3], [%language "[Jj][Aa][Vv][Aa]"\|%skeleton "[a-z0-9]+\.java"], [$1], [$2])])
# The target language: "c", "c++", or "java". # The target language: "c", "c++", or "java".
m4_pushdef([AT_LANG], m4_pushdef([AT_LANG],
[AT_JAVA_IF([java], [AT_JAVA_IF([java],
[AT_CXX_IF([c++], [AT_CXX_IF([c++],
[c])])]) [AT_D_IF([d],
[c])])])])
m4_pushdef([AT_GLR_IF], m4_pushdef([AT_GLR_IF],
[m4_bmatch([$3], [%glr-parser\|%skeleton "glr\..*"], [$1], [$2])]) [m4_bmatch([$3], [%glr-parser\|%skeleton "glr\..*"], [$1], [$2])])
m4_pushdef([AT_LALR1_CC_IF], m4_pushdef([AT_LALR1_CC_IF],
@@ -633,6 +636,40 @@ done
CXXFLAGS=$at_for_each_std_CXXFLAGS_save CXXFLAGS=$at_for_each_std_CXXFLAGS_save
]]) ]])
## --- ##
## D. ##
## --- ##
# AT_DATA_GRAMMAR(NAME, CONTENT)
# ------------------------------
m4_copy([AT_DATA], [AT_DATA_GRAMMAR(d)])
# No need to declare, it's part of the class interface.
m4_define([AT_YYERROR_DECLARE(d)], [])
m4_define([AT_YYERROR_DECLARE_EXTERN(d)], [])
m4_define([AT_YYERROR_DEFINE(d)],
[[/* An error reporting function. */
public void error (]AT_LOCATION_IF([[location_type l, ]])[string m)
{
// FIXME: location.
stderr.writeln (m);
}]])
m4_define([AT_MAIN_DEFINE(d)],
[[int main ()
{
Lexer l = new Lexer ();
Parser p = new Parser (l);
p.parse ();
}]])
## ------ ## ## ------ ##
## Java. ## ## Java. ##
## ------ ## ## ------ ##
@@ -921,6 +958,25 @@ AT_CHECK(m4_join([ ],
0, [ignore], [ignore])]) 0, [ignore], [ignore])])
# AT_COMPILE_D(OUTPUT, [SOURCES = OUTPUT.d], [EXTRA-COMPILER-FLAGS])
# -------------------------------------------------------------------
# Compile SOURCES into OUTPUT. If the C++ compiler does not work,
# ignore the test.
#
# If OUTPUT does not contain '.', assume that we are linking too,
# otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT
# with trailing ".o" removed, and ".cc" appended.
m4_define([AT_COMPILE_D],
[AT_KEYWORDS(d)
AT_CHECK(m4_join([ ],
[$DC $DCFLAGS $3],
[m4_bmatch([$1], [[.]], [-c])],
[-of$1],
[m4_default([$2], [m4_bpatsubst([$1], [\.o$]).d])],
[m4_bmatch([$1], [[.]], [], [$LIBS])]),
0, [ignore], [ignore])])
# AT_JAVA_COMPILE(SOURCES) # AT_JAVA_COMPILE(SOURCES)
# ------------------------ # ------------------------
# Compile SOURCES into Java class files. Skip the test if java or javac # Compile SOURCES into Java class files. Skip the test if java or javac
@@ -948,6 +1004,7 @@ m4_define([AT_LANG_FOR_EACH_STD], [AT_LANG_DISPATCH([$0], $@)])
m4_define([AT_LANG_COMPILE], [AT_LANG_DISPATCH([$0], $@)]) m4_define([AT_LANG_COMPILE], [AT_LANG_DISPATCH([$0], $@)])
m4_define([AT_LANG_COMPILE(c)], [AT_COMPILE([$1], [$2], [$3])]) m4_define([AT_LANG_COMPILE(c)], [AT_COMPILE([$1], [$2], [$3])])
m4_define([AT_LANG_COMPILE(c++)], [AT_COMPILE_CXX([$1], [$2], [$3])]) m4_define([AT_LANG_COMPILE(c++)], [AT_COMPILE_CXX([$1], [$2], [$3])])
m4_define([AT_LANG_COMPILE(d)], [AT_COMPILE_D([$1], [$2], [$3])])
m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2], [$3])]) m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2], [$3])])
@@ -957,6 +1014,7 @@ m4_define([AT_LANG_COMPILE(java)], [AT_JAVA_COMPILE([$1.java], [$2], [$3])])
m4_define([AT_LANG_EXT], [AT_LANG_DISPATCH([$0], $@)]) m4_define([AT_LANG_EXT], [AT_LANG_DISPATCH([$0], $@)])
m4_define([AT_LANG_EXT(c)], [c]) m4_define([AT_LANG_EXT(c)], [c])
m4_define([AT_LANG_EXT(c++)], [cc]) m4_define([AT_LANG_EXT(c++)], [cc])
m4_define([AT_LANG_EXT(d)], [d])
m4_define([AT_LANG_EXT(java)], [java]) m4_define([AT_LANG_EXT(java)], [java])