Little fix in bnf header
[cascardo/grammar.git] / rdp.c
1 #include <rdp.h>
2 #include <stdlib.h>
3
4 struct _buffer
5 {
6   symbol_t* symbol;
7   gpointer attrib;
8 };
9
10 gpointer leaf_new (gpointer data)
11 {
12   return g_node_new (data);
13 }
14
15 gpointer tree_new (rule_t* rule)
16 {
17   return g_node_new (rule);
18 }
19
20 gpointer tree_add (gpointer tree, gpointer data)
21 {
22   return g_node_append (tree, data);
23 }
24
25 void tree_delete (gpointer tree)
26 {
27   g_node_destroy (tree);
28 }
29
30 static void rdp_init (GTypeInstance* instance, gpointer g_class)
31 {
32   Rdp* self = RDP(instance);
33   self->cb = NULL;
34   self->data = NULL;
35   self->buffer = NULL;
36   self->start = NULL;
37 }
38
39 static void rdp_finalize (GObject* obj)
40 {
41   RdpClass* klass;
42   GObject* parent_class;
43   Rdp* self;
44   self = RDP(obj);
45   g_free (self->start);
46   klass = RDP_GET_CLASS(obj);
47   parent_class = g_type_class_peek_parent (klass);
48   G_OBJECT_CLASS(parent_class)->finalize (obj);
49 }
50
51 static void rdp_class_init (RdpClass* klass)
52 {
53   GObjectClass* gobj_class = G_OBJECT_CLASS(klass);
54   gobj_class->finalize = rdp_finalize;
55 }
56
57 GType rdp_get_type ()
58 {
59   static GType type = 0;
60   if (type == 0)
61     {
62       static const GTypeInfo info =
63         {
64           sizeof (RdpClass),
65           NULL,
66           NULL,
67           (GClassInitFunc)rdp_class_init,
68           NULL,
69           NULL,
70           sizeof (Rdp),
71           0,
72           rdp_init
73         };
74       type = g_type_register_static (GRAMMAR_TYPE, "RdpType", &info, 0);
75     }
76   return type;
77 }
78
79 Rdp* rdp_new (nextcb cb, gpointer data, gint value)
80 {
81
82   Rdp* parser;
83
84   parser = g_object_new (RDP_TYPE, NULL);
85
86   parser->cb = cb;
87   parser->data = data;
88   parser->start = symbol_new (FALSE, value);
89
90   parser->buffer = g_list_append (NULL, NULL);
91
92   return parser;
93
94 }
95
96 void rdp_delete (Rdp* parser)
97 {
98
99   g_object_unref (parser);
100
101 }
102
103 symbol_t* buffer_next (Rdp* parser, gpointer* attrib)
104 {
105
106   buffer_t* buffer;
107
108   if (parser->buffer->next == NULL)
109     {
110       buffer = g_malloc (sizeof (buffer_t));
111       buffer->symbol = g_malloc (sizeof (symbol_t));
112       buffer->symbol->terminal = TRUE;
113       buffer->symbol->value = parser->cb (parser->data, &(buffer->attrib));
114       g_list_append (parser->buffer, buffer);
115     }
116
117   parser->buffer = g_list_next (parser->buffer);
118   buffer = (buffer_t*) parser->buffer->data;
119
120   if (attrib)
121     *attrib = buffer->attrib;
122
123   return buffer->symbol;
124       
125 }
126
127 gboolean rdp_step (Rdp* parser, symbol_t* symbol, gpointer* attrib)
128 {
129
130   GList* l;
131   GList* buffer;
132   gpointer attr;
133
134   buffer = parser->buffer;
135
136   if (symbol != NULL && symbol->terminal)
137     {
138       symbol_t* s;
139       s = buffer_next (parser, &attr);
140       if (!symbol_equal (symbol, s))
141         {
142           parser->buffer = buffer;
143           return FALSE;
144         }
145       *attrib = leaf_new (attr);
146       return TRUE;
147     }
148
149   for (l = grammar_get_rules (parser, symbol); l != NULL; l = g_list_next (l))
150     {
151
152       rule_t* rule;
153       GList* m;
154
155       rule = (rule_t*) l->data;
156
157
158       *attrib = tree_new (symbol_copy (symbol));
159
160       m = grammar_get_rule (rule);
161
162       /*
163       if (m == NULL)
164         {
165           tree_add (*attrib, leaf_new (g_string_new ("")));
166           return TRUE;
167         }
168       */
169
170       while (m != NULL)
171         {
172
173           symbol_t* s;
174
175           s = (symbol_t*) m->data;
176
177           if (!rdp_step (parser, s, &attr))
178             {
179               parser->buffer = buffer;
180               break;
181             }
182
183           tree_add (*attrib, attr);
184
185           m = g_list_next (m);
186
187         }
188
189       if (m == NULL)
190         return TRUE;
191       else
192         tree_delete (*attrib);
193
194     }
195
196   return FALSE;
197
198 }
199
200 gpointer rdp_build (Rdp* parser)
201 {
202
203   gpointer attrib;
204
205   if (rdp_step (parser, parser->start, &attrib))
206     return attrib;
207
208   return NULL;
209
210 }