Added GPLv2+ as license for libgrammatic
[cascardo/grammar.git] / rdp.c
1 /*
2  *  Copyright (C) 2005  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19
20
21 #include <rdp.h>
22 #include <stdlib.h>
23
24 struct _buffer
25 {
26   symbol_t* symbol;
27   gpointer attrib;
28 };
29
30 gpointer leaf_new (gpointer data)
31 {
32   return g_node_new (data);
33 }
34
35 gpointer tree_new (rule_t* rule)
36 {
37   return g_node_new (rule);
38 }
39
40 gpointer tree_add (gpointer tree, gpointer data)
41 {
42   return g_node_append (tree, data);
43 }
44
45 void tree_delete (gpointer tree)
46 {
47   g_node_destroy (tree);
48 }
49
50 rdp_t* rdp_new (nextcb cb, gpointer data, gint value, grammar_t* grammar)
51 {
52
53   rdp_t* parser;
54
55   parser = g_malloc (sizeof (rdp_t));
56
57   parser->cb = cb;
58   parser->data = data;
59   parser->start = symbol_new (FALSE, value);
60   parser->grammar = grammar;
61
62   parser->buffer = g_list_append (NULL, NULL);
63
64   return parser;
65
66 }
67
68 void rdp_delete (rdp_t* rdp)
69 {
70   g_free (rdp->start);
71 }
72
73 symbol_t* buffer_next (rdp_t* parser, gpointer* attrib)
74 {
75
76   buffer_t* buffer;
77
78   if (parser->buffer->next == NULL)
79     {
80       buffer = g_malloc (sizeof (buffer_t));
81       buffer->symbol = g_malloc (sizeof (symbol_t));
82       buffer->symbol->terminal = TRUE;
83       buffer->symbol->value = parser->cb (parser->data, &(buffer->attrib));
84       g_list_append (parser->buffer, buffer);
85     }
86
87   parser->buffer = g_list_next (parser->buffer);
88   buffer = (buffer_t*) parser->buffer->data;
89
90   if (attrib)
91     *attrib = buffer->attrib;
92
93   return buffer->symbol;
94       
95 }
96
97 gboolean rdp_step (rdp_t* parser, symbol_t* symbol, gpointer* attrib)
98 {
99
100   GList* l;
101   GList* buffer;
102   gpointer attr;
103
104   buffer = parser->buffer;
105
106   if (symbol != NULL && symbol->terminal)
107     {
108       symbol_t* s;
109       s = buffer_next (parser, &attr);
110       if (!symbol_equal (symbol, s))
111         {
112           parser->buffer = buffer;
113           return FALSE;
114         }
115       *attrib = leaf_new (attr);
116       return TRUE;
117     }
118
119   l = grammar_get_rules (parser->grammar, symbol);
120   for (; l != NULL; l = g_list_next (l))
121     {
122
123       rule_t* rule;
124       GList* m;
125
126       rule = (rule_t*) l->data;
127
128
129       *attrib = tree_new (symbol_copy (symbol));
130
131       m = grammar_get_rule (rule);
132
133       /*
134       if (m == NULL)
135         {
136           tree_add (*attrib, leaf_new (g_string_new ("")));
137           return TRUE;
138         }
139       */
140
141       while (m != NULL)
142         {
143
144           symbol_t* s;
145
146           s = (symbol_t*) m->data;
147
148           if (!rdp_step (parser, s, &attr))
149             {
150               parser->buffer = buffer;
151               break;
152             }
153
154           tree_add (*attrib, attr);
155
156           m = g_list_next (m);
157
158         }
159
160       if (m == NULL)
161         return TRUE;
162       else
163         tree_delete (*attrib);
164
165     }
166
167   return FALSE;
168
169 }
170
171 gpointer rdp_build (rdp_t* parser)
172 {
173
174   gpointer attrib;
175
176   if (rdp_step (parser, parser->start, &attrib))
177     return attrib;
178
179   return NULL;
180
181 }