Пример #1
0
array_t *
parse (lexer_t *lex) {
	unsigned i;

	array_t stack;
	array_init(&stack, sizeof(parser_stack_t));
	parser_stack_t initial;
	bzero(&initial, sizeof(initial));
	array_add(&stack, &initial);

	array_t *result = 0;
	while (stack.size > 0) {
		parser_stack_t *current = array_get(&stack, stack.size-1);
		const parser_state_t *state = parser_states + current->state;

		for (i = 0; i < state->num_actions; ++i)
			if (state->actions[i].token == lex->token)
				break;

		if (i >= state->num_actions) {
			char *msg = strdup("syntax error, expected");
			for (i = 0; i < state->num_actions; ++i) {
				char *glue;
				if (i == 0)
					glue = " ";
				else if (i == state->num_actions-1)
					glue = ", or ";
				else
					glue = ", ";
				char *nmsg;
				asprintf(&nmsg, "%s%s\"%s\"", msg, glue, token_names[state->actions[i].token]);
				free(msg);
				msg = nmsg;
			}
			derror(&lex->loc, "%s\n", msg);
			free(msg);
		}

		const parser_action_t *action = &state->actions[i];
		if (action->state_or_length < 0) {
			if (action->rule == 0) {
				result = current->token.ptr;
				break;
			}

			unsigned num_tokens = -action->state_or_length;

			parser_stack_t *target = array_get(&stack, stack.size-num_tokens);
			parser_stack_t *base = array_get(&stack, stack.size-num_tokens-1);
			const parser_state_t *base_state = parser_states + base->state;

			token_t reduced = target->token;
			reduced.id = action->rule;
			reduced.last = current->token.last;

			if (action->reducer) {
				token_t tokens[num_tokens];
				for (i = 0; i < num_tokens; ++i)
					tokens[i] = (target+i)->token;
				action->reducer(&reduced, tokens, action->reducer_tag);
			}

			target->token = reduced;

			for (i = 0; i < base_state->num_gotos; ++i) {
				if (base_state->gotos[i].rule == action->rule) {
					target->state = base_state->gotos[i].state;
					break;
				}
			}

			array_resize(&stack, stack.size-num_tokens+1);
		} else {
			parser_stack_t *new_stack = array_add(&stack, 0);
			bzero(new_stack, sizeof(*new_stack));
			new_stack->state = action->state_or_length;
			new_stack->token.id = lex->token;
			new_stack->token.first = lex->base;
			new_stack->token.last = lex->ptr;
			new_stack->token.loc = lex->loc;
			lexer_next(lex);
		}
	}

	array_dispose(&stack);

	return result;
}
Пример #2
0
void nl_input_dispose(NLInput *in_input)
{
    if (in_input->sentences) array_dispose(in_input->sentences);
    brain_free_(in_input);
}