a6fca7c36229ab7e1ccbe8722f59b373546164a0
[cascardo/grammar.git] / rdp.c
1 #include "rdp.h"
2 #include <stdlib.h>
3
4 rdp_t* rdp_new (nextcb cb, gpointer data)
5 {
6
7   rdp_t* parser;
8
9   parser = g_malloc (sizeof (rdp_t));
10   parser->cb = cb;
11   parser->data = data;
12
13   parser->rules = NULL;
14
15   parser->buffer = g_list_append (NULL, NULL);
16
17   return parser;
18
19 }
20
21 void rdp_delete (rdp_t* parser)
22 {
23
24   g_free (parser);
25
26 }
27
28 gpointer leaf_new (gpointer data)
29 {
30   return g_node_new (data);
31 }
32
33 gpointer tree_new (rule_t* rule)
34 {
35   return g_node_new (rule);
36 }
37
38 gpointer tree_add (gpointer tree, gpointer data)
39 {
40   return g_node_append (tree, data);
41 }
42
43 void tree_delete (gpointer tree)
44 {
45   g_node_destroy (tree);
46 }
47
48 symbol_t* buffer_next (rdp_t* parser, gpointer* attrib)
49 {
50
51   buffer_t* buffer;
52
53   if (parser->buffer->next == NULL)
54     {
55       buffer = g_malloc (sizeof (buffer_t));
56       buffer->symbol = g_malloc (sizeof (symbol_t));
57       buffer->symbol->terminal = TRUE;
58       buffer->symbol->value = parser->cb (parser->data, &(buffer->attrib));
59       g_list_append (parser->buffer, buffer);
60     }
61
62   parser->buffer = g_list_next (parser->buffer);
63   buffer = (buffer_t*) parser->buffer->data;
64
65   if (attrib)
66     *attrib = buffer->attrib;
67
68   return buffer->symbol;
69       
70 }
71
72 gboolean rdp_step (rdp_t* parser, symbol_t* symbol, gpointer* attrib)
73 {
74
75   GList* l;
76   GList* buffer;
77   gpointer attr;
78
79   buffer = parser->buffer;
80
81   if (symbol != NULL && symbol->terminal)
82     {
83       symbol_t* s;
84       s = buffer_next (parser, &attr);
85       if (!symbol_equal (symbol, s))
86         {
87           parser->buffer = buffer;
88           return FALSE;
89         }
90       *attrib = leaf_new (attr);
91       return TRUE;
92     }
93
94   for (l = g_list_first (parser->rules); l != NULL; l = g_list_next (l))
95     {
96
97       rule_t* rule;
98
99       rule = (rule_t*) l->data;
100
101       if (symbol == NULL || symbol_equal (symbol, rule->left))
102         {
103
104           GList* m;
105
106           *attrib = tree_new (rule);
107
108           for (m = g_list_first (rule->right); m != NULL; m = g_list_next (m))
109             {
110
111               symbol_t* s;
112
113               s = (symbol_t*) m->data;
114
115               if (!rdp_step (parser, s, &attr))
116                 {
117                   parser->buffer = buffer;
118                   break;
119                 }
120
121               tree_add (*attrib, attr);
122
123             }
124
125           if (m == NULL)
126             return TRUE;
127           else
128             tree_delete (*attrib);
129
130         }
131
132     }
133
134   return FALSE;
135
136 }
137
138 gpointer rdp_build (rdp_t* parser)
139 {
140
141   gpointer attrib;
142
143   if (rdp_step (parser, NULL, &attrib))
144     return attrib;
145
146   return NULL;
147
148 }