Commit 1a8ce03d authored by Michal Cadilhac's avatar Michal Cadilhac

2005-09-16 Michael Cadilhac <michael.cadilhac@lrde.epita.fr>

	* src/named_subtree.h,
	* src/named_subtree.c: New. Named subtree related functions.
	Allow use in multi-rules.
	
	* src/rule.c,
	* src/rule.h: Move named subtree related functions to
	`src/named_subtree.[ch]'.
	Move memory cleaning related functions to `src/mem_clean.[ch]'
	
	* src/mem_clean.c,
	* src/mem_clean.h: New. Memory cleaning related functions.
	
	* src/emit_files.c: Use `mem_clean.h'.
	
	* src/parser.y,
	* src/emit_functions.c,
	* src/emit_cost.c: Allow named subtree in multi-rules.
	
	* src/main.c: Fix to (close to) compile with -pedantic.
	
	* src/Makefile.am: Add new files.
	* tests/sample.c.ref: Regen.
	
	* configure.ac,
	* NEWS: Bump to 1.0.4.
parent 5becb42c
2005-09-16 Michael Cadilhac <michael.cadilhac@lrde.epita.fr>
* src/named_subtree.h,
* src/named_subtree.c: New. Named subtree related functions.
Allow use in multi-rules.
* src/rule.c,
* src/rule.h: Move named subtree related functions to
`src/named_subtree.[ch]'.
Move memory cleaning related functions to `src/mem_clean.[ch]'
* src/mem_clean.c,
* src/mem_clean.h: New. Memory cleaning related functions.
* src/emit_files.c: Use `mem_clean.h'.
* src/parser.y,
* src/emit_functions.c,
* src/emit_cost.c: Allow named subtree in multi-rules.
* src/main.c: Fix to (close to) compile with -pedantic.
* src/Makefile.am: Add new files.
* tests/sample.c.ref: Regen.
* configure.ac,
* NEWS: Bump to 1.0.4.
2005-09-16 Michael Cadilhac <michael.cadilhac@lrde.epita.fr>
* tests/Makefile.am: Use diff(1) instead of cmp(1) if VERBOSE is set.
......
* 1.0.4
** Support named subtree with multi rules
One can now do:
num: Plus (Name1 : num, Name2 : num),
num: Moins (Name3 : num, Name4 : num)
Moreover, Name3 could be renamed Name1. The only restriction
is that Name4 couldn't be named Name1 nor Name3.
* 1.0.3
** Add --with-line option
......
......@@ -14,7 +14,7 @@
## -------------------------------------
## Project
AC_INIT([MonoBURG], [1.0.3a])
AC_INIT([MonoBURG], [1.0.4])
AM_CONFIG_HEADER([config.h])
## -------------------------------------
......
......@@ -24,6 +24,8 @@ monoburg_SOURCES = \
emit_functions.c emit_kids.c \
emit_pretty_print.c main.c \
monoburg.h parser.h \
rule.c rule.h
rule.c rule.h \
mem_clean.c mem_clean.h \
named_subtree.c named_subtree.h
monoburg_LDADD = $(GLIB_LIBS)
......@@ -51,7 +51,7 @@ void emit_cost_func ()
output ("(void) state;\n");
else
output ("(void) tree;\n");
output ("\t{\n%s\n\t}\n", rule->cfunc);
output ("%s\n", rule->cfunc);
output ("}\n\n");
}
i++;
......
......@@ -20,6 +20,7 @@
#include "monoburg.h"
#include "parser.h"
#include "mem_clean.h"
#include "emit.h"
/** Output header file data. */
......
......@@ -21,9 +21,6 @@
#include "monoburg.h"
#include "emit.h"
static void emit_tree_variables (char *prefix, int depth, Tree *t);
static void emit_rule_variables (Rule *rule);
/** Emit rule functions. */
void emit_emitter_func ()
{
......@@ -47,7 +44,7 @@ void emit_emitter_func ()
if (dag_mode)
output ("mono_burg_emit_%d (MBState *state, MBTREE_TYPE %ctree, MBCGEN_TYPE *s)\n", i,
(with_references ? '&' : '*'));
(with_references ? '&' : '*'));
else
output ("mono_burg_emit_%d (MBTREE_TYPE %ctree, MBCGEN_TYPE *s)\n", i,
(with_references ? '&' : '*'));
......@@ -56,9 +53,7 @@ void emit_emitter_func ()
output ("\t(void) tree; (void) s;");
if (dag_mode)
output (" (void) state;");
output ("\n\t{\n");
emit_rule_variables (rule);
output ("%s\n\t}\n", rule->code);
output ("\n\t{\n%s\n\t}\n", rule->code);
output ("}\n\n");
g_hash_table_insert (cache, rule->code, GINT_TO_POINTER (i + 1));
}
......@@ -81,47 +76,3 @@ void emit_emitter_func ()
}
output ("};\n\n");
}
/** Emit named rule parts of a rule. */
static void emit_rule_variables (Rule *rule)
{
Tree *t = rule->tree;
if (t) {
emit_tree_variables ("", 0, t);
}
}
/** Emit named rule parts of a rule tree. */
static void emit_tree_variables (char *prefix, int depth, Tree *t)
{
char *tn;
int i;
if (t->varname) {
if (with_references) {
output ("MBTREE_TYPE &%s = *(%s(&tree))",
t->varname, prefix);
} else {
output ("MBTREE_TYPE *%s = (%s(tree))",
t->varname, prefix);
}
for (i = 0; i < depth; ++i)
output (")");
output (";\n");
}
if (t->left) {
tn = g_strconcat ("MBTREE_LEFT(", prefix, NULL);
emit_tree_variables (tn, depth + 1, t->left);
g_free (tn);
}
if (t->right) {
tn = g_strconcat ("MBTREE_RIGHT(", prefix, NULL);
emit_tree_variables (tn, depth + 1, t->right);
g_free (tn);
}
}
......@@ -18,8 +18,6 @@
** \brief Main function. Option parsing, and so on.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <glib/goption.h>
#include "monoburg.h"
......@@ -53,11 +51,11 @@ gboolean predefined_terms = 0;
GOPTION_CALLBACK (add_to_defined_vars,
g_hash_table_insert (definedvars, g_strdup (value),
GUINT_TO_POINTER (1));
return TRUE;);
return TRUE;)
GOPTION_CALLBACK (add_to_include_dirs,
include_dirs = g_list_append (include_dirs, g_strdup (value));
return TRUE);
return TRUE;)
static void bad_use (const char *program_name, const char *use)
{
......
/**
** mem_clean.c: this file is part of MonoBURG.
**
** MonoBURG, an iburg like code generator generator.
**
** Copyright (C) 2001, 2002, 2004, 2005 Ximian, Inc.
**
** This program 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.
**
** The complete GNU General Public Licence Notice can be found as the
** `NOTICE' file in the root directory.
**
** \author Dietmar Maurer (dietmar@ximian.com)
** \author Cadilhac Michael (cadilhac@lrde.org)
** \brief Cleaning functions that free everything.
*/
#include "monoburg.h"
#include "rule.h"
#include "mem_clean.h"
static void free_tree (Tree *tree);
static void free_vartree (VarTree *tree);
static void free_prefix (void);
static void free_rules_prevent_refree (Rule *rule, GList *rule_list);
void free_rules (void)
{
GList *rule;
Rule *p_rule;
for (rule = rule_list; rule; rule = rule->next ) {
p_rule = (Rule *) rule->data;
free_rules_prevent_refree (p_rule, rule->next);
g_free (p_rule->cost);
g_free (p_rule->cfunc);
g_free (p_rule->code);
free_tree (p_rule->tree);
free_vartree (p_rule->vartree);
g_free (p_rule);
}
g_list_free (rule_list);
free_prefix ();
}
void free_terms (void)
{
GList *term;
Term *p_term;
for (term = term_list; term; term = term->next) {
p_term = (Term *) term->data;
g_free (p_term->name);
g_list_free (p_term->rules);
g_free (p_term);
}
g_list_free (term_list);
g_hash_table_destroy (term_hash);
}
void free_nonterms (void)
{
GList *nonterm = nonterm_list;
NonTerm *p_nonterm;
for (nonterm = nonterm_list; nonterm; nonterm = nonterm->next) {
p_nonterm = (NonTerm *) nonterm->data;
g_free (p_nonterm->name);
g_list_free (p_nonterm->chain);
g_list_free (p_nonterm->rules);
g_free (p_nonterm);
}
g_list_free (nonterm_list);
g_hash_table_destroy (nonterm_hash);
}
static void free_tree (Tree *tree)
{
if (!tree)
return;
free_tree (tree->left);
free_tree (tree->right);
g_free (tree);
}
static void free_vartree (VarTree *tree)
{
GList *varnames;
if (!tree)
return;
for (varnames = tree->varnames; varnames; varnames = varnames->next)
g_free (varnames->data);
g_list_free (tree->varnames);
free_vartree (tree->left);
free_vartree (tree->right);
g_free (tree);
}
static void free_prefix (void)
{
GList *prefix;
for (prefix = prefix_list; prefix; prefix = prefix->next) {
g_free (prefix->data);
}
g_list_free (prefix);
}
static void free_rules_prevent_refree (Rule *rule, GList *rule_list)
{
char *cost = rule->cost;
char *cfunc = rule->cfunc;
char *code = rule->code;
Tree *tree = rule->tree;
for (; rule_list; rule_list = rule_list->next) {
rule = (Rule *) rule_list->data;
if (cost == rule->cost)
rule->cost = NULL;
if (cfunc == rule->cfunc)
rule->cfunc = NULL;
if (code == rule->code)
rule->code = NULL;
if (tree == rule->tree)
rule->tree = NULL;
}
}
/**
** mem_clean.h: this file is part of MonoBURG.
**
** MonoBURG, an iburg like code generator generator.
**
** Copyright (C) 2001, 2002, 2004, 2005 Ximian, Inc.
**
** This program 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.
**
** The complete GNU General Public Licence Notice can be found as the
** `NOTICE' file in the root directory.
**
** \author Dietmar Maurer (dietmar@ximian.com)
** \author Cadilhac Michael (cadilhac@lrde.org)
** \brief Memory freeing related functions.
*/
#ifndef __MONO_MEM_CLEAN_H__
# define __MONO_MEM_CLEAN_H__
void free_rules (void);
void free_terms (void);
void free_nonterms (void);
#endif /* __MONO_MEM_CLEAN_H__ */
/**
** named_subtree.c: this file is part of MonoBURG.
**
** MonoBURG, an iburg like code generator generator.
**
** Copyright (C) 2001, 2002, 2004, 2005 Ximian, Inc.
**
** This program 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.
**
** The complete GNU General Public Licence Notice can be found as the
** `NOTICE' file in the root directory.
**
** \author Dietmar Maurer (dietmar@ximian.com)
** \author Cadilhac Michael (cadilhac@lrde.org)
** \brief Named subtree related functions.
*/
#include <string.h>
#include "monoburg.h"
#include "parser.h"
#include "named_subtree.h"
static char *compute_vartree_decs_ (char *prefix, int depth, VarTree *t);
static void fill_vartree_ (VarTree **p_vartree, Tree *tree,
VarTree *vartree_root);
static void check_varname (char *varname, VarTree *t);
/** Compute declarations of a variable tree. */
char *compute_vartree_decs (VarTree *t)
{
return compute_vartree_decs_ ("", 0, t);
}
static char *compute_vartree_decs_ (char *prefix, int depth, VarTree *t)
{
char *res = g_strdup ("");
char *child;
char *tmp_res;
char *tn;
int i;
if (t->varnames) {
GList *varnames = t->varnames;
for (; varnames; varnames = varnames->next) {
if (with_references)
tmp_res = "%s\tMBTREE_TYPE &%s = *(%s(&tree))";
else
tmp_res = "%s\tMBTREE_TYPE *%s = (%s(tree))";
tmp_res = g_strdup_printf (tmp_res, res,
(char *) varnames->data, prefix);
g_free (res);
res = tmp_res;
for (i = 0; i < depth; ++i) {
tmp_res = g_strconcat (res, ")", NULL);
g_free (res);
res = tmp_res;
}
tmp_res = g_strconcat (res, ";\n", NULL);
g_free (res);
res = tmp_res;
}
}
if (t->left) {
tn = g_strconcat ("MBTREE_LEFT(", prefix, NULL);
child = compute_vartree_decs_ (tn, depth + 1, t->left);
tmp_res = g_strconcat (res, child, NULL);
g_free (child);
g_free (res);
res = tmp_res;
g_free (tn);
}
if (t->right) {
tn = g_strconcat ("MBTREE_RIGHT(", prefix, NULL);
child = compute_vartree_decs_ (tn, depth + 1, t->right);
tmp_res = g_strconcat (res, child, NULL);
g_free (child);
g_free (res);
res = tmp_res;
g_free (tn);
}
return res;
}
/** Compute void uses of variable in a tree. */
char *compute_vartree_void_use (VarTree *t)
{
char *res = g_strdup ("");
char *tmp_res;
char *child;
if (t->varnames) {
GList *varnames = t->varnames;
for (; varnames; varnames = varnames->next) {
tmp_res = g_strdup_printf ("%s%s(void) %s;",
*res ? res : "\t",
*res ? " " : "",
(char *) varnames->data);
g_free (res);
res = tmp_res;
}
tmp_res = g_strconcat (res, "\n", NULL);
g_free (res);
res = tmp_res;
}
if (t->left) {
child = compute_vartree_void_use (t->left);
tmp_res = g_strconcat (res, child, NULL);
g_free (child);
g_free (res);
res = tmp_res;
}
if (t->right) {
child = compute_vartree_void_use (t->right);
tmp_res = g_strconcat (res, child, NULL);
g_free (child);
g_free (res);
res = tmp_res;
}
return res;
}
/** Fill the tree of all vars in the local rule. */
void fill_vartree (VarTree **p_vartree, Tree *tree)
{
fill_vartree_ (p_vartree, tree, *p_vartree);
}
static void fill_vartree_ (VarTree **p_vartree, Tree *tree,
VarTree *vartree_root)
{
VarTree *vartree = *p_vartree;
if (!vartree && (tree->varname || tree->left || tree->right))
{
*p_vartree = (vartree = g_new0 (VarTree, 1));
vartree->left = NULL;
vartree->right = NULL;
vartree->varnames = NULL;
}
if (tree->varname) {
if (vartree->varnames &&
g_list_find_custom (vartree->varnames, tree->varname,
(GCompareFunc) &strcmp))
g_free (tree->varname);
else {
if (vartree_root)
check_varname (tree->varname, vartree_root);
else
vartree_root = vartree;
vartree->varnames = g_list_prepend (vartree->varnames,
tree->varname);
}
tree->varname = NULL;
}
if (tree->left)
fill_vartree_ (&(vartree->left), tree->left,
vartree_root);
if (tree->right)
fill_vartree_ (&(vartree->right), tree->right,
vartree_root);
}
static void check_varname (char *varname, VarTree *t)
{
GList *varnames = t->varnames;
if (varnames)
for (; varnames; varnames = varnames->next)
if (!strcmp (varname, (char *) varnames->data))
yyerror ("variable name `%s' redefined incorrectly", varname);
if (t->left)
check_varname (varname, t->left);
if (t->right)
check_varname (varname, t->right);
}
/**
** named_subtree.h: this file is part of MonoBURG.
**
** MonoBURG, an iburg like code generator generator.
**
** Copyright (C) 2001, 2002, 2004, 2005 Ximian, Inc.
**
** This program 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.
**
** The complete GNU General Public Licence Notice can be found as the
** `NOTICE' file in the root directory.
**
** \author Dietmar Maurer (dietmar@ximian.com)
** \author Cadilhac Michael (cadilhac@lrde.org)
** \brief Declaration of named subtree related functions.
*/
#ifndef __MONO_NAMED_SUBTREE_H__
# define __MONO_NAMED_SUBTREE_H__
# include "rule.h"
char *compute_vartree_decs (VarTree *t);
char *compute_vartree_void_use (VarTree *t);
void fill_vartree (VarTree **p_vartree, Tree *tree);
#endif /* __MONO_NAMED_SUBTREE_H__ */
......@@ -19,14 +19,11 @@
** \brief Burg files' grammar description.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#include <stdarg.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include "monoburg.h"
#include "rule.h"
......@@ -79,7 +76,7 @@ decls : /* empty */
| rule_list optcost optcode optcfunc {
GList *tmp;
for (tmp = $1; tmp; tmp = tmp->next) {
rule_add (tmp->data, $3, $2, $4);
rule_add (tmp->data, &($3), $2, $4);
}
g_list_free ($1);
} decls
......@@ -195,7 +192,7 @@ fgets_inc(char *s, int size)
if (state != 1 && with_line)
output ("#line %d \"%s\"\n", 1, path);
new_include->yylineno = 0;
new_include->filename = strdup (path);
new_include->filename = g_strdup (path);
inputs = g_list_append (inputs, new_include);
return fgets_inc(s, size);
}
......@@ -220,7 +217,7 @@ yyerror (char *fmt, ...)
}
void
reset_parser ()
reset_parser (void)
{
state = 0;
}
......@@ -263,7 +260,7 @@ push_if (char *input, gboolean flip)
}
static void
flip_if ()
flip_if (void)
{
if (!pp)
yyerror ("%%else without %%if");
......@@ -272,7 +269,7 @@ flip_if ()
}
static void
pop_if ()
pop_if (void)
{
struct pplist *prev_pp = pp;
......@@ -284,7 +281,7 @@ pop_if ()
}
static char
nextchar ()
nextchar (void)
{
int next_state ;
gboolean ll;
......@@ -445,12 +442,13 @@ yylex (void)
}
if (c == '{') {
unsigned i = 0, d = 1;
unsigned i = 3, d = 1;
static char buf [100000];
g_memmove (buf, "\t{\n", 4);
if (with_line)
i = sprintf (buf, "#line %d \"%s\"\n", LASTINPUT->yylineno,
LASTINPUT->filename);
i += sprintf (buf + 3, "#line %d \"%s\"\n", LASTINPUT->yylineno,
LASTINPUT->filename);
while (d && (c = nextchar ())) {
buf [i++] = c;
assert (i < sizeof (buf));
......@@ -462,7 +460,7 @@ yylex (void)
break;
}
}
buf [--i] = '\0';
g_memmove (buf + --i, "\n\t}", 4);
yylval.text = g_strdup (buf);
return CODE;
......
......@@ -21,6 +21,7 @@
#include <string.h>
#include "monoburg.h"
#include "parser.h"
#include "named_subtree.h"
#include "rule.h"
GList *term_list = NULL;
......@@ -33,22 +34,41 @@ int default_cost = 0;
static NonTerm *nonterm (char *id);
Rule *make_rule (char *id, Tree *tree)
{
Rule *rule = g_new0 (Rule, 1);
rule->lhs = nonterm (id);
rule->tree = tree;
rule->vartree = NULL;
rule->code = NULL;
return rule;
}
void rule_add (Rule *rule, char *code, char *cost, char *cfunc)
void rule_add (Rule *rule, char **p_code, char *cost, char *cfunc)
{
rule_list = g_list_append (rule_list, rule);
rule->cfunc = cfunc;
rule->code = code;
if (rule->vartree) {
char *varstr;
varstr = compute_vartree_decs (rule->vartree);
if (*varstr) {
char *varstr_void_use = compute_vartree_void_use (rule->vartree);
rule->code = g_strconcat (varstr, varstr_void_use, *p_code, NULL);
g_free (*p_code);
g_free (varstr);
g_free (varstr_void_use);
*p_code = rule->code;
} else {
g_free (varstr);
rule->code = *p_code;
}
} else
rule->code = *p_code;
if (cfunc) {