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
201 # b4_symbol_kind(NUM)
202 # -------------------
203 m4_define([b4_symbol_kind],
204 [SymbolKind.b4_symbol_kind_base($@)])
207 # b4_symbol_enum(SYMBOL-NUM)
208 # --------------------------
209 # Output the definition of this symbol as an enum.
210 m4_define([b4_symbol_enum],
211 [m4_format([ %-30s %s],
212 m4_format([[%s = %s,]],
213 b4_symbol([$1], [kind_base]),
215 [b4_symbol_tag_comment([$1])])])
218 # b4_declare_symbol_enum
219 # ----------------------
220 # The definition of the symbol internal numbers as an enum.
221 # Defining YYEMPTY here is important: it forces the compiler
222 # to use a signed type, which matters for yytoken.
223 m4_define([b4_declare_symbol_enum],
224 [[ /* Symbol kinds. */
229 ]b4_symbol(empty, kind_base)[ = -2, /* No symbol. */
230 ]b4_symbol_foreach([b4_symbol_enum])dnl
241 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
242 First, the terminals, then, starting at \a YYNTOKENS_, nonterminals. */
243 static immutable string[] yytname_ = @{
247 /* Return YYSTR after stripping away unnecessary quotes and
248 backslashes, so that it's suitable for yyerror. The heuristic is
249 that double-quoting is unnecessary unless the string contains an
250 apostrophe, a comma, or backslash (other than backslash-backslash).
251 YYSTR is taken from yytname. */
252 final void toString(W)(W sink) const
253 if (isOutputRange!(W, char))
255 string yystr = yytname_[yycode_];
260 for (int i = 1; i < yystr.length; i++)
268 if (yystr[++i] != '\\')
279 else if (yystr == "$end")
281 put(sink, "end of input");
291 # b4-case(ID, CODE, [COMMENTS])
292 # -----------------------------
293 m4_define([b4_case], [ case $1:m4_ifval([$3], [ b4_comment([$3])])
298 ## ---------------- ##
299 ## Default values. ##
300 ## ---------------- ##
302 m4_define([b4_yystype], [b4_percent_define_get([[stype]])])
303 b4_percent_define_default([[stype]], [[YYSemanticType]])])
306 m4_define_default([b4_prefix], [[YY]])
308 b4_percent_define_default([[api.parser.class]], [b4_prefix[]Parser])])
309 m4_define([b4_parser_class], [b4_percent_define_get([[api.parser.class]])])
311 #b4_percent_define_default([[location_type]], [Location])])
312 m4_define([b4_location_type], b4_percent_define_ifdef([[location_type]],[b4_percent_define_get([[location_type]])],[YYLocation]))
314 #b4_percent_define_default([[position_type]], [Position])])
315 m4_define([b4_position_type], b4_percent_define_ifdef([[position_type]],[b4_percent_define_get([[position_type]])],[YYPosition]))
318 ## ----------------- ##
319 ## Semantic Values. ##
320 ## ----------------- ##
323 # b4_symbol_value(VAL, [SYMBOL-NUM], [TYPE-TAG])
324 # ----------------------------------------------
325 # See README. FIXME: factor in c-like?
326 m4_define([b4_symbol_value],
330 [b4_symbol_if([$2], [has_type],
331 [($1.b4_symbol([$2], [type]))],
335 # b4_lhs_value(SYMBOL-NUM, [TYPE])
336 # --------------------------------
338 m4_define([b4_lhs_value],
339 [b4_symbol_value([yyval], [$1], [$2])])
342 # b4_rhs_value(RULE-LENGTH, POS, SYMBOL-NUM, [TYPE])
343 # --------------------------------------------------
346 # In this simple implementation, %token and %type have class names
347 # between the angle brackets.
348 m4_define([b4_rhs_value],
349 [b4_symbol_value([(yystack.valueAt (b4_subtract([$1], [$2])))], [$3], [$4])])
355 m4_define([b4_lhs_location],
359 # b4_rhs_location(RULE-LENGTH, POS)
360 # ---------------------------------
361 # Expansion of @POS, where the current rule has RULE-LENGTH symbols
363 m4_define([b4_rhs_location],
364 [yystack.locationAt (b4_subtract($@))])
370 # If defined, b4_lex_param arrives double quoted, but below we prefer
371 # it to be single quoted. Same for b4_parse_param.
373 # TODO: should be in bison.m4
374 m4_define_default([b4_lex_param], [[]]))
375 m4_define([b4_lex_param], b4_lex_param))
376 m4_define([b4_parse_param], b4_parse_param))
379 # -------------------
380 # Extra formal arguments of the constructor.
381 m4_define([b4_lex_param_decl],
382 [m4_ifset([b4_lex_param],
383 [b4_remove_comma([$1],
384 b4_param_decls(b4_lex_param))],
387 m4_define([b4_param_decls],
388 [m4_map([b4_param_decl], [$@])])
389 m4_define([b4_param_decl], [, $1])
391 m4_define([b4_remove_comma], [m4_ifval(m4_quote($1), [$1, ], [])m4_shift2($@)])
395 # b4_parse_param_decl
396 # -------------------
397 # Extra formal arguments of the constructor.
398 m4_define([b4_parse_param_decl],
399 [m4_ifset([b4_parse_param],
400 [b4_remove_comma([$1],
401 b4_param_decls(b4_parse_param))],
407 # -------------------
408 # Delegating the lexer parameters to the lexer constructor.
409 m4_define([b4_lex_param_call],
410 [m4_ifset([b4_lex_param],
411 [b4_remove_comma([$1],
412 b4_param_calls(b4_lex_param))],
414 m4_define([b4_param_calls],
415 [m4_map([b4_param_call], [$@])])
416 m4_define([b4_param_call], [, $2])
420 # b4_parse_param_cons
421 # -------------------
422 # Extra initialisations of the constructor.
423 m4_define([b4_parse_param_cons],
424 [m4_ifset([b4_parse_param],
425 [b4_constructor_calls(b4_parse_param)])])
427 m4_define([b4_constructor_calls],
428 [m4_map([b4_constructor_call], [$@])])
429 m4_define([b4_constructor_call],
435 # b4_parse_param_vars
436 # -------------------
437 # Extra instance variables.
438 m4_define([b4_parse_param_vars],
439 [m4_ifset([b4_parse_param],
441 /* User arguments. */
442 b4_var_decls(b4_parse_param)])])
444 m4_define([b4_var_decls],
445 [m4_map_sep([b4_var_decl], [
447 m4_define([b4_var_decl],
451 # b4_public_types_declare
452 # -----------------------
453 # Define the public types: token, semantic value, location, and so forth.
454 # Depending on %define token_lex, may be output in the header or source file.
455 m4_define([b4_public_types_declare],
457 alias Symbol = ]b4_parser_class[.Symbol;
458 alias Value = ]b4_yystype[;]b4_locations_if([[
459 alias Location = ]b4_location_type[;
460 alias Position = ]b4_position_type[;]])[
464 # b4_symbol_type_define
465 # ---------------------
466 # Define symbol_type, the external type for symbols used for symbol
468 m4_define([b4_symbol_type_define],
475 private SymbolKind kind;
476 private Value value_;]b4_locations_if([[
477 private Location location_;]])[
478 this(TokenKind token]b4_locations_if([[, Location loc]])[)
480 kind = yytranslate_(token);]b4_locations_if([
483 static foreach (member; __traits(allMembers, YYSemanticType))
485 this(TokenKind token, typeof(mixin("YYSemanticType." ~ member)) val]b4_locations_if([[, Location loc]])[)
487 kind = yytranslate_(token);
488 mixin("value_." ~ member ~ " = val;");]b4_locations_if([
492 SymbolKind token() { return kind; }
493 Value value() { return value_; }]b4_locations_if([[
494 Location location() { return location_; }]])[