[#]define YYSKELETON_NAME b4_skeleton
/* Pure parsers. */
-[#]define YYPURE b4_pure
+[#]define YYPURE b4_pure_flag
+
+/* Push parsers. */
+[#]define YYPUSH b4_push_flag
/* Using locations. */
[#]define YYLSP_NEEDED b4_locations_flag
])
-
## ---------------- ##
## Default values. ##
## ---------------- ##
m4_define_default([b4_epilogue], [])
+# If the %union is not named, its name is YYSTYPE.
+m4_define_default([b4_union_name], [YYSTYPE])
+
+# The initial column and line.
+m4_define_default([b4_location_initial_column], [1])
+m4_define_default([b4_location_initial_line], [1])
## ------------------------ ##
## Pure/impure interfaces. ##
## ------------------------ ##
-
# b4_user_args
# ------------
m4_define([b4_user_args],
])dnl
])
+
## ------------ ##
## Data Types. ##
## ------------ ##
-
# b4_ints_in(INT1, INT2, LOW, HIGH)
# ---------------------------------
# Return 1 iff both INT1 and INT2 are in [LOW, HIGH], 0 otherwise.
[b4_int_type($1_min, $1_max)])
+## ---------##
+## Values. ##
+## ---------##
+
+# b4_null
+---------
+# Return a null pointer constant. NULL infringes on the user name
+# space in C, so use 0 rather than NULL.
+m4_define([b4_null], [0])
+
+
## ------------------ ##
## Decoding options. ##
## ------------------ ##
+# b4_flag_if(FLAG, IF-TRUE, IF-FALSE)
+# -----------------------------------
+# Run IF-TRUE if b4_FLAG_flag is 1, IF-FALSE if FLAG is 0, otherwise fail.
+m4_define([b4_flag_if],
+[m4_case(b4_$1_flag,
+ [0], [$3],
+ [1], [$2],
+ [m4_fatal([invalid $1 value: ]$1)])])
-# b4_error_verbose_if(IF-TRUE, IF-FALSE)
-# --------------------------------------
-# Expand IF-TRUE, if errors are verbose, IF-FALSE otherwise.
-m4_define([b4_error_verbose_if],
-[m4_if(b4_error_verbose, [1],
- [$1],
- [$2])])
-
-# b4_location_if(IF-TRUE, IF-FALSE)
-# ---------------------------------
-# Expand IF-TRUE, if locations are used, IF-FALSE otherwise.
-m4_define([b4_location_if],
-[m4_if(b4_locations_flag, [1],
- [$1],
- [$2])])
+# b4_define_flag_if(FLAG)
+# -----------------------
+# Define "b4_FLAG_if(IF-TRUE, IF-FALSE)" that depends on the
+# value of the Boolean FLAG.
+m4_define([b4_define_flag_if],
+[_b4_define_flag_if($[1], $[2], [$1])])
+
+# _b4_define_flag_if($1, $2, FLAG)
+# --------------------------------
+# This macro works around the impossibility to define macros
+# inside macros, because issuing `[$1]' is not possible in M4 :(.
+# This sucks hard, GNU M4 should really provide M5 like $$1.
+m4_define([_b4_define_flag_if],
+[m4_if([$1$2], $[1]$[2], [],
+ [m4_fatal([$0: Invalid arguments: $@])])dnl
+m4_define([b4_$3_if],
+ [b4_flag_if([$3], [$1], [$2])])])
+
+
+# b4_FLAG_if(IF-TRUE, IF-FALSE)
+# -----------------------------
+# Expand IF-TRUE, if FLAG is true, IF-FALSE otherwise.
+b4_define_flag_if([defines]) # Whether headers are requested.
+b4_define_flag_if([error_verbose]) # Whether error are verbose.
+b4_define_flag_if([locations]) # Whether locations are tracked.
+b4_define_flag_if([pure]) # Whether the interface is pure.
+b4_define_flag_if([yacc]) # Whether POSIX Yacc is emulated.
-# b4_pure_if(IF-TRUE, IF-FALSE)
+# b4_push_if(IF-TRUE, IF-FALSE)
# -----------------------------
-# Expand IF-TRUE, if %pure-parser, IF-FALSE otherwise.
-m4_define([b4_pure_if],
-[m4_if(b4_pure, [1],
+# Expand IF-TRUE, if %push-parser, IF-FALSE otherwise.
+m4_define([b4_push_if],
+[m4_if(b4_push_flag, [1],
[$1],
[$2])])
# b4_token_enums_defines(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
# -------------------------------------------------------------
-# Output the definition of the tokens (if there are) as enums and #defines.
+# Output the definition of the tokens (if there are any) as enums and, if POSIX
+# Yacc is enabled, as #defines.
m4_define([b4_token_enums_defines],
-[b4_token_enums($@)b4_token_defines($@)
+[b4_token_enums($@)b4_yacc_if([b4_token_defines($@)], [])
])
## Synclines. ##
## ----------- ##
+# b4_basename(NAME)
+# -----------------
+# Similar to POSIX basename; the differences don't matter here.
+# Beware that NAME is not evaluated.
+m4_define([b4_basename],
+[m4_bpatsubst([$1], [^.*/\([^/]+\)/*$], [\1])])
+
+
# b4_syncline(LINE, FILE)
# -----------------------
m4_define([b4_syncline],
-[m4_if(b4_synclines_flag, 1,
- [[#]line $1 $2])])
+[b4_flag_if([synclines],
+[/* Line __line__ of b4_basename(m4_quote(__file__)). */
+[#]line $1 $2])])
+
+# b4_user_code(USER-CODE)
+# -----------------------
+# Emit code from the user, ending it with synclines.
+m4_define([b4_user_code],
+[$1
+b4_syncline([@oline@], [@ofile@])])
+
+
+# b4_define_user_code(MACRO)
+# --------------------------
+# From b4_MACRO, build b4_user_MACRO that includes the synclines.
+m4_define([b4_define_user_code],
+[m4_define([b4_user_$1],
+[b4_user_code([b4_$1])])])
+
+
+# b4_user_actions
+# b4_user_initial_action
+# b4_user_post_prologue
+# b4_user_start_header
+# b4_user_stype
+# ----------------------
+# Macros that issue user code, ending with synclines.
+b4_define_user_code([actions])
+b4_define_user_code([initial_action])
+b4_define_user_code([post_prologue])
+b4_define_user_code([start_header])
+b4_define_user_code([stype])
## -------------- ##
## User actions. ##
## -------------- ##
+# b4_case(LABEL, STATEMENTS)
+# --------------------------
+m4_define([b4_case],
+[ case $1:
+$2
+ break;])
+
# b4_symbol_actions(FILENAME, LINENO,
# SYMBOL-TAG, SYMBOL-NUM,
# SYMBOL-ACTION, SYMBOL-TYPENAME)
[[const char *yymsg], [yymsg]],
[[int yytype], [yytype]],
[[YYSTYPE *yyvaluep], [yyvaluep]][]dnl
-b4_location_if( [, [[YYLTYPE *yylocationp], [yylocationp]]])[]dnl
+b4_locations_if( [, [[YYLTYPE *yylocationp], [yylocationp]]])[]dnl
m4_ifset([b4_parse_param], [, b4_parse_param]))[
{
YYUSE (yyvaluep);
-]b4_location_if([ YYUSE (yylocationp);
+]b4_locations_if([ YYUSE (yylocationp);
])dnl
b4_parse_param_use[]dnl
[
[static void],
[[FILE *yyoutput], [yyoutput]],
[[int yytype], [yytype]],
- [[const YYSTYPE * const yyvaluep], [yyvaluep]][]dnl
-b4_location_if([, [[const YYLTYPE * const yylocationp], [yylocationp]]])[]dnl
+ [[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
+b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
m4_ifset([b4_parse_param], [, b4_parse_param]))[
{
if (!yyvaluep)
return;
-]b4_location_if([ YYUSE (yylocationp);
+]b4_locations_if([ YYUSE (yylocationp);
])dnl
b4_parse_param_use[]dnl
[# ifdef YYPRINT
[static void],
[[FILE *yyoutput], [yyoutput]],
[[int yytype], [yytype]],
- [[const YYSTYPE * const yyvaluep], [yyvaluep]][]dnl
-b4_location_if([, [[const YYLTYPE * const yylocationp], [yylocationp]]])[]dnl
+ [[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
+b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
m4_ifset([b4_parse_param], [, b4_parse_param]))[
{
if (yytype < YYNTOKENS)
else
YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-]b4_location_if([ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+]b4_locations_if([ YY_LOCATION_PRINT (yyoutput, *yylocationp);
YYFPRINTF (yyoutput, ": ");
])dnl
[ yy_symbol_value_print (yyoutput, yytype, yyvaluep]dnl
-b4_location_if([, yylocationp])[]b4_user_args[);
+b4_locations_if([, yylocationp])[]b4_user_args[);
YYFPRINTF (yyoutput, ")");
}]dnl
])