[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
- [PATCH 0/9] glr2.cc: fixes, Akim Demaille, 2020/12/13
- [PATCH 1/9] glr2.cc: add sanity checks in glr_stack_item, Akim Demaille, 2020/12/13
- [PATCH 3/9] glr2.cc: style fixes, Akim Demaille, 2020/12/13
- [PATCH 2/9] glr2.cc: add sanity check in glr_state, Akim Demaille, 2020/12/13
- [PATCH 4/9] glr2.cc: fix pointer arithmethics, Akim Demaille, 2020/12/13
- [PATCH 5/9] glr2.cc: fix yycompressStack, Akim Demaille, 2020/12/13
- [PATCH 6/9] glr2.cc: being pure is not an option, Akim Demaille, 2020/12/13
- [PATCH 7/9] glr2.cc: make yyparse a member function, Akim Demaille, 2020/12/13
- [PATCH 8/9] glr2.cc: make the example more C++,
Akim Demaille <=
- [PATCH 9/9] glr.c: comment changes, Akim Demaille, 2020/12/13