--- /dev/null
+#include <grammar.h>
+#include <rdp.h>
+#include <scanner.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static gint scanner_next (scanner_t* scanner, GString** val)
+{
+
+ int state;
+ int start;
+ int stop;
+ int i;
+ gchar* buffer;
+ GString* lexeme;
+
+ state = NONE;
+ start = 0;
+ stop = 0;
+ buffer = malloc (256);
+
+ for (i = 0; stop == 0; i++)
+ {
+
+ gchar c;
+
+ if (scanner->buffer->len == 0)
+ {
+ int r;
+ r = scanner->cb (scanner->data, buffer, 256);
+ if (r == 0)
+ g_string_append_c (scanner->buffer, 0);
+ else
+ g_string_append_len (scanner->buffer, buffer, r);
+ }
+
+ c = scanner->buffer->str[i];
+
+ switch (state)
+ {
+ case NONE:
+ if (g_ascii_isalpha (c))
+ {
+ start = i;
+ state = ID;
+ break;
+ }
+ else if (g_ascii_isspace (c))
+ {
+ if (c == '\n')
+ {
+ start = i;
+ state = EOL;
+ }
+ break;
+ }
+ else if (c == ':')
+ {
+ start = i;
+ state = EQUAL;
+ break;
+ }
+ else if (c == '"')
+ {
+ start = i;
+ state = STRING;
+ break;
+ }
+ else if (c == 0)
+ {
+ stop = i;
+ break;
+ }
+ case ID:
+ if (g_ascii_isalnum (c))
+ {
+ break;
+ }
+ else if (g_ascii_isspace (c) || c == 0)
+ {
+ stop = i;
+ break;
+ }
+ case EOL:
+ case EQUAL:
+ stop = i;
+ break;
+ case STRING:
+ if (c == '"')
+ stop = i+1;
+ break;
+ }
+
+ }
+
+ free (buffer);
+
+ g_string_erase (scanner->buffer, 0, start);
+ lexeme = g_string_new_len (scanner->buffer->str, stop - start);
+ g_string_erase (scanner->buffer, 0, stop - start);
+
+ if (val)
+ {
+ *val = lexeme;
+ }
+ else
+ {
+ g_string_free (lexeme, TRUE);
+ }
+
+ return state;
+
+}
+
+enum
+ {
+ BNF_GRAMMAR = 1,
+ BNF_RULES,
+ BNF_RULE,
+ BNF_LEFT,
+ BNF_RIGHT,
+ BNF_SYMBOL,
+ BNF_TERMINAL,
+ BNF_NONTERMINAL
+ };
+
+void grammar_tree (Grammar* grammar, GNode* tree)
+{
+
+ GNode* child_rules;
+ GNode* child_rule;
+ GNode* child_left;
+ GNode* child_right;
+ GNode* child_symbol;
+ GNode* child_nonterminal;
+ GNode* child_terminal;
+ GNode* child;
+ symbol_t* symbol;
+ rule_t* rule;
+ GString* sym;
+ GQuark value;
+
+ assert (G_NODE_IS_LEAF(tree) == FALSE);
+ symbol = tree->data;
+ assert (symbol->value == BNF_GRAMMAR);
+
+ child_rules = tree->children;
+
+ while (child_rules->children != NULL)
+ {
+
+ assert (G_NODE_IS_LEAF(child_rules) == FALSE);
+ symbol = child_rules->data;
+ assert (symbol->value == BNF_RULES);
+
+ child_rule = child_rules->children;
+ assert (G_NODE_IS_LEAF(child_rule) == FALSE);
+ symbol = child_rule->data;
+ assert (symbol->value == BNF_RULE);
+
+ child_left = child_rule->children;
+ assert (G_NODE_IS_LEAF (child_left) == FALSE);
+ symbol = child_left->data;
+ assert (symbol->value == BNF_LEFT);
+
+ child_nonterminal = child_left->children;
+ assert (G_NODE_IS_LEAF (child_nonterminal) == FALSE);
+ symbol = child_nonterminal->data;
+ assert (symbol->value == BNF_NONTERMINAL);
+ assert (child_nonterminal->next == NULL);
+
+ child = child_nonterminal->children;
+ assert (G_NODE_IS_LEAF (child));
+ sym = child->data;
+
+ /* Create new rule */
+ value = g_quark_from_string (sym->str);
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, value));
+
+ child_right = child_left->next->next;
+ while (child_right->children != NULL)
+ {
+
+ assert (G_NODE_IS_LEAF(child_right) == FALSE);
+ symbol = child_right->data;
+ assert (symbol->value == BNF_RIGHT);
+
+ child_symbol = child_right->children;
+ assert (G_NODE_IS_LEAF(child_symbol) == FALSE);
+ symbol = child_symbol->data;
+ assert (symbol->value == BNF_SYMBOL);
+
+ child = child_symbol->children;
+ symbol = child->data;
+ if (symbol->value == BNF_NONTERMINAL)
+ {
+ child_nonterminal = child;
+ assert (G_NODE_IS_LEAF (child_nonterminal) == FALSE);
+ assert (child_nonterminal->next == NULL);
+ child = child_nonterminal->children;
+ assert (G_NODE_IS_LEAF (child));
+ sym = child->data;
+ /* Append nonterminal to rule */
+ value = g_quark_from_string (sym->str);
+ rule_append (rule, symbol_new (FALSE, value));
+ }
+ else if (symbol->value == BNF_TERMINAL)
+ {
+ child_terminal = child;
+ assert (G_NODE_IS_LEAF (child_terminal) == FALSE);
+ assert (child_terminal->next == NULL);
+ child = child_terminal->children;
+ assert (G_NODE_IS_LEAF (child));
+ sym = child->data;
+ /* Append terminal to rule */
+ value = g_quark_from_string (sym->str);
+ rule_append (rule, symbol_new (TRUE, value));
+ }
+ else
+ {
+ assert (TRUE);
+ }
+
+ child_right = child_symbol->next;
+
+ }
+
+ child_rules = child_rule->next;
+
+ }
+
+}
+
+Grammar* grammar_load (char* filename)
+{
+
+ Grammar* grammar;
+ rule_t* rule;
+
+ scanner_t* scanner;
+ Rdp* parser;
+ GNode* tree;
+
+ int fd;
+
+ fd = open (filename, O_RDONLY);
+
+ scanner = scanner_new (read, fd);
+
+ parser = rdp_new (scanner_next, scanner, BNF_GRAMMAR);
+ grammar = (Grammar*) parser;
+
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_GRAMMAR));
+ rule_append (rule, symbol_new (FALSE, BNF_RULES));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RULES));
+ rule_append (rule, symbol_new (FALSE, BNF_RULE));
+ rule_append (rule, symbol_new (FALSE, BNF_RULES));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RULES));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RULE));
+ rule_append (rule, symbol_new (FALSE, BNF_LEFT));
+ rule_append (rule, symbol_new (TRUE, EQUAL));
+ rule_append (rule, symbol_new (FALSE, BNF_RIGHT));
+ rule_append (rule, symbol_new (TRUE, EOL));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_LEFT));
+ rule_append (rule, symbol_new (FALSE, BNF_NONTERMINAL));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RIGHT));
+ rule_append (rule, symbol_new (FALSE, BNF_SYMBOL));
+ rule_append (rule, symbol_new (FALSE, BNF_RIGHT));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RIGHT));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_SYMBOL));
+ rule_append (rule, symbol_new (FALSE, BNF_TERMINAL));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_SYMBOL));
+ rule_append (rule, symbol_new (FALSE, BNF_NONTERMINAL));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_TERMINAL));
+ rule_append (rule, symbol_new (TRUE, STRING));
+ rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_NONTERMINAL));
+ rule_append (rule, symbol_new (TRUE, ID));
+
+ tree = rdp_build (parser);
+
+ close (fd);
+ scanner_delete (scanner);
+
+ if (tree == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ Grammar* gr;
+ gr = g_object_new (GRAMMAR_TYPE, NULL);
+ grammar_tree (gr, tree);
+ return gr;
+ }
+
+}