[WIP PATCH for Dlang support] d: token constructors

Adela Vais <[email protected]> Wed, 20 Jan 2021 00:54:00 +0200
Newsgroups gmane.comp.parsers.bison.patches
Message-ID <CAPk8xGeQ7zc=eYDSbsMUzazzg6m5vcjp_E-Uxo9O4qyTkPu7qw@mail.gmail.com>
Hello,

I need some help with the patches I am writing.
I talked today with Akim and I am sending the WIP patches I have as
attachments. If it is easier, here is a Github link [1].
Thank you, Akim, in advance, for your help. After yyaction() works
properly, I can continue modifying the patches. I already expect some
problems with the Symbol's constructors, but that is a D-related problem I
will solve.

A bit of context:

I started working on token constructors and I made them work for the type
of parser that uses %union.

I had trouble when I tried to implement api.value.type union.
(I initially thought I should implement variant, so that is why the second
patch uses it. I tried making my own b4_union_if, that was mimicking
b4_variant_if, but I had no luck, so this is why I still have b4_variant_if
in the code. Regardless, they should be similar enough at this stage.)
The problem is that when I use api.value.type union or variant, in yyaction(),
b4_user_actions uses the type of the union field instead of the union
field. For example:
{ (yyval.int) = ((yystack.valueAt (0)).int); }

Adela

[1] https://github.com/adelavais/bison/tree/token-constructors-squash
0001-d-create-token-constructors.patch (application/octet-stream, 7.3 KB)
From 5e3b8438d1e6c8377ca61965450b10543256df01 Mon Sep 17 00:00:00 2001
From: Adela Vais <[email protected]>
Date: Thu, 14 Jan 2021 01:21:26 +0200
Subject: [PATCH for Dlang support 1/2] d: create token constructors

Symbol's constructor does not check if the TokenKind and the value it receives
correspond. The token constructors are methods of Symbol struct that can
make this check at compile time.

* data/skeletons/d.m4: Here.
* tests/calc.at: Test them.
---
 data/skeletons/d.m4 | 55 +++++++++++++++++++++++++++++++++++++++++++++
 tests/calc.at       | 42 ++++++++++++++++++++++------------
 2 files changed, 83 insertions(+), 14 deletions(-)

diff --git a/data/skeletons/d.m4 b/data/skeletons/d.m4
index 4b5f9f95..0e5b0bda 100644
--- a/data/skeletons/d.m4
+++ b/data/skeletons/d.m4
@@ -201,6 +201,7 @@ b4_symbol_foreach([b4_token_enum])dnl
 }
 ])
 
+
 # b4_symbol_translate(STRING)
 # ---------------------------
 # Used by "bison" in the array of symbol names to mark those that
@@ -208,6 +209,59 @@ b4_symbol_foreach([b4_token_enum])dnl
 m4_define([b4_symbol_translate],
 [[_($1)]])
 
+
+# _b4_token_maker_define_types(SYMBOL-NUM)
+# ----------------------------------
+# Declare the union types for SYMBOL-NUM values.
+m4_define([_b4_token_maker_define_types],
+[b4_token_visible_if([$1],
+  [b4_symbol_if([$1], [has_type],
+    [      "][b4_symbol([$1], [type])]["],
+    [      "void"]),
+])])
+
+
+# b4_token_constructor_define
+# ---------------------------
+# Define the overloaded versions of make_symbol for all the value types.
+m4_define([b4_token_constructor_define],
+[[    immutable string[] visibleTokenTypes = @{
+]b4_symbol_foreach([_b4_token_maker_define_types])[    @};
+    /* Implementation of token constructors for each symbol type visible to
+       the user. The visibleTokenTypes array provides the types.
+       The code generates static methods that have the names as the TokenKinds. */
+    static foreach (member; __traits(allMembers, TokenKind))
+    {
+      static if (mixin("TokenKind." ~ member) >= 0)
+      {
+        static if (visibleTokenTypes[mixin("TokenKind." ~ member)] == "void")
+        {]b4_locations_if([[
+          mixin("static auto " ~ member ~ " (Location l)
+          {
+            return Symbol(TokenKind." ~ member ~ ", l);
+          }");]], [[
+          mixin("static auto " ~ member ~ "()
+          {
+            return Symbol(TokenKind." ~ member ~ ");
+          }");]])[
+        }
+        else
+        {]b4_locations_if([[
+          mixin("static auto " ~ member ~ "(typeof(YYSemanticType." ~
+            visibleTokenTypes[mixin("TokenKind." ~ member)] ~ ") v, Location l)
+          {
+            return Symbol(TokenKind." ~ member ~ ", v, l);
+          }");]], [[
+          mixin("static auto " ~ member ~ "(typeof(YYSemanticType." ~
+             visibleTokenTypes[mixin("TokenKind." ~ member)] ~ ") v)
+          {
+            return Symbol(TokenKind." ~ member ~ ", v);
+          }");]])[
+        }
+      }
+    }]])
+
+
 ## -------------- ##
 ## Symbol kinds.  ##
 ## -------------- ##
@@ -479,5 +533,6 @@ m4_define([b4_symbol_type_define],
     SymbolKind token() { return kind; }
     Value value() { return value_; }]b4_locations_if([[
     Location location() { return location_; }]])[
+]b4_token_ctor_if([b4_token_constructor_define])[
   }
 ]])
diff --git a/tests/calc.at b/tests/calc.at
index 1d2e818d..2904bae5 100644
--- a/tests/calc.at
+++ b/tests/calc.at
@@ -519,6 +519,18 @@ m4_copy([_AT_DATA_CALC_Y(c)], [_AT_DATA_CALC_Y(c++)])
 ## Calc in D.  ##
 ## ----------- ##
 
+# YYLEX_RETURN_WITH_VALUE
+m4_define([YYLEX_RETURN_WITH_VALUE],
+[AT_TOKEN_CTOR_IF([[return Symbol.]AT_TOKEN_PREFIX[$1]($2 AT_LOCATION_IF([[, location]])[);]],
+                  [[return Symbol(TokenKind.]AT_TOKEN_PREFIX[$1, $2]AT_LOCATION_IF([[, location]])[);]])]
+)
+
+# YYLEX_RETURN_WITHOUT_VALUE
+m4_define([YYLEX_RETURN_WITHOUT_VALUE],
+[AT_TOKEN_CTOR_IF([[return Symbol.]AT_TOKEN_PREFIX[$1](AT_LOCATION_IF([[location]])[);]],
+                  [[return Symbol(TokenKind.]AT_TOKEN_PREFIX[$1]AT_LOCATION_IF([[, location]])[);]])]
+)
+
 # AT_CALC_MAIN(d).
 m4_define([AT_CALC_MAIN(d)],
 [[int main (string[] args)
@@ -598,13 +610,13 @@ class CalcLexer(R) : Lexer
 
     // EOF.
     if (input.empty)
-      return Symbol(TokenKind.]AT_TOKEN_PREFIX[EOF]AT_LOCATION_IF([[, location]])[);
+      ]YYLEX_RETURN_WITHOUT_VALUE([EOF])[
 
     // Numbers.
     if (input.front.isNumber)
       {
         value_.ival = parseInt;
-        return Symbol(TokenKind.]AT_TOKEN_PREFIX[NUM, value_.ival]AT_LOCATION_IF([[, location]])[);
+        ]YYLEX_RETURN_WITH_VALUE([NUM], [value_.ival])[
       }
 
     // Individual characters
@@ -622,22 +634,22 @@ class CalcLexer(R) : Lexer
     if (c == '#')
       {
         stderr.writeln (]AT_LOCATION_IF([location, ": ", ])["syntax error: invalid character: '#'");
-        return Symbol(TokenKind.]AT_TOKEN_PREFIX[YYerror]AT_LOCATION_IF([[, location]])[);
+        ]YYLEX_RETURN_WITHOUT_VALUE([YYerror])[
       }
 
     switch (c)
     {
-      case '+':  return Symbol(TokenKind.]AT_TOKEN_PREFIX[PLUS]AT_LOCATION_IF([[, location]])[);
-      case '-':  return Symbol(TokenKind.]AT_TOKEN_PREFIX[MINUS]AT_LOCATION_IF([[, location]])[);
-      case '*':  return Symbol(TokenKind.]AT_TOKEN_PREFIX[STAR]AT_LOCATION_IF([[, location]])[);
-      case '/':  return Symbol(TokenKind.]AT_TOKEN_PREFIX[SLASH]AT_LOCATION_IF([[, location]])[);
-      case '(':  return Symbol(TokenKind.]AT_TOKEN_PREFIX[LPAR]AT_LOCATION_IF([[, location]])[);
-      case ')':  return Symbol(TokenKind.]AT_TOKEN_PREFIX[RPAR]AT_LOCATION_IF([[, location]])[);
-      case '\n': return Symbol(TokenKind.]AT_TOKEN_PREFIX[EOL]AT_LOCATION_IF([[, location]])[);
-      case '=':  return Symbol(TokenKind.]AT_TOKEN_PREFIX[EQUAL]AT_LOCATION_IF([[, location]])[);
-      case '^':  return Symbol(TokenKind.]AT_TOKEN_PREFIX[POW]AT_LOCATION_IF([[, location]])[);
-      case '!':  return Symbol(TokenKind.]AT_TOKEN_PREFIX[NOT]AT_LOCATION_IF([[, location]])[);
-      default:   return Symbol(TokenKind.]AT_TOKEN_PREFIX[YYUNDEF]AT_LOCATION_IF([[, location]])[);
+      case '+':  ]YYLEX_RETURN_WITHOUT_VALUE([PLUS])[
+      case '-':  ]YYLEX_RETURN_WITHOUT_VALUE([MINUS])[
+      case '*':  ]YYLEX_RETURN_WITHOUT_VALUE([STAR])[
+      case '/':  ]YYLEX_RETURN_WITHOUT_VALUE([SLASH])[
+      case '(':  ]YYLEX_RETURN_WITHOUT_VALUE([LPAR])[
+      case ')':  ]YYLEX_RETURN_WITHOUT_VALUE([RPAR])[
+      case '\n': ]YYLEX_RETURN_WITHOUT_VALUE([EOL])[
+      case '=':  ]YYLEX_RETURN_WITHOUT_VALUE([EQUAL])[
+      case '^':  ]YYLEX_RETURN_WITHOUT_VALUE([POW])[
+      case '!':  ]YYLEX_RETURN_WITHOUT_VALUE([NOT])[
+      default:   ]YYLEX_RETURN_WITHOUT_VALUE([YYUNDEF])[
     }
   }
 }
@@ -1505,6 +1517,8 @@ AT_CHECK_CALC_LALR1_D([%locations %define parse.lac full %define parse.error det
 #AT_CHECK_CALC_LALR1_D([%locations %define parse.error detailed %debug %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
 #AT_CHECK_CALC_LALR1_D([%locations %define parse.error detailed %debug %define api.prefix {calc} %verbose %parse-param {semantic_value *result}{int *count}{int *nerrs}])
 
+AT_CHECK_CALC_LALR1_D([%define api.token.constructor %define parse.error custom])
+AT_CHECK_CALC_LALR1_D([%define api.token.constructor %locations %define parse.error detailed])
 
 # ----------------------- #
 # LALR1 Java Calculator.  #
-- 
2.17.1
0002-d-add-api.value.type-union-support.patch (application/octet-stream, 2.3 KB)
From a66d922e9fd1de570fa78914ad6630125017610a Mon Sep 17 00:00:00 2001
From: Adela Vais <[email protected]>
Date: Tue, 19 Jan 2021 20:33:05 +0200
Subject: [PATCH for Dlang support 2/2] d: add api.value.type union support

---
 data/skeletons/d.m4    | 14 ++++++++++++--
 data/skeletons/lalr1.d |  5 +++--
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/data/skeletons/d.m4 b/data/skeletons/d.m4
index 0e5b0bda..44b022db 100644
--- a/data/skeletons/d.m4
+++ b/data/skeletons/d.m4
@@ -221,6 +221,16 @@ m4_define([_b4_token_maker_define_types],
 ])])
 
 
+# b4_union_define_types(SYMBOL-NUM)
+# ----------------------------------
+# Declare the union entry for SYMBOL-NUM values.
+m4_define([b4_union_define_types],
+[b4_token_visible_if([$1],
+  [b4_symbol_if([$1], [has_type],
+    [  ][b4_symbol([$1], [type])][ ][b4_symbol([$1], [id])][;], [dnl])
+])])
+
+
 # b4_token_constructor_define
 # ---------------------------
 # Define the overloaded versions of make_symbol for all the value types.
@@ -247,12 +257,12 @@ m4_define([b4_token_constructor_define],
         }
         else
         {]b4_locations_if([[
-          mixin("static auto " ~ member ~ "(typeof(YYSemanticType." ~
+          mixin("static auto " ~ member ~ "(]b4_variant_if([[]], [[typeof(YYSemanticType.]])[" ~
             visibleTokenTypes[mixin("TokenKind." ~ member)] ~ ") v, Location l)
           {
             return Symbol(TokenKind." ~ member ~ ", v, l);
           }");]], [[
-          mixin("static auto " ~ member ~ "(typeof(YYSemanticType." ~
+          mixin("static auto " ~ member ~ "(]b4_variant_if([[]], [[typeof(YYSemanticType.]])[" ~
              visibleTokenTypes[mixin("TokenKind." ~ member)] ~ ") v)
           {
             return Symbol(TokenKind." ~ member ~ ", v);
diff --git a/data/skeletons/lalr1.d b/data/skeletons/lalr1.d
index 62b12d1c..ff80490f 100644
--- a/data/skeletons/lalr1.d
+++ b/data/skeletons/lalr1.d
@@ -207,8 +207,9 @@ public struct ]b4_location_type[
 private immutable bool yy_location_is_class = false;
 
 ]])])m4_ifdef([b4_user_union_members], [private union YYSemanticType
-{
-b4_user_union_members
+{]b4_variant_if([[
+]b4_symbol_foreach([b4_union_define_types])[]],
+[[b4_user_union_members]])[
 };],
 [m4_if(b4_tag_seen_flag, 0,
 [[private alias int YYSemanticType;]])])[
-- 
2.17.1