* examples/d/calc.test, examples/d/calc.y, examples/d/local.mk: --- configure.ac | 3 +- examples/d/calc.test | 26 +++++++ examples/d/calc.y | 161 +++++++++++++++++++++++++++++++++++++++++++ examples/d/local.mk | 35 ++++++++++ examples/local.mk | 1 + tests/calc.at | 4 +- 6 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 examples/d/calc.test create mode 100644 examples/d/calc.y create mode 100644 examples/d/local.mk
diff --git a/configure.ac b/configure.ac index f0d5a585..61b07ca1 100644 --- a/configure.ac +++ b/configure.ac @@ -189,7 +189,8 @@ BISON_TEST_FOR_WORKING_CXX_COMPILER BISON_CXX_COMPILER_POSIXLY_CORRECT # D. -AM_CONDITIONAL([ENABLE_D], [true]) +AC_CHECK_PROGS([DC], [dmd]) +AM_CONDITIONAL([ENABLE_D], [test x"$DC" != x]) # Java. gt_JAVACOMP([1.7], [1.7]) diff --git a/examples/d/calc.test b/examples/d/calc.test new file mode 100644 index 00000000..3a067e05 --- /dev/null +++ b/examples/d/calc.test @@ -0,0 +1,26 @@ +#! /bin/sh + +# Copyright (C) 2018 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +cat >input <<EOF +1 + 2 * 3 +EOF +run 0 7 + +cat >input <<EOF +1 + 2 * * 3 +EOF +run 0 "err: syntax error, unexpected *, expecting - or ! or ( or number" diff --git a/examples/d/calc.y b/examples/d/calc.y new file mode 100644 index 00000000..320e7427 --- /dev/null +++ b/examples/d/calc.y @@ -0,0 +1,161 @@ +%language "D" +%name-prefix "Calc" +%define parser_class_name {Calc} +%define public + +%define parse.error verbose + +%code imports { + import std.ascii; + import std.stdio; +} + +%union { + int ival; +} + +/* Bison Declarations */ +%token EQ "=" + PLUS "+" + MINUS "-" + STAR "*" + SLASH "/" + BANG "!" + LPAR "(" + RPAR ")" + EOL "end of line" +%token <ival> NUM "number" +%type <ival> exp + +%nonassoc "=" /* comparison */ +%left "-" "+" +%left "*" "/" +%precedence NEG /* negation--unary minus */ + +/* Grammar follows */ +%% +input: + line +| input line +; + +line: + EOL +| exp EOL { writeln ($exp); } +| error EOL +; + +exp: + NUM { $$ = $1; } +| exp "=" exp + { + if ($1 != $3) + yyerror (format ("calc: error: %d != %d", $1, $3)); + } +| exp "+" exp { $$ = $1 + $3; } +| exp "-" exp { $$ = $1 - $3; } +| exp "*" exp { $$ = $1 * $3; } +| exp "/" exp { $$ = $1 / $3; } +| "-" exp %prec NEG { $$ = -$2; } +| "(" exp ")" { $$ = $2; } +| "(" error ")" { $$ = 1111; } +| "!" { $$ = 0; return YYERROR; } +| "-" error { $$ = 0; return YYERROR; } +; + + +%% +class CalcLexer : Lexer { + + this () + {} + + int + get_char () + { + import stdc = core.stdc.stdio; + return stdc.getc (stdc.stdin); + } + + void + unget_char (int c) + { + import stdc = core.stdc.stdio; + stdc.ungetc (c, stdc.stdin); + } + + 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_; + } + + YYTokenType 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; + } + + switch (c) + { + case EOF: return YYTokenType.EOF; + case '=': return YYTokenType.EQ; + case '+': return YYTokenType.PLUS; + case '-': return YYTokenType.MINUS; + case '*': return YYTokenType.STAR; + case '/': return YYTokenType.SLASH; + case '!': return YYTokenType.BANG; + case '(': return YYTokenType.LPAR; + case ')': return YYTokenType.RPAR; + case '\n': return YYTokenType.EOL; + default: assert(0); + } + } +} + +void main () +{ + CalcLexer l = new CalcLexer (); + Calc p = new Calc (l); + p.parse (); +} + diff --git a/examples/d/local.mk b/examples/d/local.mk new file mode 100644 index 00000000..d5d9ac9d --- /dev/null +++ b/examples/d/local.mk @@ -0,0 +1,35 @@ +## Copyright (C) 2018 Free Software Foundation, Inc. +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. + +ddir = $(docdir)/%D% + +## ------ ## +## Calc. ## +## ------ ## + +if ENABLE_D + check_SCRIPTS += %D%/calc + TESTS += %D%/calc.test +endif + +%D%/calc.d: %D%/calc.y $(BISON_IN) $(dist_pkgdata_DATA) + $(AM_V_GEN)$(MKDIR_P) %D% + $(AM_V_at)$(BISON) $< -o $@ + +%D%/calc: %D%/calc.d + $(AM_V_GEN) $(DC) $(DCFLAGS) -of$@ $< + +dist_d_DATA = %D%/calc.y +CLEANFILES += %D%/calc %D%/Calc.d diff --git a/examples/local.mk b/examples/local.mk index 3c7efff5..0fd81b5c 100644 --- a/examples/local.mk +++ b/examples/local.mk @@ -77,6 +77,7 @@ CLEANDIRS += %D%/*.dSYM include %D%/calc++/local.mk include %D%/c++/local.mk +include %D%/d/local.mk include %D%/java/local.mk include %D%/mfcalc/local.mk include %D%/rpcalc/local.mk diff --git a/tests/calc.at b/tests/calc.at index d4c817d6..d602797b 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -176,7 +176,7 @@ read_signed_integer (]AT_YYLEX_FORMALS[) ]AT_YYLEX_PROTOTYPE[ { int c; - /* Skip current token, then white spaces. */ + /* Skip white spaces. */ do { ]AT_LOCATION_IF( @@ -186,7 +186,7 @@ read_signed_integer (]AT_YYLEX_FORMALS[) } while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t'); - /* process numbers */ + /* Process numbers */ if (c == '.' || isdigit (c)) { unget_char (]AT_YYLEX_PRE_ARGS[ c); -- 2.19.2
