struct cParseNode* _get_parse_tree(int start, struct Grammar* grammar, struct TokenStream* tokens, struct Error* error) { struct cParseNode* parent = parse_rule(start, grammar, tokens, error); if (parent == NULL) { return NULL; } struct cParseNode* current = parent->child; struct cParseNode* tmp; int m, ignore; int rule = start; LOG("ignore any trailing ignores\n"); while (tokens->at < tokens->num) { ignore = 0; for (m=0;m<grammar->ignore.num;m++) { if (tokens->tokens[tokens->at].which == grammar->ignore.tokens[m]) { ignore = 1; break; } } if (ignore == 0) { break; } LOG("ignoring white\n"); tmp = _new_parsenode(rule); tmp->token = &tokens->tokens[tokens->at]; tmp->type = NTOKEN; current = append_nodes(current, tmp); LOG("inc token %d %d\n", tokens->at, tokens->at+1); tokens->at += 1; } parent->child = current; return parent; }
static DBusHandlerResult handle_get_nodes(DBusConnection *conn, DBusMessage *message, void *arg) { DBusMessage *reply; DBusMessageIter array; dbus_uint32_t serial = 0; reply = dbus_message_new_method_return(message); dbus_message_iter_init_append(reply, &array); if (!append_nodes(CRAS_STREAM_OUTPUT, &array)) return DBUS_HANDLER_RESULT_NEED_MEMORY; if (!append_nodes(CRAS_STREAM_INPUT, &array)) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_connection_send(conn, reply, &serial); dbus_message_unref(reply); return DBUS_HANDLER_RESULT_HANDLED; }
struct cParseNode* check_special(unsigned int rule, struct RuleSpecial special, struct cParseNode* current, struct Grammar* grammar, struct TokenStream* tokens, struct Error* error) { struct cParseNode* tmp; int at, i; LOG("special\n"); INDENT(); if (special.type == STAR) { LOG("star!\n"); while (tokens->at < tokens->num) { at = tokens->at; tmp = parse_children(rule, special.option, grammar, tokens, error); if (tmp == NULL) { tokens->at = at; break; } current = append_nodes(current, tmp); if (at == tokens->at) { break; } } LOG("awesome star\n"); DEDENT(); return current; } else if (special.type == PLUS) { LOG("plus!\n"); at = tokens->at; tmp = parse_children(rule, special.option, grammar, tokens, error); if (tmp == NULL) { tokens->at = at; LOG("failed plus\n"); DEDENT(); return NULL; } current = append_nodes(current, tmp); if (at == tokens->at) { return current; } while (tokens->at < tokens->num) { at = tokens->at; tmp = parse_children(rule, special.option, grammar, tokens, error); if (tmp == NULL) { tokens->at = at; break; } current = append_nodes(current, tmp); if (at == tokens->at) { break; } } LOG("good plus\n"); DEDENT(); return current; } else if (special.type == OR) { LOG("or!\n"); at = tokens->at; for (i=0;i<special.option->num;i++) { // each of the child items with be of the special STRAIGHT option // type -> allowing the OR special to have a list of lists tmp = parse_children(rule, special.option->items[i].value.special.option, grammar, tokens, error); if (tmp != NULL) { LOG("got or...\n"); current = append_nodes(current, tmp); DEDENT(); return current; } } LOG("fail or\n"); DEDENT(); return NULL; } else if (special.type == QUESTION) { LOG("?maybe\n"); at = tokens->at; tmp = parse_children(rule, special.option, grammar, tokens, error); LOG("done maybe children\n"); if (tmp == NULL) { LOG("not taking it\n"); tokens->at = at; DEDENT(); return current; } current = append_nodes(current, tmp); LOG("got maybe\n"); DEDENT(); return current; } else if (special.type == NOIGNORE) { LOG("no ignore (initial %d)\n", grammar->rules.rules[rule].dont_ignore); int before_ignore = grammar->rules.rules[rule].dont_ignore; at = tokens->at; grammar->rules.rules[rule].dont_ignore = 1; tmp = parse_children(rule, special.option, grammar, tokens, error); grammar->rules.rules[rule].dont_ignore = before_ignore; if (tmp == NULL) { tokens->at = at; LOG("failed ignore\n"); DEDENT(); return NULL; } current = append_nodes(current, tmp); LOG("ignore success! back to %d %d", grammar->rules.rules[rule].dont_ignore, before_ignore); DEDENT(); return current; } else if (special.type == NOT) { LOG("NOT\n"); at = tokens->at; tmp = parse_children(rule, special.option, grammar, tokens, error); if (tmp == NULL) { if (tokens->at < tokens->num) { tmp = _new_parsenode(rule); tmp->token = &tokens->tokens[tokens->at]; tmp->type = NTOKEN; tokens->at += 1; current = append_nodes(current, tmp); LOG("awesome. eating token\n"); } else { LOG("not enough tokens to eat\n"); at = tokens->at; return NULL; } DEDENT(); return current; } LOG("nope, it passed\n"); tokens->at = at; DEDENT(); return NULL; } else { LOG("unknown special type: %s\n", special.type); DEDENT(); return NULL; } LOG("umm shouldnt happen"); DEDENT(); return NULL; }
// clean struct cParseNode* parse_children(unsigned int rule, struct RuleOption* option, struct Grammar* grammar, struct TokenStream* tokens, struct Error* error) { LOG("parsing children of %d (token at %d)\n", rule, tokens->at); struct cParseNode* current = UNINITIALIZED; unsigned int i = 0, m = 0; unsigned int at = 0; struct cParseNode* tmp = NULL; struct RuleItem* item = NULL; int ignore; INDENT(); for (i=0;i<option->num;i++) { item = &option->items[i]; if (!grammar->rules.rules[rule].dont_ignore) { while (tokens->at < tokens->num) { ignore = 0; for (m=0;m<grammar->ignore.num;m++) { if (tokens->tokens[tokens->at].which == grammar->ignore.tokens[m]) { ignore = 1; break; } } if (ignore == 0) { break; } LOG("ignoring white\n"); tmp = _new_parsenode(rule); tmp->token = &tokens->tokens[tokens->at]; tmp->type = NTOKEN; current = append_nodes(current, tmp); LOG("inc token %d %d\n", tokens->at, tokens->at+1); tokens->at += 1; } } if (tokens->at < tokens->num) { LOG("At token %d '%s'\n", tokens->at, tokens->tokens[tokens->at].value); } if (item->type == RULE) { LOG(">RULE\n"); /** if (0 && tokens->at >= tokens->num) { // disabling error->at = tokens->at; error->reason = 1; error->token = NULL; error->text = "ran out"; // error[1] = ['ran out', rule, i, item->value.which]; // log('not enough tokens') DEDENT(); return NULL; } **/ at = tokens->at; tmp = parse_rule(item->value.which, grammar, tokens, error); if (tmp == NULL) { tokens->at = at; if (tokens->at >= error->at && error->reason!=1 && error->reason!=4) { error->at = tokens->at; error->reason = 2; error->token = &tokens->tokens[tokens->at]; error->text = "rule failed"; error->wanted = item->value.which; } DEDENT(); return NULL; } current = append_nodes(current, tmp); continue; } else if (item->type == TOKEN) { LOG(">TOKEN\n"); if (tokens->at >= tokens->num) { if (item->value.which == tokens->eof) { LOG("EOF -- passing\n"); tmp = _new_parsenode(rule); tmp->token = (struct Token*)malloc(sizeof(struct Token)); tmp->token->value = NULL; tmp->token->which = tokens->eof; tmp->token->lineno = -1; tmp->token->charno = -1; tmp->type = NTOKEN; current = append_nodes(current, tmp); continue; } LOG("no more tokens\n"); error->at = tokens->at; error->reason = 1; error->token = NULL; error->text = "ran out"; error->wanted = item->value.which; DEDENT(); return NULL; } if (tokens->tokens[tokens->at].which == item->value.which) { LOG("got token! %d\n", item->value.which); tmp = _new_parsenode(rule); tmp->token = &tokens->tokens[tokens->at]; tmp->type = NTOKEN; current = append_nodes(current, tmp); LOG("inc token %d %d\n", tokens->at, tokens->at+1); tokens->at += 1; continue; } else { if (tokens->at > error->at) { error->at = tokens->at; error->reason = 3; error->token = &tokens->tokens[tokens->at]; error->text = "token failed"; error->wanted = option->items[i].value.which; } LOG("token failed (wanted %d, got %d)\n", item->value.which, tokens->tokens[tokens->at].which); DEDENT(); return NULL; } } else if (item->type == LITERAL) { LOG(">LITERAL\n"); if (tokens->at >= tokens->num) { error->at = tokens->at; error->reason = 4; error->token = NULL; error->text = item->value.text; DEDENT(); return NULL; } if (strcmp(item->value.text, tokens->tokens[tokens->at].value) == 0) { LOG("got literal!\n"); tmp = _new_parsenode(rule); tmp->token = &tokens->tokens[tokens->at]; tmp->type = NTOKEN; current = append_nodes(current, tmp); LOG("inc token %d %d\n", tokens->at, tokens->at+1); tokens->at += 1; continue; } else { if (tokens->at > error->at) { error->at = tokens->at; error->reason = 5; error->token = &tokens->tokens[tokens->at]; error->text = item->value.text; } LOG("failed....literally: %s\n", item->value.text); DEDENT(); return NULL; } } else if (item->type == SPECIAL) { LOG(">SPECIAL\n"); tmp = check_special(rule, item->value.special, current, grammar, tokens, error); if (tmp == NULL) { LOG("FAIL SPECIAL\n"); DEDENT(); return NULL; } current = tmp; } } DEDENT(); return current; }