From c44a782a4e2a1720676dcbf4d51b4edcf5133ef3 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Mon, 3 Dec 2018 07:03:29 +0100 Subject: [PATCH] backend: revamp the handling of symbol types Currently it is the front end that passes the symbol types to the backend. For instance: %token NUM %type exp1 exp2 exp1: NUM { $$ = $1; } exp2: NUM { $$ = $1; } In both cases, $$ and $1 are passed to the backend as having type 'ival' resulting in code like `val.ival`. This is troublesome in the case of api.value.type=union, since in that the case the code this: %define api.value.type union %token NUM %type exp1 exp2 exp1: NUM { $$ = $1; } exp2: NUM { $$ = $1; } because in this case, since the backend does not know the symbol being processed, it is forced to generate casts in both cases: *(int*)(&val)`. This is unfortunate in the first case (exp1) where there is no reason at all to use a cast instead of `val.NUM` and `val.exp1`. So instead delegate the computation of the actual value type to the backend: pass $$ as `symbol-number, ival` and $$ as `symbol-number, MULL`, instead of passing `ival` before. * src/scan-code.l (handle_action_dollar): Find the symbol the action is about, not just its tyye. Pass both symbol-number, and explicit type tag ($n when there is one) to b4_lhs_value and b4_rhs_value. * data/bison.m4 (b4_symbol_action): adjust to the new signature to b4_dollar_pushdef. * data/c-like.m4 (_b4_dollar_dollar, b4_dollar_pushdef): Accept the symbol-number as new argument. * data/c.m4 (b4_symbol_value): Accept the symbol-number as new argument, and use it. (b4_symbol_value_union): Accept the symbol-number as new argument, and use it to prefer ready a union member rather than casting the union. * data/yacc.c (b4_lhs_value, b4_rhs_value): Accept the new symbol-number argument. Adjust uses of b4_dollar_pushdef. * data/glr.c (b4_lhs_value, b4_rhs_value): Adjust. * data/lalr1.cc (b4_symbol_value_template, b4_lhs_value): Adjust to the new symbol-number argument. * data/variant.hh (b4_symbol_value, b4_symbol_value_template): Accept the new symbol-number argument. * data/java.m4 (b4_symbol_value, b4_rhs_data): New. (b4_rhs_value): Use them. * data/lalr1.java: Adjust to b4_dollar_pushdef, and use b4_rhs_data. --- data/bison.m4 | 4 ++-- data/c-like.m4 | 21 +++++++++++---------- data/c.m4 | 44 ++++++++++++++++++++++++++++++-------------- data/glr.c | 18 +++++++++--------- data/java.m4 | 43 +++++++++++++++++++++++++++++++++++++++---- data/lalr1.cc | 30 +++++++++++++++--------------- data/lalr1.java | 6 +++--- data/variant.hh | 28 ++++++++++++++++++---------- data/yacc.c | 18 +++++++++--------- src/scan-code.l | 25 +++++++++++++++---------- 10 files changed, 151 insertions(+), 86 deletions(-) diff --git a/data/bison.m4 b/data/bison.m4 index 4be8e696..9b80f7d2 100644 --- a/data/bison.m4 +++ b/data/bison.m4 @@ -468,8 +468,8 @@ m4_define([b4_symbol_action_location], m4_define([b4_symbol_action], [b4_symbol_if([$1], [has_$2], [b4_dollar_pushdef([(*yyvaluep)], - b4_symbol_if([$1], [has_type], - [m4_dquote(b4_symbol([$1], [type]))]), + [$1], + [], [(*yylocationp)])dnl _b4_symbol_case([$1])[]dnl b4_syncline([b4_symbol([$1], [$2_line])], [b4_symbol([$1], [$2_file])]) diff --git a/data/c-like.m4 b/data/c-like.m4 index 4e476ac8..ff0e87c5 100644 --- a/data/c-like.m4 +++ b/data/c-like.m4 @@ -39,25 +39,26 @@ m4_define([b4_comment], -# _b4_dollar_dollar(VALUE, FIELD, DEFAULT-FIELD) -# ---------------------------------------------- +# _b4_dollar_dollar(VALUE, SYMBOL-NUM, FIELD, DEFAULT-FIELD) +# ---------------------------------------------------------- # If FIELD (or DEFAULT-FIELD) is non-null, return "VALUE.FIELD", -# otherwise just VALUE. Be sure to pass "(VALUE)" is VALUE is a +# otherwise just VALUE. Be sure to pass "(VALUE)" if VALUE is a # pointer. m4_define([_b4_dollar_dollar], [b4_symbol_value([$1], - m4_if([$2], [[]], - [[$3]], [[$2]]))]) + [$2], + m4_if([$3], [[]], + [[$4]], [[$3]]))]) -# b4_dollar_pushdef(VALUE-POINTER, DEFAULT-FIELD, LOCATION) +# b4_dollar_pushdef(VALUE-POINTER, SYMBOL-NUM, [TYPE_TAG], LOCATION) # b4_dollar_popdef -# --------------------------------------------------------- -# Define b4_dollar_dollar for VALUE and DEFAULT-FIELD, +# ------------------------------------------------------------------ +# Define b4_dollar_dollar for VALUE-POINTER and DEFAULT-FIELD, # and b4_at_dollar for LOCATION. m4_define([b4_dollar_pushdef], [m4_pushdef([b4_dollar_dollar], - [_b4_dollar_dollar([$1], m4_dquote($][1), [$2])])dnl -m4_pushdef([b4_at_dollar], [$3])dnl + [_b4_dollar_dollar([$1], [$2], m4_dquote($][1), [$3])])dnl +m4_pushdef([b4_at_dollar], [$4])dnl ]) m4_define([b4_dollar_popdef], [m4_popdef([b4_at_dollar])dnl diff --git a/data/c.m4 b/data/c.m4 index bb19b348..5e253d63 100644 --- a/data/c.m4 +++ b/data/c.m4 @@ -373,15 +373,28 @@ m4_define([b4_token_enums_defines], ## ----------------- ## -# b4_symbol_value(VAL, [TYPE]) -# ---------------------------- -# Given a semantic value VAL ($$, $1 etc.), extract its value of type -# TYPE if TYPE is given, otherwise just return VAL. The result can be -# used safely, it is put in parens to avoid nasty precedence issues. -# TYPE is *not* put in braces, provide some if needed. +# b4_symbol_value(VAL, [SYMBOL-NUM], [TYPE-TAG]) +# ---------------------------------------------- +# Expansion of $$, $1, $3, etc. +# +# The semantic value from a given VAL. +# +# VAL: some semantic value storage (typically a union). +# e.g., yylval +# SYMBOL-NUM: the symbol number from which we extract the +# type tag. +# TYPE-TAG, the user forced the . +# +# The result can be used safely, it is put in parens to avoid nasty +# precedence issues. m4_define([b4_symbol_value], -[($1[]m4_ifval([$2], [.$2]))]) - +[m4_ifval([$3], + [($1.$3)], + [m4_ifval([$2], + [b4_symbol_if([$2], [has_type], + [($1.b4_symbol([$2], [type]))], + [$1])], + [$1])])]) ## ---------------------- ## @@ -604,14 +617,17 @@ m4_define([b4_type_define_tag], ]) -# b4_symbol_value_union(VAL, [TYPE]) -# ---------------------------------- +# b4_symbol_value_union(VAL, SYMBOL-NUM, [TYPE]) +# ---------------------------------------------- # Same of b4_symbol_value, but when api.value.type=union. m4_define([b4_symbol_value_union], -[m4_ifval([$2], - [(*($2*)(&$1))], - [$1])]) -]) +[m4_ifval([$3], + [(*($3*)(&$1))], + [m4_ifval([$2], + [b4_symbol_if([$2], [has_type], + [($1.b4_symbol([$2], [type_tag]))], + [$1])], + [$1])])]) # b4_value_type_setup_union diff --git a/data/glr.c b/data/glr.c index 4c0c0165..f3e5fc34 100644 --- a/data/glr.c +++ b/data/glr.c @@ -112,11 +112,11 @@ m4_define([b4_locuser_args], ## ----------------- ## -# b4_lhs_value([TYPE]) -# -------------------- -# Expansion of $$. +# b4_lhs_value(SYMBOL-NUM, [TYPE]) +# -------------------------------- +# Expansion of $$ or $$, for symbol SYMBOL-NUM. m4_define([b4_lhs_value], -[b4_symbol_value([(*yyvalp)], [$1])]) +[b4_symbol_value([(*yyvalp)], [$1], [$2])]) # b4_rhs_data(RULE-LENGTH, POS) @@ -127,12 +127,12 @@ m4_define([b4_rhs_data], [((yyGLRStackItem const *)yyvsp)@{YYFILL (b4_subtract([$2], [$1]))@}.yystate]) -# b4_rhs_value(RULE-LENGTH, NUM, [TYPE]) -# -------------------------------------- -# Expansion of $NUM, where the current rule has RULE-LENGTH +# b4_rhs_value(RULE-LENGTH, POS, SYMBOL-NUM, [TYPE]) +# -------------------------------------------------- +# Expansion of $POS, where the current rule has RULE-LENGTH # symbols on RHS. m4_define([b4_rhs_value], -[b4_symbol_value([b4_rhs_data([$1], [$2]).yysemantics.yysval], [$3])]) +[b4_symbol_value([b4_rhs_data([$1], [$2]).yysemantics.yysval], [$3], [$4])]) @@ -2265,7 +2265,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[) yylval = yyval_default;]b4_locations_if([ yylloc = yyloc_default;])[ ]m4_ifdef([b4_initial_action], [ -b4_dollar_pushdef([yylval], [], [yylloc])dnl +b4_dollar_pushdef([yylval], [], [], [yylloc])dnl b4_user_initial_action b4_dollar_popdef])[]dnl [ diff --git a/data/java.m4 b/data/java.m4 index 12491fd4..5290d590 100644 --- a/data/java.m4 +++ b/data/java.m4 @@ -219,21 +219,56 @@ m4_define([b4_position_type], [b4_percent_define_get([[api.position.type]])]) ## ----------------- ## +# b4_symbol_value(VAL, [SYMBOL-NUM], [TYPE-TAG]) +# ---------------------------------------------- +# Expansion of $$, $1, $3, etc. +# +# The semantic value from a given VAL. +# +# VAL: some semantic value storage (typically a union). +# e.g., yylval +# SYMBOL-NUM: the symbol number from which we extract the +# type tag. +# TYPE-TAG, the user forced the . +# +# The result can be used safely, it is put in parens to avoid nasty +# precedence issues. +m4_define([b4_symbol_value], +[m4_ifval([$3], + [(($3)($1))], + [m4_ifval([$2], + [b4_symbol_if([$2], [has_type], + [((b4_symbol([$2], [type]))($1))], + [$1])], + [$1])])]) + + # b4_lhs_value([TYPE]) # -------------------- # Expansion of $$. m4_define([b4_lhs_value], [yyval]) -# b4_rhs_value(RULE-LENGTH, NUM, [TYPE]) -# -------------------------------------- -# Expansion of $NUM, where the current rule has RULE-LENGTH +# b4_rhs_data(RULE-LENGTH, POS) +# ----------------------------- +# Expansion of $POS, where the current rule has RULE-LENGTH +# symbols on RHS. +# +# In this simple implementation, %token and %type have class names +# between the angle brackets. +m4_define([b4_rhs_data], +[yystack.valueAt ($1-($2))]) + +# b4_rhs_value(RULE-LENGTH, POS, SYMBOL-NUM, [TYPE]) +# -------------------------------------------------- +# Expansion of $POS, where the current rule has RULE-LENGTH # symbols on RHS. # # In this simple implementation, %token and %type have class names # between the angle brackets. m4_define([b4_rhs_value], -[(m4_ifval($3, [($3)])[](yystack.valueAt ($1-($2))))]) +[b4_symbol_value([b4_rhs_data([$1], [$2])], [$3], [$4])]) + # b4_lhs_location() # ----------------- diff --git a/data/lalr1.cc b/data/lalr1.cc index b66846b4..e97b9b41 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -41,20 +41,20 @@ m4_define([b4_integral_parser_table_define], };dnl ]) -# b4_symbol_value_template(VAL, [TYPE]) -# ------------------------------------- +# b4_symbol_value_template(VAL, SYMBOL-NUM, [TYPE]) +# ------------------------------------------------- # Same as b4_symbol_value, but used in a template method. It makes # a difference when using variants. Note that b4_value_type_setup_union # overrides b4_symbol_value, so we must override it again. m4_copy([b4_symbol_value], [b4_symbol_value_template]) m4_append([b4_value_type_setup_union], - [m4_copy_force([b4_symbol_value_union], [b4_symbol_value_template])]) +[m4_copy_force([b4_symbol_value_union], [b4_symbol_value_template])]) -# b4_lhs_value([TYPE]) -# -------------------- -# Expansion of $$. +# b4_lhs_value(SYMBOL-NUM, SYMBOL-NUM, [TYPE]) +# -------------------------------------------- +# Expansion of $$ or $$, for symbol SYMBOL-NUM. m4_define([b4_lhs_value], - [b4_symbol_value([yylhs.value], [$1])]) +[b4_symbol_value([yylhs.value], [$1], [$2])]) # b4_lhs_location() @@ -80,12 +80,12 @@ m4_define([b4_rhs_state], [b4_rhs_data([$1], [$2]).state]) -# b4_rhs_value(RULE-LENGTH, NUM, [TYPE]) -# -------------------------------------- -# Expansion of $NUM, where the current rule has RULE-LENGTH +# b4_rhs_value(RULE-LENGTH, POS, SYMBOL-NUM, [TYPE]) +# -------------------------------------------------- +# Expansion of $POS, where the current rule has RULE-LENGTH # symbols on RHS. m4_define([_b4_rhs_value], - [b4_symbol_value([b4_rhs_data([$1], [$2]).value], [$3])]) +[b4_symbol_value([b4_rhs_data([$1], [$2]).value], [$3], [$4])]) m4_define([b4_rhs_value], [b4_percent_define_ifdef([api.value.automove], @@ -109,9 +109,9 @@ m4_define([b4_symbol_action], [b4_symbol_if([$1], [has_$2], [m4_pushdef([b4_symbol_value], m4_defn([b4_symbol_value_template]))[]dnl b4_dollar_pushdef([yysym.value], - b4_symbol_if([$1], [has_type], - [m4_dquote(b4_symbol([$1], [type]))]), - [yysym.location])dnl + [$1], + [], + [yysym.location])dnl _b4_symbol_case([$1]) b4_syncline([b4_symbol([$1], [$2_line])], [b4_symbol([$1], [$2_file])]) b4_symbol([$1], [$2]) @@ -780,7 +780,7 @@ m4_if(b4_prefix, [yy], [], YYCDEBUG << "Starting parse\n"; ]m4_ifdef([b4_initial_action], [ -b4_dollar_pushdef([yyla.value], [], [yyla.location])dnl +b4_dollar_pushdef([yyla.value], [], [], [yyla.location])dnl b4_user_initial_action b4_dollar_popdef])[]dnl diff --git a/data/lalr1.java b/data/lalr1.java index 7326d624..ae87cfb8 100644 --- a/data/lalr1.java +++ b/data/lalr1.java @@ -584,7 +584,7 @@ b4_define_state])[ /* Initialize the stack. */ yystack.push (yystate, yylval ]b4_locations_if([, yylloc])[); ]m4_ifdef([b4_initial_action], [ -b4_dollar_pushdef([yylval], [], [yylloc])dnl +b4_dollar_pushdef([yylval], [], [], [yylloc])dnl b4_user_initial_action b4_dollar_popdef[]dnl ])[ @@ -594,7 +594,7 @@ b4_dollar_popdef[]dnl { push_parse_initialize (); ]m4_ifdef([b4_initial_action], [ -b4_dollar_pushdef([yylval], [], [yylloc])dnl +b4_dollar_pushdef([yylval], [], [], [yylloc])dnl b4_user_initial_action b4_dollar_popdef[]dnl ])[ @@ -1033,7 +1033,7 @@ b4_both_if([[ for (int yyi = 0; yyi < yynrhs; yyi++) yy_symbol_print (" $" + (yyi + 1) + " =", yystos_[yystack.stateAt(yynrhs - (yyi + 1))], - ]b4_rhs_value(yynrhs, yyi + 1)b4_locations_if([, + ]b4_rhs_data(yynrhs, yyi + 1)b4_locations_if([, b4_rhs_location(yynrhs, yyi + 1)])[); } diff --git a/data/variant.hh b/data/variant.hh index 93ee3218..eea2c765 100644 --- a/data/variant.hh +++ b/data/variant.hh @@ -304,20 +304,28 @@ m4_define([b4_value_type_declare], # How the semantic value is extracted when using variants. -# b4_symbol_value(VAL, [TYPE]) -# ---------------------------- +# b4_symbol_value(VAL, SYMBOL-NUM, [TYPE]) +# ---------------------------------------- m4_define([b4_symbol_value], -[m4_ifval([$2], - [$1.as< $2 > ()], - [$1])]) +[m4_ifval([$3], + [$1.as< $3 > ()], + [m4_ifval([$2], + [b4_symbol_if([$2], [has_type], + [$1.as < b4_symbol([$2], [type]) > ()], + [$1])], + [$1])])]) -# b4_symbol_value_template(VAL, [TYPE]) -# ------------------------------------- +# b4_symbol_value_template(VAL, SYMBOL-NUM, [TYPE]) +# ------------------------------------------------- # Same as b4_symbol_value, but used in a template method. m4_define([b4_symbol_value_template], -[m4_ifval([$2], - [$1.template as< $2 > ()], - [$1])]) +[m4_ifval([$3], + [$1.template as< $3 > ()], + [m4_ifval([$2], + [b4_symbol_if([$2], [has_type], + [$1.template as < b4_symbol([$2], [type]) > ()], + [$1])], + [$1])])]) diff --git a/data/yacc.c b/data/yacc.c index ff023e88..e74ba71a 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -128,19 +128,19 @@ m4_define([b4_int_type], ## ----------------- ## -# b4_lhs_value([TYPE]) -# -------------------- -# Expansion of $$. +# b4_lhs_value(SYMBOL-NUM, [TYPE]) +# -------------------------------- +# Expansion of $$ or $$, for symbol SYMBOL-NUM. m4_define([b4_lhs_value], -[b4_symbol_value(yyval, [$1])]) +[b4_symbol_value(yyval, [$1], [$2])]) -# b4_rhs_value(RULE-LENGTH, NUM, [TYPE]) -# -------------------------------------- -# Expansion of $NUM, where the current rule has RULE-LENGTH +# b4_rhs_value(RULE-LENGTH, POS, SYMBOL-NUM, [TYPE]) +# -------------------------------------------------- +# Expansion of $POS, where the current rule has RULE-LENGTH # symbols on RHS. m4_define([b4_rhs_value], - [b4_symbol_value([yyvsp@{b4_subtract([$2], [$1])@}], [$3])]) +[b4_symbol_value([yyvsp@{b4_subtract([$2], [$1])@}], [$3], [$4])]) ## ----------- ## @@ -1426,7 +1426,7 @@ b4_function_define([[yyparse]], [[int]], b4_parse_param)[ yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ ]m4_ifdef([b4_initial_action], [ -b4_dollar_pushdef([m4_define([b4_dollar_dollar_used])yylval], [], +b4_dollar_pushdef([m4_define([b4_dollar_dollar_used])yylval], [], [], [b4_push_if([b4_pure_if([*])yypushed_loc], [yylloc])])dnl b4_user_initial_action b4_dollar_popdef[]dnl diff --git a/src/scan-code.l b/src/scan-code.l index a58ab4be..6ec278a9 100644 --- a/src/scan-code.l +++ b/src/scan-code.l @@ -627,10 +627,9 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc) case LHS_REF: { - if (!type_name) - type_name = symbol_list_n_type_name_get (rule, 0); - - if (!type_name) + symbol_list *sym = symbol_list_n_get (rule, 0); + if (!type_name + && !sym->content.sym->content->type_name) { if (union_seen | tag_seen) { @@ -649,7 +648,8 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc) untyped_var_seen = true; } - obstack_sgrow (&obstack_for_string, "]b4_lhs_value("); + obstack_printf (&obstack_for_string, "]b4_lhs_value(%d, ", + sym->content.sym->content->number); obstack_quote (&obstack_for_string, type_name); obstack_sgrow (&obstack_for_string, ")["); rule->action_props.is_value_used = true; @@ -661,9 +661,9 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc) { if (max_left_semantic_context < 1 - n) max_left_semantic_context = 1 - n; - if (!type_name && 0 < n) - type_name = symbol_list_n_type_name_get (effective_rule, n); - if (!type_name) + symbol_list *sym = 0 < n ? symbol_list_n_get (effective_rule, n) : NULL; + if (!type_name + && (!sym || !sym->content.sym->content->type_name)) { if (union_seen | tag_seen) complain (&dollar_loc, complaint, @@ -674,12 +674,17 @@ handle_action_dollar (symbol_list *rule, char *text, location dollar_loc) } obstack_printf (&obstack_for_string, - "]b4_rhs_value(%d, %d, ", effective_rule_length, n); + "]b4_rhs_value(%d, %d, ", + effective_rule_length, n); + if (sym) + obstack_printf (&obstack_for_string, "%d, ", sym->content.sym->content->number); + else + obstack_sgrow (&obstack_for_string, "[], "); + obstack_quote (&obstack_for_string, type_name); obstack_sgrow (&obstack_for_string, ")["); if (0 < n) { - symbol_list *sym = symbol_list_n_get (effective_rule, n); if (muscle_percent_define_ifdef ("api.value.automove") && sym->action_props.is_value_used) complain (&dollar_loc, Wother,