3 # D language support for Bison
5 # Copyright (C) 2018-2020 Free Software Foundation, Inc.
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 # _b4_comment(TEXT, OPEN, CONTINUE, END)
22 # --------------------------------------
23 # Put TEXT in comment. Avoid trailing spaces: don't indent empty lines.
24 # Avoid adding indentation to the first line, as the indentation comes
25 # from OPEN. That's why we don't patsubst([$1], [^\(.\)], [ \1]).
27 # Prefix all the output lines with PREFIX.
28 m4_define([_b4_comment],
29 [$2[]m4_bpatsubst(m4_expand([[$1]]), [
34 # b4_comment(TEXT, [PREFIX])
35 # --------------------------
36 # Put TEXT in comment. Prefix all the output lines with PREFIX.
37 m4_define([b4_comment],
38 [_b4_comment([$1], [$2/* ], [$2 ], [ */])])
41 # b4_sync_start(LINE, FILE)
42 # -------------------------
43 m4_define([b4_sync_start], [[#]line $1 $2])
46 # b4_list2(LIST1, LIST2)
47 # ----------------------
48 # Join two lists with a comma if necessary.
50 [$1[]m4_ifval(m4_quote($1), [m4_ifval(m4_quote($2), [[, ]])])[]$2])
53 # b4_percent_define_get3(DEF, PRE, POST, NOT)
54 # -------------------------------------------
55 # Expand to the value of DEF surrounded by PRE and POST if it's %define'ed,
57 m4_define([b4_percent_define_get3],
58 [m4_ifval(m4_quote(b4_percent_define_get([$1])),
59 [$2[]b4_percent_define_get([$1])[]$3], [$4])])
61 # b4_percent_define_if_get2(ARG1, ARG2, DEF, NOT)
62 # -----------------------------------------------
63 # Expand to the value of DEF if ARG1 or ARG2 are %define'ed,
65 m4_define([b4_percent_define_if_get2],
66 [m4_ifval(m4_quote(b4_percent_define_get([$1])),
67 [$3], [m4_ifval(m4_quote(b4_percent_define_get([$2])),
70 # b4_percent_define_class_before_interface(CLASS, INTERFACE)
71 # ----------------------------------------------------------
72 # Expand to a ', ' if both a class and an interface have been %define'ed
73 m4_define([b4_percent_define_class_before_interface],
74 [m4_ifval(m4_quote(b4_percent_define_get([$1])),
75 [m4_ifval(m4_quote(b4_percent_define_get([$2])),
79 # b4_flag_value(BOOLEAN-FLAG)
80 # ---------------------------
81 m4_define([b4_flag_value], [b4_flag_if([$1], [true], [false])])
84 # b4_parser_class_declaration
85 # ---------------------------
86 # The declaration of the parser class ("class YYParser"), with all its
87 # qualifiers/annotations.
88 b4_percent_define_default([[api.parser.abstract]], [[false]])
89 b4_percent_define_default([[api.parser.final]], [[false]])
90 b4_percent_define_default([[api.parser.public]], [[false]])
92 m4_define([b4_parser_class_declaration],
93 [b4_percent_define_get3([api.parser.annotations], [], [ ])dnl
94 b4_percent_define_flag_if([api.parser.public], [public ])dnl
95 b4_percent_define_flag_if([api.parser.abstract], [abstract ])dnl
96 b4_percent_define_flag_if([api.parser.final], [final ])dnl
97 [class ]b4_parser_class[]dnl
98 b4_percent_define_if_get2([api.parser.extends], [api.parser.implements], [ : ])dnl
99 b4_percent_define_get([api.parser.extends])dnl
100 b4_percent_define_class_before_interface([api.parser.extends], [api.parser.implements])dnl
101 b4_percent_define_get([api.parser.implements])])
104 # b4_lexer_if(TRUE, FALSE)
105 # ------------------------
106 m4_define([b4_lexer_if],
107 [b4_percent_code_ifdef([[lexer]], [$1], [$2])])
110 # b4_position_type_if(TRUE, FALSE)
111 # --------------------------------
112 m4_define([b4_position_type_if],
113 [b4_percent_define_ifdef([[position_type]], [$1], [$2])])
116 # b4_location_type_if(TRUE, FALSE)
117 # --------------------------------
118 m4_define([b4_location_type_if],
119 [b4_percent_define_ifdef([[location_type]], [$1], [$2])])
124 m4_define([b4_identification],
125 [[/** Version number for the Bison executable that generated this parser. */
126 public static immutable string yy_bison_version = "]b4_version_string[";
128 /** Name of the skeleton that generated this parser. */
129 public static immutable string yy_bison_skeleton = ]b4_skeleton[;
137 # b4_int_type(MIN, MAX)
138 # ---------------------
139 # Return the smallest int type able to handle numbers ranging from
140 # MIN to MAX (included).
141 m4_define([b4_int_type],
142 [m4_if(b4_ints_in($@, [-128], [127]), [1], [byte],
143 b4_ints_in($@, [-32768], [32767]), [1], [short],
146 # b4_int_type_for(NAME)
147 # ---------------------
148 # Return the smallest int type able to handle numbers ranging from
149 # `NAME_min' to `NAME_max' (included).
150 m4_define([b4_int_type_for],
151 [b4_int_type($1_min, $1_max)])
155 m4_define([b4_null], [null])
158 # b4_integral_parser_table_define(NAME, DATA, COMMENT)
159 #-----------------------------------------------------
160 # Define "yy<TABLE-NAME>" whose contents is CONTENT.
161 m4_define([b4_integral_parser_table_define],
162 [m4_ifvaln([$3], [b4_comment([$3], [ ])])dnl
163 private static immutable b4_int_type_for([$2])[[]] yy$1_ =
174 m4_define([b4_symbol(-2, id)], [[YYEMPTY]])
175 b4_percent_define_default([[api.token.raw]], [[true]])
177 # b4_token_enum(TOKEN-NAME, TOKEN-NUMBER)
178 # ---------------------------------------
179 # Output the definition of this token as an enum.
180 m4_define([b4_token_enum],
181 [b4_token_format([ %s = %s,
186 # Output the definition of the tokens as enums.
187 m4_define([b4_token_enums],
189 public enum TokenKind {
190 ]b4_symbol(empty, id)[ = -2,
191 b4_symbol_foreach([b4_token_enum])dnl
195 # b4_symbol_translate(STRING)
196 # ---------------------------
197 # Used by "bison" in the array of symbol names to mark those that
198 # require translation.
199 m4_define([b4_symbol_translate],
206 # b4_symbol_kind(NUM)
207 # -------------------
208 m4_define([b4_symbol_kind],
209 [SymbolKind.b4_symbol_kind_base($@)])
212 # b4_symbol_enum(SYMBOL-NUM)
213 # --------------------------
214 # Output the definition of this symbol as an enum.
215 m4_define([b4_symbol_enum],
216 [m4_format([ %-30s %s],
217 m4_format([[%s = %s,]],
218 b4_symbol([$1], [kind_base]),
220 [b4_symbol_tag_comment([$1])])])
223 # b4_declare_symbol_enum
224 # ----------------------
225 # The definition of the symbol internal numbers as an enum.
226 # Defining YYEMPTY here is important: it forces the compiler
227 # to use a signed type, which matters for yytoken.
228 m4_define([b4_declare_symbol_enum],
229 [[ /* Symbol kinds. */
234 ]b4_symbol(empty, kind_base)[ = -2, /* No symbol. */
235 ]b4_symbol_foreach([b4_symbol_enum])dnl
246 /* Return YYSTR after stripping away unnecessary quotes and
247 backslashes, so that it's suitable for yyerror. The heuristic is
248 that double-quoting is unnecessary unless the string contains an
249 apostrophe, a comma, or backslash (other than backslash-backslash).
250 YYSTR is taken from yytname. */
251 final void toString(W)(W sink) const
252 if (isOutputRange!(W, char))
254 immutable string[] yy_sname = @{
256 @};]b4_has_translations_if([[
257 /* YYTRANSLATABLE[SYMBOL-NUM] -- Whether YY_SNAME[SYMBOL-NUM] is
258 internationalizable. */
259 immutable ]b4_int_type_for([b4_translatable])[[] yytranslatable = @{
263 put(sink, yy_sname[yycode_]);
269 # b4-case(ID, CODE, [COMMENTS])
270 # -----------------------------
271 m4_define([b4_case], [ case $1:m4_ifval([$3], [ b4_comment([$3])])
276 ## ---------------- ##
277 ## Default values. ##
278 ## ---------------- ##
280 m4_define([b4_yystype], [b4_percent_define_get([[stype]])])
281 b4_percent_define_default([[stype]], [[YYSemanticType]])])
284 m4_define_default([b4_prefix], [[YY]])
286 b4_percent_define_default([[api.parser.class]], [b4_prefix[]Parser])])
287 m4_define([b4_parser_class], [b4_percent_define_get([[api.parser.class]])])
289 #b4_percent_define_default([[location_type]], [Location])])
290 m4_define([b4_location_type], b4_percent_define_ifdef([[location_type]],[b4_percent_define_get([[location_type]])],[YYLocation]))
292 #b4_percent_define_default([[position_type]], [Position])])
293 m4_define([b4_position_type], b4_percent_define_ifdef([[position_type]],[b4_percent_define_get([[position_type]])],[YYPosition]))
296 ## ----------------- ##
297 ## Semantic Values. ##
298 ## ----------------- ##
301 # b4_symbol_value(VAL, [SYMBOL-NUM], [TYPE-TAG])
302 # ----------------------------------------------
303 # See README. FIXME: factor in c-like?
304 m4_define([b4_symbol_value],
308 [b4_symbol_if([$2], [has_type],
309 [($1.b4_symbol([$2], [type]))],
313 # b4_lhs_value(SYMBOL-NUM, [TYPE])
314 # --------------------------------
316 m4_define([b4_lhs_value],
317 [b4_symbol_value([yyval], [$1], [$2])])
320 # b4_rhs_value(RULE-LENGTH, POS, SYMBOL-NUM, [TYPE])
321 # --------------------------------------------------
324 # In this simple implementation, %token and %type have class names
325 # between the angle brackets.
326 m4_define([b4_rhs_value],
327 [b4_symbol_value([(yystack.valueAt (b4_subtract([$1], [$2])))], [$3], [$4])])
333 m4_define([b4_lhs_location],
337 # b4_rhs_location(RULE-LENGTH, POS)
338 # ---------------------------------
339 # Expansion of @POS, where the current rule has RULE-LENGTH symbols
341 m4_define([b4_rhs_location],
342 [yystack.locationAt (b4_subtract($@))])
348 # If defined, b4_lex_param arrives double quoted, but below we prefer
349 # it to be single quoted. Same for b4_parse_param.
351 # TODO: should be in bison.m4
352 m4_define_default([b4_lex_param], [[]]))
353 m4_define([b4_lex_param], b4_lex_param))
354 m4_define([b4_parse_param], b4_parse_param))
357 # -------------------
358 # Extra formal arguments of the constructor.
359 m4_define([b4_lex_param_decl],
360 [m4_ifset([b4_lex_param],
361 [b4_remove_comma([$1],
362 b4_param_decls(b4_lex_param))],
365 m4_define([b4_param_decls],
366 [m4_map([b4_param_decl], [$@])])
367 m4_define([b4_param_decl], [, $1])
369 m4_define([b4_remove_comma], [m4_ifval(m4_quote($1), [$1, ], [])m4_shift2($@)])
373 # b4_parse_param_decl
374 # -------------------
375 # Extra formal arguments of the constructor.
376 m4_define([b4_parse_param_decl],
377 [m4_ifset([b4_parse_param],
378 [b4_remove_comma([$1],
379 b4_param_decls(b4_parse_param))],
385 # -------------------
386 # Delegating the lexer parameters to the lexer constructor.
387 m4_define([b4_lex_param_call],
388 [m4_ifset([b4_lex_param],
389 [b4_remove_comma([$1],
390 b4_param_calls(b4_lex_param))],
392 m4_define([b4_param_calls],
393 [m4_map([b4_param_call], [$@])])
394 m4_define([b4_param_call], [, $2])
398 # b4_parse_param_cons
399 # -------------------
400 # Extra initialisations of the constructor.
401 m4_define([b4_parse_param_cons],
402 [m4_ifset([b4_parse_param],
403 [b4_constructor_calls(b4_parse_param)])])
405 m4_define([b4_constructor_calls],
406 [m4_map([b4_constructor_call], [$@])])
407 m4_define([b4_constructor_call],
413 # b4_parse_param_vars
414 # -------------------
415 # Extra instance variables.
416 m4_define([b4_parse_param_vars],
417 [m4_ifset([b4_parse_param],
419 /* User arguments. */
420 b4_var_decls(b4_parse_param)])])
422 m4_define([b4_var_decls],
423 [m4_map_sep([b4_var_decl], [
425 m4_define([b4_var_decl],
429 # b4_public_types_declare
430 # -----------------------
431 # Define the public types: token, semantic value, location, and so forth.
432 # Depending on %define token_lex, may be output in the header or source file.
433 m4_define([b4_public_types_declare],
435 alias Symbol = ]b4_parser_class[.Symbol;
436 alias Value = ]b4_yystype[;]b4_locations_if([[
437 alias Location = ]b4_location_type[;
438 alias Position = ]b4_position_type[;]])[
442 # b4_symbol_type_define
443 # ---------------------
444 # Define symbol_type, the external type for symbols used for symbol
446 m4_define([b4_symbol_type_define],
453 private SymbolKind kind;
454 private Value value_;]b4_locations_if([[
455 private Location location_;]])[
456 this(TokenKind token]b4_locations_if([[, Location loc]])[)
458 kind = yytranslate_(token);]b4_locations_if([
461 static foreach (member; __traits(allMembers, YYSemanticType))
463 this(TokenKind token, typeof(mixin("YYSemanticType." ~ member)) val]b4_locations_if([[, Location loc]])[)
465 kind = yytranslate_(token);
466 mixin("value_." ~ member ~ " = val;");]b4_locations_if([
470 SymbolKind token() { return kind; }
471 Value value() { return value_; }]b4_locations_if([[
472 Location location() { return location_; }]])[