/* 
 * This header (everything before the first "%%") is copied 
 * directly to the output.
 */

#include <glib.h>
#include <stdio.h>
#include <string.h>

#define MBTREE_TYPE  MBTree

typedef struct _MBTree MBTree;
struct _MBTree {
	guint16 op;
	MBTree *left, *right;
	gpointer state;
};

%% these are the monoburg definition
#
# This is the start of the definitions
# comments start with a '#' as first line character
#

#
# we must fisrt define the terminals
# with or without numbers
# 
%term Assign Constant Fetch=3 Four=8 Mul=5 Plus=6 AltFetch=7

#
# optional start nonterminal
#
%start reg

con:  Constant                0 

con:  Four                    0 

addr: con                     0 

addr: Plus(con,reg)           
{
	int ern = mono_burg_rule (tree->state, MB_NTERM_addr);
	printf ("%s\n", mono_burg_rule_string [ern]);
} cost 
{  
  return 1;
}

addr: Plus(con,Mul(Four,reg)) 2 
{
	int ern = mono_burg_rule (tree->state, MB_NTERM_addr);
	printf ("%s\n", mono_burg_rule_string [ern]);
} 

reg:  AltFetch(addr),
reg:  Fetch(addr)             1 
{
	int ern = mono_burg_rule (tree->state, MB_NTERM_reg);
	printf ("%s\n", mono_burg_rule_string [ern]);
}

reg:  Assign(addr,reg)        1 
{
	int ern = mono_burg_rule (tree->state, MB_NTERM_reg);
	printf ("%s\n", mono_burg_rule_string [ern]);
}

%% the rest is also copied directly to the output
/* everything below the second "%%" is also copied directly
 * to the output file.
 */

static MBTree *
create_tree (int op, MBTree *left, MBTree *right)
{
	MBTree *t = g_new0 (MBTree, 1);
	
	t->op = op;
	t->left = left;
	t->right = right;

	return t;
}

static void
reduce (MBTree *tree, int goal) 
{
	MBTree *kids[10];
	int ern = mono_burg_rule (tree->state, goal);
	guint16 *nts = mono_burg_nts [ern];
	int i, n;

	mono_burg_kids (tree, ern, kids);

	// printf ("TEST %d %d %s %d\n", goal, ern, mono_burg_rule_string [ern], nts [0]);
	
	for (i = 0; nts [i]; i++) 
		reduce (kids [i], nts [i]);

	n = (tree->left != NULL) + (tree->right != NULL);

	if (n) { /* not a terminal */
	  // printf ("XXTE %s %d\n", mono_burg_rule_string [ern], n);
		if (mono_burg_func [ern])
			mono_burg_func [ern] (tree, NULL);
		else
			g_warning ("no code for rule %s\n", 
				   mono_burg_rule_string [ern]);
	} else {
		if (mono_burg_func [ern])
			g_warning ("unused code in rule %s\n", 
				   mono_burg_rule_string [ern]);
	}
}

int
main ()
{
	MBTree *t, *l, *r;
	MBState *s;

	l = create_tree (MB_TERM_Constant, NULL, NULL);

	r = create_tree (MB_TERM_Fetch, l, NULL);
	l = create_tree (MB_TERM_Constant, NULL, NULL);

	r = create_tree (MB_TERM_Assign, l, r);
	l = create_tree (MB_TERM_Four, NULL, NULL);

	r = create_tree (MB_TERM_Mul, l, r);
	l = create_tree (MB_TERM_Constant, NULL, NULL);

	l = create_tree (MB_TERM_Plus, l, r);

	t = create_tree (MB_TERM_Fetch, l, NULL);

	s = mono_burg_label (t, NULL);

	g_assert (s);

	reduce (t, MB_NTERM_reg);

	return 0;
}
