Commit ea300793 authored by Michaël Cadilhac's avatar Michaël Cadilhac
Browse files

2005-07-13 Michael Cadilhac <michael.cadilhac@lrde.epita.fr>

	* sample.brg: Move to...
	* tests/sample.brg: ...Here.

	* parser.y: Move to...
	* src/parser.y: ...Here.
	
	* monoburg.1: Move to...
	* src/monoburg.1: ...Here.
	
	* monoburg.c,
	* monoburg.h: Split in...
	* src/emit.c,
	* src/parser.h,
	* src/emit.h,
	* src/rule.c,
	* src/emit_kids.c,
	* src/rule.h,
	* src/check.c,
	* src/emit_files.c,
	* src/emit_pretty_print.c,
	* src/check.h,
	* src/main.c,
	* src/emit_cost.c,
	* src/emit_functions.c,
	* src/monoburg.h: ...These files.
	
	* src/Makefile.am,
	* tests/Makefile.am: New. Create accordingly.
	
	* NOTICE,
	* AUTHORS,
	* NEWS: New. Add some package related files.
	
	* configure.ac,
	* Makefile.am: Update accordingly.
parent 95d27bca
* Dietmar Maurer (dietmar@ximian.com).
* Cadilhac Michael (cadilhac@lrde.org).
2005-07-13 Michael Cadilhac <michael.cadilhac@lrde.epita.fr>
* sample.brg: Move to...
* tests/sample.brg: ...Here.
* parser.y: Move to...
* src/parser.y: ...Here.
* monoburg.1: Move to...
* src/monoburg.1: ...Here.
* monoburg.c,
* monoburg.h: Split in...
* src/emit.c,
* src/parser.h,
* src/emit.h,
* src/rule.c,
* src/emit_kids.c,
* src/rule.h,
* src/check.c,
* src/emit_files.c,
* src/emit_pretty_print.c,
* src/check.h,
* src/main.c,
* src/emit_cost.c,
* src/emit_functions.c,
* src/monoburg.h: ...These files.
* src/Makefile.am,
* tests/Makefile.am: New. Create accordingly.
* NOTICE,
* AUTHORS,
* NEWS: New. Add some package related files.
* configure.ac,
* Makefile.am: Update accordingly.
2005-06-27 Michael Cadilhac <michael.cadilhac@lrde.epita.fr>
* configure.ac: Bump to 1.0.2.
......
## Makefile.am -- Process this file with automake to produce Makefile.in
##
SUBDIRS = config
## Include path
INCLUDES = $(GLIB_CFLAGS) -I$(srcdir)
## MonoBURG binary
bin_PROGRAMS = monoburg
monoburg_SOURCES = \
parser.y \
monoburg.c monoburg.h
monoburg_LDADD = \
$(GLIB_LIBS)
## MonoBURG manual
man_MANS = monoburg.1
EXTRA_DIST = ChangeLog $(man_MANS)
## Check/Sample
check_PROGRAMS = sample
TESTS = sample
sample.c: monoburg$(EXEEXT) $(srcdir)/sample.brg
./monoburg$(EXEEXT) $(srcdir)/sample.brg > sample.c
sample_SOURCES = sample.brg
sample_LDADD = sample.o $(GLIB_LIBS)
CLEANFILES = sample.c sample.o parser.c
SUBDIRS = src config tests
EXTRA_DIST = bootstrap ChangeLog NOTICE
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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
The Vaucanson Group consists of people listed in the `AUTHORS' file.
Contact: mono@novell.com.
......@@ -18,7 +18,7 @@ AC_CONFIG_AUX_DIR([config])
AC_CONFIG_FILES([config/Makefile])
# Initiate automake.
AM_INIT_AUTOMAKE([foreign 1.7.5 dist-bzip2])
AM_INIT_AUTOMAKE([1.7.5 dist-bzip2])
## -------------------------------------
## Development tools
......@@ -41,6 +41,8 @@ AM_PATH_GLIB_2_0
# Ask for Makefile creation
AC_CONFIG_FILES([
Makefile
src/Makefile
tests/Makefile
])
# Instantiate the output files
......
This diff is collapsed.
INCLUDES = $(GLIB_CFLAGS) -I$(srcdir)
bin_PROGRAMS = monoburg
monoburg_SOURCES = \
parser.y \
check.c check.h \
emit.c emit.h \
emit_cost.c emit_files.c \
emit_functions.c emit_kids.c \
emit_pretty_print.c main.c \
monoburg.h parser.h \
rule.c rule.h
monoburg_LDADD = \
$(GLIB_LIBS)
man_MANS = monoburg.1
EXTRA_DIST = $(man_MANS)
/**
** check.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 Check parse consistency.
*/
#include "monoburg.h"
#include "rule.h"
static void check_reach (NonTerm *n);
static void mark_reached (Tree *tree);
/** Check the consistency of the parse, by checking reachability of
each non terminal symbols and arity of terminals. */
void check_result ()
{
GList *l;
for (l = term_list; l; l = l->next) {
Term *term = (Term *)l->data;
if (term->arity == -1)
g_warning ("unused terminal \"%s\"",term->name);
}
check_reach (((NonTerm *)nonterm_list->data));
for (l = nonterm_list; l; l = l->next) {
NonTerm *n = (NonTerm *)l->data;
if (!n->reached)
g_warning ("unreachable nonterm \"%s\"", n->name);
}
}
static void check_reach (NonTerm *n)
{
GList *l;
n->reached = 1;
for (l = n->rules; l; l = l->next) {
Rule *rule = (Rule *)l->data;
mark_reached (rule->tree);
}
}
static void mark_reached (Tree *tree)
{
if (tree->nonterm && !tree->nonterm->reached)
check_reach (tree->nonterm);
if (tree->left)
mark_reached (tree->left);
if (tree->right)
mark_reached (tree->right);
}
/**
** check.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 Check parse consistency (prototypes).
*/
#ifndef __MONO_CHECK_H__
# define __MONO_CHECK_H__
void check_result ();
#endif /* __MONO_CHECK_H__ */
/**
** emit.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 General emit functions that produce files' skeletons.
*/
#include <string.h>
#include "monoburg.h"
#include "emit.h"
FILE *outputfd;
static int term_compare_func (Term *t1, Term *t2);
static int next_term_num ();
static int term_compare_func (Term *t1, Term *t2);
static void emit_tree_match (char *st, Tree *t);
static void emit_rule_match (Rule *rule);
static char *compute_nonterms (Tree *tree);
/** Output some text /a la/ printf in the currently opened file. */
void output (char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf (outputfd, fmt, ap);
va_end (ap);
}
/** Emit includes of external header files. */
void emit_includes ()
{
if (with_glib) {
output ("#include <glib.h>\n");
output ("\n");
}
else {
output ("#include <stdio.h>\n");
output ("#include <stdlib.h>\n");
output ("#include <stdarg.h>\n");
output ("#include <assert.h>\n");
}
}
/** Emit header defines, replace glib definitions if !with_glib. */
void emit_header ()
{
if (!with_glib) {
output ("#ifndef guint8\n"
"# define guint8 unsigned char\n"
"#endif /* !guint8 */\n"
"#ifndef guint16\n"
"# define guint16 unsigned short\n"
"#endif /* !guint16 */\n"
"#ifndef gpointer\n"
"# define gpointer void*\n"
"#endif /* !gpointer */\n"
"\n");
output ("#ifndef g_new\n"
"static void *\n"
"mono_burg_xmalloc_ (size_t size)\n"
"{\n"
" void *p;\n"
"\n"
" p = malloc (size);\n"
" if (!p) {\n"
" fprintf (stderr, \"Not enough memory\\n\");\n"
" exit (1);\n"
" }\n"
" return p;\n"
"}\n"
"# define g_new(struct_type, n_structs) ((struct_type *) mono_burg_xmalloc_ (sizeof(struct_type) * n_structs))\n"
"#endif /* !g_new */\n"
"\n");
output ("#ifndef g_error\n"
"static int\n"
"mono_burg_error_ (const char *format, ...)\n"
"{\n"
" int n = 0;\n"
" va_list ap;\n"
"\n"
" n = fprintf (stderr, \"Error: \");\n"
" va_start (ap, format);\n"
" n += vfprintf (stderr, format, ap);\n"
" va_end (ap);\n"
"\n"
" return n;\n"
"}\n"
"# define g_error mono_burg_error_\n"
"#endif /* !g_error */\n");
output ("#ifndef g_assert\n"
"# define g_assert assert\n"
"#endif /* !g_assert */\n"
"\n");
output ("#ifndef g_return_val_if_fail\n"
"# ifdef NDEBUG\n"
"# define g_return_val_if_fail(expr, val)\n"
"# else /* !NDEBUG */\n"
"# define g_return_val_if_fail(expr, val) do { if (! (expr)) return val; } while (0)\n"
"# endif /* NDEBUG */\n"
"#endif /* !g_return_val_if_fail */\n"
"#ifndef g_assert_not_reached\n"
"# define g_assert_not_reached(X) assert (!\"Should not be there\")\n"
"#endif /* !g_assert_not_reached */\n"
"\n");
}
output ("#ifndef MBTREE_TYPE\n#error MBTREE_TYPE undefined\n#endif\n"
"#ifndef MBTREE_OP\n#define MBTREE_OP(t) ((t)->op)\n#endif\n"
"#ifndef MBTREE_LEFT\n#define MBTREE_LEFT(t) ((t)->left)\n#endif\n"
"#ifndef MBTREE_RIGHT\n#define MBTREE_RIGHT(t) ((t)->right)\n#endif\n"
"#ifndef MBTREE_STATE\n#define MBTREE_STATE(t) ((t)->state)\n#endif\n"
"#ifndef MBCGEN_TYPE\n#define MBCGEN_TYPE int\n#endif\n"
"#ifndef MBALLOC_STATE\n#define MBALLOC_STATE g_new (MBState, 1)\n#endif\n"
"#ifndef MBCOST_DATA\n#define MBCOST_DATA gpointer\n#endif\n"
"\n"
"#define MBMAXCOST 32768\n"
"\n");
output ("#define MBCOND(x) if (!(x)) return MBMAXCOST;\n"
"\n");
}
/** Emit the enum for terminal members. */
void emit_term ()
{
GList *l;
for (l = term_list; l; l = l->next) {
Term *t = (Term *)l->data;
if (t->number == -1)
t->number = next_term_num ();
}
term_list = g_list_sort (term_list, (GCompareFunc)term_compare_func);
output ("typedef enum {\n");
for (l = term_list; l; l = l->next) {
Term *t = (Term *)l->data;
if (t->number == -1)
t->number = next_term_num ();
if (predefined_terms)
output ("\tMB_TERM_%s = %s%s\n", t->name, t->name,
l->next ? "," : "");
else
output ("\tMB_TERM_%s = %d%s\n", t->name, t->number,
l->next ? "," : "");
}
output ("} MBTerms;\n\n");
}
/** Get the next available term id. */
static int next_term_num ()
{
GList *l = term_list;
int i = 1;
while (l) {
Term *t = (Term *)l->data;
if (t->number == i) {
l = term_list;
i++;
} else
l = l->next;
}
return i;
}
/** Function to compare terms. */
static int term_compare_func (Term *t1, Term *t2)
{
return t1->number - t2->number;
}
/** Emit the enum for non-terminal members. */
void emit_nonterm ()
{
GList *l;
output ("typedef enum {\n");
for (l = nonterm_list; l; l = l->next) {
NonTerm *n = (NonTerm *)l->data;
output ("\tMB_NTERM_%s = %d%s\n", n->name, n->number,
(l->next) ? "," : "");
}
output ("} MBNTerms;\n\n");
output ("#define MB_MAX_NTERMS\t%d\n", g_list_length (nonterm_list));
output ("\n");
}
/** Emit the MBState struct. */
void emit_state ()
{
GList *l;
int i, j;
output ("struct _MBState {\n");
output ("\tint\t\top;\n");
if (dag_mode) {
output ("\tMBTREE_TYPE\t *tree;\n");
output ("\tgint32 reg1, reg2;\n");
}
output ("\tstruct _MBState\t*left, *right;\n");
output ("\tguint16\t\tcost[%d];\n", g_list_length (nonterm_list) + 1);
for (l = nonterm_list; l; l = l->next) {
NonTerm *n = (NonTerm *)l->data;
g_assert (g_list_length (n->rules) < 256);
i = g_list_length (n->rules);
j = 1;
while (i >>= 1)
j++;
output ("\tunsigned int\t rule_%s:%d;\n", n->name, j);
}
output ("};\n\n");
output ("typedef struct _MBState MBState;\n");
}
/** Emit rule decoders. */
void emit_decoders ()
{
GList *l;
GList *rl;
for (l = nonterm_list; l; l = l->next) {
NonTerm *n = (NonTerm *)l->data;
output ("const int mono_burg_decode_%s[] = {\n", n->name);
output ("\t0,\n");
for (rl = n->rules; rl; rl = rl->next) {
Rule *rule = (Rule *)rl->data;
output ("\t%d,\n", g_list_index (rule_list, rule) + 1);
}
output ("};\n\n");
}
}
/** Emit the condition to match a tree. */
static void emit_tree_match (char *st, Tree *t)
{
char *tn;
int not_first = strcmp (st, "p->");
/* We can omit this check at the top level */
if (not_first) {
if (predefined_terms)
output ("\t\t\t%sop == %s /* %s */", st, t->op->name, t->op->name);
else
output ("\t\t\t%sop == %d /* %s */", st, t->op->number, t->op->name);
}
if (t->left && t->left->op) {
tn = g_strconcat (st, "left->", NULL);
if (not_first)
output (" &&\n");
not_first = 1;
emit_tree_match (tn, t->left);
g_free (tn);
}
if (t->right && t->right->op) {
tn = g_strconcat (st, "right->", NULL);
if (not_first)
output (" &&\n");
emit_tree_match (tn, t->right);
g_free (tn);
}
}
/** Emit the whole rule match using emit_tree_match. */
static void emit_rule_match (Rule *rule)
{
Tree *t = rule->tree;
if ((t->left && t->left->op) ||
(t->right && t->right->op)) {
output ("\t\tif (\n");
emit_tree_match ("p->", t);
output ("\n\t\t)\n");
}
}
/** Emit the tree matcher that put a tree together with its rule. */
void emit_label_func ()
{
GList *l;
int i;
if (dag_mode) {
output ("static void\n");
output ("mono_burg_label_priv (MBTREE_TYPE *tree, MBCOST_DATA *data, MBState *p) {\n");
} else {
output ("static MBState *\n");
output ("mono_burg_label_priv (MBTREE_TYPE *tree, MBCOST_DATA *data) {\n");
}
output ("\tint arity;\n");
output ("\tint c;\n");
if (!dag_mode)
output ("\tMBState *p;\n");
output ("\tMBState *left = NULL, *right = NULL;\n\n");
output ("\tswitch (mono_burg_arity [MBTREE_OP(tree)]) {\n");
output ("\tcase 0:\n");
output ("\t\tbreak;\n");
output ("\tcase 1:\n");
if (dag_mode) {
output ("\t\tleft = MBALLOC_STATE;\n");
output ("\t\tmono_burg_label_priv (MBTREE_LEFT(tree), data, left);\n");
} else {
output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree), data);\n");
output ("\t\tright = NULL;\n");
}
output ("\t\tbreak;\n");
output ("\tcase 2:\n");
if (dag_mode) {
output ("\t\tleft = MBALLOC_STATE;\n");
output ("\t\tmono_burg_label_priv (MBTREE_LEFT(tree), data, left);\n");
output ("\t\tright = MBALLOC_STATE;\n");
output ("\t\tmono_burg_label_priv (MBTREE_RIGHT(tree), data, right);\n");
} else {
output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree), data);\n");
output ("\t\tright = mono_burg_label_priv (MBTREE_RIGHT(tree), data);\n");
}
output ("\t}\n\n");
output ("\tarity = (left != NULL) + (right != NULL);\n");
output ("\tg_assert (arity == mono_burg_arity [MBTREE_OP(tree)]);\n\n");
if (!dag_mode)
output ("\tp = MBALLOC_STATE;\n");
output ("\tmemset (p, 0, sizeof (MBState));\n");
output ("\tp->op = MBTREE_OP(tree);\n");
output ("\tp->left = left;\n");
output ("\tp->right = right;\n");
if (dag_mode)
output ("\tp->tree = tree;\n");
for (l = nonterm_list, i = 0; l; l = l->next) {
output ("\tp->cost [%d] = 32767;\n", ++i);
}
output ("\n");
output ("\tswitch (MBTREE_OP(tree)) {\n");
for (l = term_list; l; l = l->next) {
Term *t = (Term *)l->data;
GList *rl;
if (predefined_terms)
output ("\tcase %s: /* %s */\n", t->name, t->name);
else
output ("\tcase %d: /* %s */\n", t->number, t->name);
for (rl = t->rules<