summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--data/skeletons/d.m42
-rw-r--r--data/skeletons/lalr1.d2
-rw-r--r--examples/d/calc.y2
-rw-r--r--tests/atlocal.in3
-rw-r--r--tests/calc.at170
-rw-r--r--tests/local.at60
7 files changed, 222 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac
index 1b5343e7..507e6f64 100644
--- a/configure.ac
+++ b/configure.ac
@@ -192,6 +192,7 @@ BISON_CXX_COMPILER_POSIXLY_CORRECT
# D.
AC_CHECK_PROGS([DC], [dmd])
+AC_CHECK_PROGS([DCFLAGS], [])
AM_CONDITIONAL([ENABLE_D], [test x"$DC" != x])
# Java.
diff --git a/data/skeletons/d.m4 b/data/skeletons/d.m4
index 722d04d2..9ebce565 100644
--- a/data/skeletons/d.m4
+++ b/data/skeletons/d.m4
@@ -190,7 +190,7 @@ b4_percent_define_default([[stype]], [[YYSemanticType]])])
# %name-prefix
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]])])
#b4_percent_define_default([[location_type]], [Location])])
diff --git a/data/skeletons/lalr1.d b/data/skeletons/lalr1.d
index bb5c83fc..07246a77 100644
--- a/data/skeletons/lalr1.d
+++ b/data/skeletons/lalr1.d
@@ -69,7 +69,7 @@ public interface Lexer
* to the next token and prepares to return the semantic value
* ]b4_locations_if([and beginning/ending positions ])[of the token.
* @@return the token identifier corresponding to the next token. */
- YYTokenType yylex ();
+ int yylex ();
/**
* Entry point for error reporting. Emits an error
diff --git a/examples/d/calc.y b/examples/d/calc.y
index 26b4413a..5c7975a3 100644
--- a/examples/d/calc.y
+++ b/examples/d/calc.y
@@ -108,7 +108,7 @@ class CalcLexer : Lexer {
return semanticVal_;
}
- YYTokenType yylex ()
+ int yylex ()
{
int c;
/* Skip white spaces. */
diff --git a/tests/atlocal.in b/tests/atlocal.in
index dc35d95a..f7db41e9 100644
--- a/tests/atlocal.in
+++ b/tests/atlocal.in
@@ -118,6 +118,9 @@ fi
## Other. ##
## ------- ##
+: ${DC='@DC@'}
+: ${DCFLAGS='@DCFLAGS@'}
+
# Empty if no javac was found
: ${CONF_JAVAC='@CONF_JAVAC@'}
diff --git a/tests/calc.at b/tests/calc.at
index 47af4d34..252f8ae0 100644
--- a/tests/calc.at
+++ b/tests/calc.at
@@ -44,11 +44,28 @@ m4_define([_AT_DATA_CALC_Y],
[m4_if([$1$2$3], $[1]$[2]$[3], [],
[m4_fatal([$0: Invalid arguments: $@])])dnl
-m4_pushdef([AT_CALC_MAIN],
-[#include <assert.h>
+AT_D_IF([m4_pushdef([AT_CALC_MAIN],
+[[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>
-AT_CXX_IF([[
+]AT_CXX_IF([[
namespace
{
/* 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;
return status;
}
-]])
+]])])
+
+AT_D_IF([m4_pushdef([AT_CALC_LEX],
+[[File input;
+
+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_;
-m4_pushdef([AT_CALC_LEX],
+ 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>
]AT_YYLEX_DECLARE_EXTERN[
@@ -202,12 +312,19 @@ read_signed_integer (]AT_YYLEX_FORMALS[)
return c;
}
]])
+])
AT_DATA_GRAMMAR([calc.y],
[[/* Infix notation calculator--calc */
-]$4
-AT_CXX_IF(
-[%define global_tokens_and_yystype])[
+]$4[
+]AT_CXX_IF([%define global_tokens_and_yystype])[
+]AT_D_IF([[
+%code imports {
+ import std.ascii;
+ import std.stdio;
+ alias semantic_value = int;
+}
+]], [[
%code requires
{
]AT_LOCATION_TYPE_SPAN_IF([[
@@ -241,6 +358,7 @@ AT_CXX_IF(
/* Exercise pre-prologue dependency to %union. */
typedef int semantic_value;
}
+]])[
/* Exercise %union. */
%union
@@ -250,6 +368,7 @@ AT_CXX_IF(
%printer { ]AT_CXX_IF([[yyo << $$]],
[[fprintf (yyo, "%d", $$)]])[; } <ival>;
+]AT_D_IF([], [[
%code provides
{
#include <stdio.h>
@@ -271,6 +390,7 @@ static int power (int base, int exponent);
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE_EXTERN[
}
+]])[
]AT_LOCATION_TYPE_SPAN_IF([[
%initial-action
@@ -299,15 +419,17 @@ input:
line:
'\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:
NUM
| exp '=' exp
{
- if ($1 != $3)
- fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
+ if ($1 != $3)]AT_D_IF([
+ stderr.writefln ("calc: error: %d != %d", $1, $3);], [
+ fprintf (stderr, "calc: error: %d != %d\n", $1, $3);], [
+ ])[
$$ = $1;
}
| exp '+' exp { $$ = $1 + $3; }
@@ -317,9 +439,9 @@ exp:
| '-' exp %prec NEG { $$ = -$2; }
| exp '^' exp { $$ = power ($1, $3); }
| '(' exp ')' { $$ = $2; }
-| '(' error ')' { $$ = 1111; yyerrok; }
-| '!' { $$ = 0; YYERROR; }
-| '-' error { $$ = 0; YYERROR; }
+| '(' error ')' { $$ = 1111; ]AT_D_IF([], [yyerrok;])[ }
+| '!' { $$ = 0; ]AT_D_IF([return YYERROR], [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 %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([]) \ No newline at end of file
diff --git a/tests/local.at b/tests/local.at
index 58e35a9a..8ba82c4f 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -147,13 +147,16 @@ m4_pushdef([AT_DEBUG_IF],
[m4_bmatch([$3], [%debug\|%define parse.trace], [$1], [$2])])
m4_pushdef([AT_CXX_IF],
[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_bmatch([$3], [%language "[Jj][Aa][Vv][Aa]"\|%skeleton "[a-z0-9]+\.java"], [$1], [$2])])
# The target language: "c", "c++", or "java".
m4_pushdef([AT_LANG],
[AT_JAVA_IF([java],
[AT_CXX_IF([c++],
- [c])])])
+ [AT_D_IF([d],
+ [c])])])])
m4_pushdef([AT_GLR_IF],
[m4_bmatch([$3], [%glr-parser\|%skeleton "glr\..*"], [$1], [$2])])
m4_pushdef([AT_LALR1_CC_IF],
@@ -633,6 +636,40 @@ done
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. ##
## ------ ##
@@ -921,6 +958,25 @@ AT_CHECK(m4_join([ ],
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)
# ------------------------
# 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(c)], [AT_COMPILE([$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])])
@@ -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(c)], [c])
m4_define([AT_LANG_EXT(c++)], [cc])
+m4_define([AT_LANG_EXT(d)], [d])
m4_define([AT_LANG_EXT(java)], [java])