# D features tests. -*- Autotest -*- # Copyright (C) 2020-2022 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 . AT_BANNER([[D Features.]]) # AT_CHECK_D_MINIMAL([DIRECTIVES], [PARSER_ACTION], [POSITION_CLASS], [EXTRA_USER_CODE]) # ---------------------------------------------------------------------- # Check that a minimal parser with DIRECTIVES compiles in D. # Put the D code in YYParser.d. m4_define([AT_CHECK_D_MINIMAL], [ AT_DATA([[YYParser.y]], [ %language "D" %token END "end" [$1] %% start: END {$2}; %% [$4] void main() {} ]) AT_BISON_CHECK([[-Wno-deprecated YYParser.y]]) AT_CHECK([[grep '[mb]4_' YYParser.y]], [1], [ignore]) AT_COMPILE_D([[YYParser]]) ]) # AT_CHECK_D_MINIMAL_W_LEXER([1:DIRECTIVES], # [2:YYLEX_ACTION], [3:LEXER_BODY], [4:PARSER_ACTION], [5:VALUE_TYPE], # [6:POSITION_TYPE], [7:LOCATION_TYPE]) # --------------------------------------------------------------------- # Check that a minimal parser with DIRECTIVES and a body for yylex() # compiles in D. m4_define([AT_CHECK_D_MINIMAL_W_LEXER], [AT_CHECK_D_MINIMAL([$1], [], [], [ import std.range.primitives; import std.stdio; auto calcLexer(R)(R range) if (isInputRange!R && is (ElementType!R : dchar)) { return new CalcLexer!R(range); } auto calcLexer (File f) { import std.algorithm : map, joiner; import std.utf : byDchar; return f.byChunk(1024) // avoid making a syscall roundtrip per char .map!(chunk => cast(char[]) chunk) // because byChunk returns ubyte[] .joiner // combine chunks into a single virtual range of char .calcLexer; // forward to other overload } class CalcLexer(R) : Lexer if (isInputRange!R && is (ElementType!R : dchar)) { R input; this(R r) { input = r; } void yyerror(string s) {} Symbol yylex() { $2 } } ] [ $3 ], [$4], [$6])]) # AT_CHECK_D_GREP([LINE], [COUNT=1]) # ------------------------------------- # Check that YYParser.d contains exactly COUNT lines matching ^LINE$ # with grep. m4_define([AT_CHECK_D_GREP], [AT_CHECK([grep -c '^$1$' YYParser.d], [ignore], [m4_default([$2], [1]) ])]) ## -------------------------------------- ## ## D parser class extends and implements. ## ## -------------------------------------- ## AT_SETUP([D parser class extends and implements]) AT_KEYWORDS([d]) AT_CHECK_D_MINIMAL([]) AT_CHECK_D_GREP([[class YYParser]]) AT_CHECK_D_MINIMAL([%define api.parser.extends {BaseClass}], [], [], [class BaseClass {}]) AT_CHECK_D_GREP([[class YYParser : BaseClass]]) AT_CHECK_D_MINIMAL([%define api.parser.extends {Interface}], [], [], [interface Interface {}]) AT_CHECK_D_GREP([[class YYParser : Interface]]) AT_CHECK_D_MINIMAL([%code lexer { Symbol yylex () {return Symbol();} void yyerror (string s) {import std.stdio;writeln(s);} }], [], [], []) AT_CHECK_D_GREP([[private class YYLexer: Lexer]]) AT_CHECK_D_MINIMAL( [%define api.parser.extends {BaseClass} %define api.parser.implements {Interface}], [], [], [class BaseClass {} interface Interface {} ]) AT_CHECK_D_GREP([[class YYParser : BaseClass, Interface]]) AT_CHECK_D_MINIMAL( [%define api.parser.extends {BaseClass} %define api.parser.implements {Interface1, Interface2}], [], [], [class BaseClass {} interface Interface1 {} interface Interface2 {} ]) AT_CHECK_D_GREP([[class YYParser : BaseClass, Interface1, Interface2]]) AT_CLEANUP ## --------------------------------------------- ## ## D parser class api.token.raw true by default. ## ## --------------------------------------------- ## AT_SETUP([D parser class api.token.raw true by default]) AT_KEYWORDS([d]) AT_CHECK_D_MINIMAL_W_LEXER([ %define api.token.raw true %union { int ival; }], [return Symbol(TokenKind.END);]) AT_CHECK_D_GREP([[ END = 3,]]) AT_CHECK_D_MINIMAL_W_LEXER([ %define api.token.raw false %union { int ival; }], [return Symbol(TokenKind.END);]) AT_CHECK_D_GREP([[ END = 258,]]) AT_CHECK_D_MINIMAL_W_LEXER([ %union { int ival; }], [return Symbol(TokenKind.END);]) AT_CHECK_D_GREP([[ END = 3,]]) AT_CLEANUP