diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | data/skeletons/d.m4 | 2 | ||||
-rw-r--r-- | data/skeletons/lalr1.d | 2 | ||||
-rw-r--r-- | examples/d/calc.y | 2 | ||||
-rw-r--r-- | tests/atlocal.in | 3 | ||||
-rw-r--r-- | tests/calc.at | 170 | ||||
-rw-r--r-- | tests/local.at | 60 |
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]) |