bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 8/9] glr2.cc: make the example more C++


From: Akim Demaille
Subject: [PATCH 8/9] glr2.cc: make the example more C++
Date: Sun, 13 Dec 2020 08:49:26 +0100

Currently the example really looks like C.  Instead of a union of
structs to implement the AST, use a hierarchy.  It would be nice to
feature a C++17 version with std variants.

* examples/c++/glr/c++-types.yy (Node, free_node, new_nterm)
(new_term): Move into...
* examples/c++/glr/ast.hh: here, a proper C++ hierarchy.
---
 examples/c++/glr/ast.hh       | 100 +++++++++++++++++++++++++
 examples/c++/glr/c++-types.yy | 134 +++++-----------------------------
 examples/c++/glr/local.mk     |   1 +
 3 files changed, 121 insertions(+), 114 deletions(-)
 create mode 100644 examples/c++/glr/ast.hh

diff --git a/examples/c++/glr/ast.hh b/examples/c++/glr/ast.hh
new file mode 100644
index 00000000..b8eb7de8
--- /dev/null
+++ b/examples/c++/glr/ast.hh
@@ -0,0 +1,100 @@
+#include <iostream>
+
+#if __cplusplus < 201103L
+# define nullptr 0
+#endif
+
+class Node
+{
+public:
+  Node ()
+    : parents_ (0)
+  {}
+
+  virtual ~Node()
+  {}
+
+  void free ()
+  {
+    parents_ -= 1;
+    /* Free only if 0 (last parent) or -1 (no parents).  */
+    if (parents_ <= 0)
+      delete this;
+  }
+
+  virtual std::ostream& print (std::ostream& o) const = 0;
+
+protected:
+  friend class Nterm;
+  friend class Term;
+  int parents_;
+};
+
+
+static std::ostream&
+operator<< (std::ostream& o, const Node &node)
+{
+  return node.print (o);
+}
+
+class Nterm : public Node
+{
+public:
+  Nterm(char const *form,
+        Node *child0 = nullptr, Node *child1 = nullptr, Node *child2 = nullptr)
+    : form_ (form)
+  {
+    children_[0] = child0;
+    if (child0)
+      child0->parents_ += 1;
+    children_[1] = child1;
+    if (child1)
+      child1->parents_ += 1;
+    children_[2] = child2;
+    if (child2)
+      child2->parents_ += 1;
+  }
+
+  ~Nterm()
+  {
+    for (int i = 0; i < 3; ++i)
+      if (children_[i])
+        children_[i]->free ();
+  }
+
+  std::ostream& print (std::ostream& o) const
+  {
+    o << form_;
+    if (children_[0])
+      {
+        o << '(' << *children_[0];
+        if (children_[1])
+          o << ", " << *children_[1];
+        if (children_[2])
+            o << ", " << *children_[2];
+        o << ')';
+      }
+    return o;
+  }
+
+private:
+  char const *form_;
+  Node *children_[3];
+};
+
+class Term : public Node
+{
+public:
+  Term (char *text)
+    : text_ (text)
+  {}
+
+  std::ostream& print (std::ostream& o) const
+  {
+    o << text_;
+    return o;
+  }
+
+private:
+  std::string text_;
+};
diff --git a/examples/c++/glr/c++-types.yy b/examples/c++/glr/c++-types.yy
index ad044c09..e01971b1 100644
--- a/examples/c++/glr/c++-types.yy
+++ b/examples/c++/glr/c++-types.yy
@@ -11,24 +11,7 @@
 
 %code requires
 {
-  union Node {
-    struct {
-      int isNterm;
-      int parents;
-    } nodeInfo;
-    struct {
-      int isNterm; /* 1 */
-      int parents;
-      char const *form;
-      union Node *children[3];
-    } nterm;
-    struct {
-      int isNterm; /* 0 */
-      int parents;
-      char *text;
-    } term;
-  };
-  typedef union Node Node;
+  #include "ast.hh"
 }
 
 %define api.value.type {Node *}
@@ -46,10 +29,6 @@
 # define nullptr 0
 #endif
 
-  static Node *new_nterm (char const *form, Node *child0 = nullptr, Node 
*child1 = nullptr, Node *child2 = nullptr);
-  static Node *new_term (char *);
-  static void free_node (Node *);
-  static std::ostream& operator<< (std::ostream& o, const Node &node);
   static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);
 
   static int yylex (YYSTYPE *lvalp, YYLTYPE *llocp);
@@ -64,31 +43,31 @@
 %right '='
 %left '+'
 
-%destructor { free_node ($$); } stmt expr decl declarator TYPENAME ID
+%destructor { $$->free (); } stmt expr decl declarator TYPENAME ID
 
 %%
 
 prog : %empty
-     | prog stmt   { std::cout << @2 << ": " << *$2 << '\n'; free_node ($2); }
+     | prog stmt   { std::cout << @2 << ": " << *$2 << '\n'; $2->free (); }
      ;
 
 stmt : expr ';'  %merge <stmtMerge>     { $$ = $1; }
      | decl      %merge <stmtMerge>
-     | error ';'        { $$ = new_nterm ("<error>"); }
+     | error ';'        { $$ = new Nterm ("<error>"); }
      | '@'              { $$ = $1; YYACCEPT; }
      ;
 
 expr : ID
      | TYPENAME '(' expr ')'
-                        { $$ = new_nterm ("<cast>", $3, $1); }
-     | expr '+' expr    { $$ = new_nterm ("+", $1, $3); }
-     | expr '=' expr    { $$ = new_nterm ("=", $1, $3); }
+                        { $$ = new Nterm ("<cast>", $3, $1); }
+     | expr '+' expr    { $$ = new Nterm ("+", $1, $3); }
+     | expr '=' expr    { $$ = new Nterm ("=", $1, $3); }
      ;
 
 decl : TYPENAME declarator ';'
-                        { $$ = new_nterm ("<declare>", $1, $2); }
+                        { $$ = new Nterm ("<declare>", $1, $2); }
      | TYPENAME declarator '=' expr ';'
-                        { $$ = new_nterm ("<init-declare>", $1,
+                        { $$ = new Nterm ("<init-declare>", $1,
                                           $2, $4); }
      ;
 
@@ -98,18 +77,6 @@ declarator
      ;
 
 %%
-
-int
-main (int argc, char **argv)
-{
-  // Enable parse traces on option -p.
-  if (1 < argc && strcmp (argv[1], "-p") == 0)
-    yydebug = 1;
-  yy::parser parser;
-  return !!parser.parse ();
-}
-
-
 /* A C error reporting function.  */
 void yy::parser::error (const location_type& l, const std::string& m)
 {
@@ -165,7 +132,7 @@ int yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
                   = isupper (static_cast <unsigned char> (buffer[0]))
                   ? yy::parser::token::TYPENAME
                   : yy::parser::token::ID;
-                *lvalp = new_term (strcpy (static_cast<char*> (malloc (i)), 
buffer));
+                *lvalp = new Term (strcpy (static_cast<char*> (malloc (i)), 
buffer));
               }
             else
               {
@@ -180,79 +147,18 @@ int yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
     }
 }
 
-static Node *
-new_nterm (char const *form, Node *child0, Node *child1, Node *child2)
-{
-  Node *res = new Node;
-  res->nterm.isNterm = 1;
-  res->nterm.parents = 0;
-  res->nterm.form = form;
-  res->nterm.children[0] = child0;
-  if (child0)
-    child0->nodeInfo.parents += 1;
-  res->nterm.children[1] = child1;
-  if (child1)
-    child1->nodeInfo.parents += 1;
-  res->nterm.children[2] = child2;
-  if (child2)
-    child2->nodeInfo.parents += 1;
-  return res;
-}
-
-static Node *
-new_term (char *text)
-{
-  Node *res = new Node;
-  res->term.isNterm = 0;
-  res->term.parents = 0;
-  res->term.text = text;
-  return res;
-}
-
-static void
-free_node (Node *node)
-{
-  if (!node)
-    return;
-  node->nodeInfo.parents -= 1;
-  /* Free only if 0 (last parent) or -1 (no parents).  */
-  if (node->nodeInfo.parents > 0)
-    return;
-  if (node->nodeInfo.isNterm == 1)
-    {
-      free_node (node->nterm.children[0]);
-      free_node (node->nterm.children[1]);
-      free_node (node->nterm.children[2]);
-    }
-  else
-    free (node->term.text);
-  delete node;
-}
-
-static std::ostream&
-operator<< (std::ostream& o, const Node &node)
+static YYSTYPE
+stmtMerge (YYSTYPE x0, YYSTYPE x1)
 {
-  if (node.nodeInfo.isNterm == 1)
-    {
-      o << node.nterm.form;
-      if (node.nterm.children[0])
-        {
-          o << '(' << *node.nterm.children[0];
-          if (node.nterm.children[1])
-            o << ", " << *node.nterm.children[1];
-          if (node.nterm.children[2])
-            o << ", " << *node.nterm.children[2];
-          o << ")";
-        }
-    }
-  else
-    o << node.term.text;
-  return o;
+  return new Nterm ("<OR>", x0, x1);
 }
 
-
-static YYSTYPE
-stmtMerge (YYSTYPE x0, YYSTYPE x1)
+int
+main (int argc, char **argv)
 {
-  return new_nterm ("<OR>", x0, x1);
+  // Enable parse traces on option -p.
+  if (1 < argc && strcmp (argv[1], "-p") == 0)
+    yydebug = 1;
+  yy::parser parser;
+  return !!parser.parse ();
 }
diff --git a/examples/c++/glr/local.mk b/examples/c++/glr/local.mk
index 8558651a..ea53aed1 100644
--- a/examples/c++/glr/local.mk
+++ b/examples/c++/glr/local.mk
@@ -37,6 +37,7 @@ $(%C%_c___types_OBJECTS): $(cxx_types_sources_generated)
 if ENABLE_CXX
   check_PROGRAMS += %D%/c++-types
   nodist_%C%_c___types_SOURCES =               \
+    %D%/ast.hh                                  \
     %D%/c++-types.cc                           \
     %D%/c++-types.hh
   # Don't use gnulib's system headers.
-- 
2.29.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]