summaryrefslogtreecommitdiff
path: root/src/commit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/commit.c')
-rw-r--r--src/commit.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/commit.c b/src/commit.c
new file mode 100644
index 00000000..473f4bbb
--- /dev/null
+++ b/src/commit.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2015 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Colm.
+ *
+ * Colm is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Colm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Colm; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "debug.h"
+#include "pdarun.h"
+#include "bytecode.h"
+#include "tree.h"
+#include "pool.h"
+
+#include "internal.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+//#define true 1
+//#define false 0
+
+static void commit_clear_parse_tree( program_t *prg, tree_t **sp, parse_tree_t *pt )
+{
+ tree_t **top = vm_ptop();
+
+ if ( pt == 0 )
+ return;
+
+free_tree:
+ if ( pt->next != 0 ) {
+ vm_push_ptree( pt->next );
+ }
+
+ if ( pt->left_ignore != 0 ) {
+ vm_push_ptree( pt->left_ignore );
+ }
+
+ if ( pt->child != 0 ) {
+ vm_push_ptree( pt->child );
+ }
+
+ if ( pt->right_ignore != 0 ) {
+ vm_push_ptree( pt->right_ignore );
+ }
+
+ if ( pt->shadow != 0 ) {
+ colm_tree_downref( prg, sp, pt->shadow->tree );
+ kid_free( prg, pt->shadow );
+ }
+
+ //printf( "commit_parse_tree_free %p\n", pt );
+ parse_tree_free( prg, pt );
+
+ /* Any trees to downref? */
+ if ( sp != top ) {
+ pt = vm_pop_ptree();
+ goto free_tree;
+ }
+}
+
+static int been_committed( parse_tree_t *parse_tree )
+{
+ return parse_tree->flags & PF_COMMITTED;
+}
+
+
+static void commit_forward_recurse( program_t *prg, tree_t **root, parse_tree_t *pt )
+{
+ tree_t **sp = root;
+
+ parse_tree_t *lel = pt;
+
+recurse:
+
+ if ( lel->child != 0 ) {
+ /* There are children. Must process all children first. */
+ vm_push_ptree( lel );
+
+ lel = lel->child;
+ while ( lel != 0 ) {
+ goto recurse;
+ resume:
+ lel = lel->next;
+ }
+
+ lel = vm_pop_ptree();
+ }
+
+ /* Now can execute the reduction action. */
+
+ commit_clear_parse_tree( prg, sp, lel->child );
+ lel->child = 0;
+ pt->flags |= PF_COMMITTED;
+
+ if ( sp != root )
+ goto resume;
+}
+
+void commit_clear( program_t *prg, tree_t **root, struct pda_run *pda_run )
+{
+ tree_t **sp = root;
+ parse_tree_t *pt = pda_run->stack_top;
+
+ /* The top level of the stack is linked right to left. This is the
+ * traversal order we need for committing. */
+ while ( pt != 0 && !been_committed( pt ) ) {
+ vm_push_ptree( pt );
+ pt = pt->next;
+ }
+
+ while ( sp != root ) {
+ pt = vm_pop_ptree();
+
+ commit_forward_recurse( prg, sp, pt );
+
+ pt->flags |= PF_COMMITTED;
+ pt = pt->next;
+ }
+}
+
+void commit_reduce( program_t *prg, tree_t **root, struct pda_run *pda_run )
+{
+ tree_t **sp = root;
+ parse_tree_t *pt = pda_run->stack_top;
+
+ /* The top level of the stack is linked right to left. This is the
+ * traversal order we need for committing. */
+ while ( pt != 0 && !been_committed( pt ) ) {
+ vm_push_ptree( pt );
+ pt = pt->next;
+ }
+
+ while ( sp != root ) {
+ pt = vm_pop_ptree();
+
+ commit_clear_parse_tree( prg, sp, pt->child );
+ pt->child = 0;
+
+ pt->flags |= PF_COMMITTED;
+ pt = pt->next;
+ }
+}