Example #1
0
static struct AstNode *parse_if(
        struct DomNode *dom,
        struct ParserState *state)
{
    struct DomNode *child = NULL;
    struct AstNode *test = NULL;
    struct AstNode *true_expr = NULL;
    struct AstNode *false_expr = NULL;

    /* 1. Is compound CORE */
    if (!dom_node_is_spec_compound(dom, DOM_CPD_CORE)) {
        return NULL;
    }

    /* 2. Has 4 children */
    if (!dom_node_is_cpd_of_size(dom, 4)) {
        return NULL;
    }

    child = dom->cpd_children;

    /* 3.1. 1st child is the if keyword. */
    if (!dom_node_is_spec_reserved_atom(child, DOM_RES_IF)) {
        return NULL;
    }
    child = child->next;

    /* 3.2 2nd child is a valid expression. */
    if (!(test = parse_one(child, state))) {
        return NULL;
    }
    child = child->next;

    /* 3.3 3rd child is a valid expression. */
    if (!(true_expr = parse_one(child, state))) {
        ast_node_free(test);
        return NULL;
    }
    child = child->next;

    /* 3.4 4th child is a valid expression. */
    if (!(false_expr = parse_one(child, state))) {
        ast_node_free(test);
        ast_node_free(true_expr);
        return NULL;
    }

    return ast_make_spec_if(test, true_expr, false_expr);
}
Example #2
0
static void bif_parse_any(struct Runtime *rt, char *string)
{
    struct AstNode *ast;

    ast = parse_source(string, NULL, NULL);
    if (!ast) {
        bif_text_error_parse();
        return;
    }

    if (ast->next != NULL) {
        bif_text_error_parse();
        ast_node_free(ast);
        return;
    }

    bif_parse_any_ast(rt, ast);
    ast_node_free(ast);
}
Example #3
0
static void bif_parse_atomic(
        struct Runtime *rt,
        VAL_LOC_T arg_loc,
        char *func,
        enum AstLiteralAtomicType type)
{
    VAL_LOC_T size_loc, data_begin, data_size;
    struct AstNode *ast = NULL;
    char *source, *err;

    /* Assert input. */
    if (!rt_val_is_string(rt, arg_loc)) {
        bif_text_error_arg(1, func, "must be a string");
        return;
    }

    /* Push header. */
    rt_val_push_tuple_init(&rt->stack, &size_loc);
    data_begin = rt->stack.top;

    source = rt_val_peek_cpd_as_string(rt, arg_loc);
    ast = parse_source(source, NULL, NULL);
    mem_free(source);

    /* Error detection. */
    if (!ast) {
        err = "Failed parsing atomic literal";
        rt_val_push_bool(&rt->stack, false);
        rt_val_push_string(&rt->stack, err, err + strlen(err));
        goto end;
    }
    if (ast->next != NULL) {
        err = "Too many nodes.";
        rt_val_push_bool(&rt->stack, false);
        rt_val_push_string(&rt->stack, err, err + strlen(err));
        goto end;
    }
    if (ast->type != AST_LITERAL_ATOMIC || ast->data.literal_atomic.type != type) {
        err = "Incorrect type.";
        rt_val_push_bool(&rt->stack, false);
        rt_val_push_string(&rt->stack, err, err + strlen(err));
        goto end;
    }

    /* Correct case. */
    rt_val_push_bool(&rt->stack, true);
    bif_parse_any_ast_literal_atomic(rt, &ast->data.literal_atomic);

end:
    data_size = rt->stack.top - data_begin;
    rt_val_push_cpd_final(&rt->stack, size_loc, data_size);
    if (ast) {
        ast_node_free(ast);
    }
}
Example #4
0
void ast_node_free(ast_node n)
{
	if (!n)
		return;
	switch (n->type) {
	case N_2OP:
		ast_node_free(n->left);
		ast_node_free(n->right);
		break;
	case N_NUM:
		break;
	case N_VAR:
		free(n->id);
		n->id = NULL;
		break;
	case N_COND:
		ast_node_free(n->left);
		ast_node_free(n->arg[0]);
		ast_node_free(n->arg[1]);
		break;
	}
	free(n);
}
Example #5
0
static struct AstNode *parse_binary(
        struct DomNode *dom,
        enum Reserved keyword,
        struct AstNode *(*constructor)(
            struct AstNode *,
            struct AstNode *),
        struct ParserState *state)
{
    struct DomNode *child = NULL;
    struct AstNode *arg1 = NULL;
    struct AstNode *arg2 = NULL;

    /* 1. Is compound CORE */
    if (!dom_node_is_spec_compound(dom, DOM_CPD_CORE)) {
        return NULL;
    }

    /* 2. Has 2 children */
    if (!dom_node_is_cpd_of_size(dom, 3)) {
        return NULL;
    }

    child = dom->cpd_children;

    /* 2.1. 1st child is the proper keyword. */
    if (!dom_node_is_spec_reserved_atom(child, keyword)) {
        return NULL;
    }
    child = child->next;

    /* 2.2 2nd child is a valid expression. */
    if (!(arg1 = parse_one(child, state))) {
        return NULL;
    }
    child = child->next;

    /* 2.3 3rd child is a valid expression. */
    if (!(arg2 = parse_one(child, state))) {
        ast_node_free(arg1);
        return NULL;
    }
    child = child->next;

    return constructor(arg1, arg2);
}
Example #6
0
static struct AstNode *parse_list(
        struct DomNode *dom,
        struct ParserState *state)
{
    struct AstNode *node;
    struct AstNode *result = NULL;
    struct AstNode *result_end = NULL;

    while (dom) {
        if ((node = parse_one(dom, state))) {
            LIST_APPEND(node, &result, &result_end);

        } else {
            ast_node_free(result);
            return NULL;
        }
        dom = dom->next;
    }

    return result;
}
Example #7
0
static struct AstNode *parse_bind(
        struct DomNode *dom,
        struct ParserState *state)
{
    struct DomNode *child = NULL;
    struct AstNode *pattern = NULL;
    struct AstNode *expr = NULL;

    /* 1. Is compound CORE */
    if (!dom_node_is_spec_compound(dom, DOM_CPD_CORE)) {
        return NULL;
    }

    /* 2. Has 3 children */
    if (!dom_node_is_cpd_of_size(dom, 3)) {
        return NULL;
    }

    child = dom->cpd_children;

    /* 2.1. 1st child is bind keyword. */
    if (!dom_node_is_spec_reserved_atom(child, DOM_RES_BIND)) {
        return NULL;
    }
    child = child->next;

    /* 2.2. 2nd child is pattern. */
    if (!(pattern = parse_one(child, state))) {
        return NULL;
    }
    child = child->next;

    /* 2.3 3rd child is any expression. */
    if (!(expr = parse_one(child, state))) {
        ast_node_free(pattern);
        return NULL;
    }

    return ast_make_spec_bind(pattern, expr);
}
Example #8
0
static struct AstNode *parse_func_def(
        struct DomNode *dom,
        struct ParserState *state)
{
    struct AstNode *expr = NULL;

    struct DomNode *child = NULL;
    struct DomNode *arg_child = NULL;

    struct AstNode *formal_args = NULL, *formal_args_end = NULL;

    /* 1. Is compound CORE. */
    if (!dom_node_is_spec_compound(dom, DOM_CPD_CORE)) {
        return NULL;
    }

    /* 2. Has 3 children. */
    if (!dom_node_is_cpd_of_size(dom, 3)) {
        return NULL;
    }

    child = dom->cpd_children;

    /* 2.1. 1st child is "func" keyword. */
    if (!dom_node_is_spec_reserved_atom(child, DOM_RES_FUNC)) {
        return NULL;
    }
    child = child->next;

    /* 2.2. 2nd keyword is a core compound of patterns. */
    if (!dom_node_is_spec_compound(child, DOM_CPD_CORE)) {
        return NULL;
    }

    arg_child = child->cpd_children;

    /* Argument list may be empty. */
    if (arg_child) {
        while (arg_child) {
            struct AstNode *pattern;
            if (!(pattern = parse_one(arg_child, state))) {
                goto fail;
            } else {
                LIST_APPEND(pattern, &formal_args, &formal_args_end);
            }
            arg_child = arg_child->next;
        }
    }

    child = child->next;

    /* 2.3. Has 1 more further expression. */
    if (!(expr = parse_one(child, state))) {
        goto fail;
    }

    return ast_make_spec_func_def(formal_args, expr);

fail:
    if (formal_args) {
        ast_node_free(formal_args);
    }

    return NULL;
}
Example #9
0
static struct AstNode *parse_match(
        struct DomNode *dom,
        struct ParserState *state)
{
    struct DomNode *child = NULL;
    struct AstNode *expr = NULL;
    struct AstNode *keys = NULL, *keys_end = NULL;
    struct AstNode *values = NULL, *values_end = NULL;

    /* 1. Is compound CORE. */
    if (!dom_node_is_spec_compound(dom, DOM_CPD_CORE)) {
        return NULL;
    }

    /* 2. Has 3 or more children. */
    if (!dom_node_is_cpd_min_size(dom, 3)) {
        return NULL;
    }

    child = dom->cpd_children;

    /* 3.1. 1st child is "match" keyword. */
    if (!dom_node_is_spec_reserved_atom(child, DOM_RES_MATCH)) {
        return NULL;
    }
    child = child->next;

    /* 3.2. 2nd child is an expression. */
    if (!(expr = parse_one(child, state))) {
        return NULL;
    }
    child = child->next;

    /* 3.3. Has at least one matching expression. */
    while (child) {
        struct DomNode *match_child = NULL;
        struct AstNode *key = NULL;
        struct AstNode *value = NULL;

        /* 3.3.1. Is compound CORE. */
        if (!dom_node_is_spec_compound(child, DOM_CPD_CORE)) {
            goto fail;
        }

        /* 3.3.2. Has 2 children. */
        if (!dom_node_is_cpd_of_size(child, 2)) {
            goto fail;
        }
        match_child = child->cpd_children;

        /* 3.3.3. 1st child is a pattern. */
        if (!(key = parse_one(match_child, state))) {
            goto fail;
        }
        match_child = match_child->next;

        /* 3.3.4. 2nd child is an expression. */
        if (!(value = parse_one(match_child, state))) {
            goto fail;
        }

        LIST_APPEND(key, &keys, &keys_end);
        LIST_APPEND(value, &values, &values_end);

        child = child->next;
    }

    return ast_make_spec_match(expr, keys, values);

fail:
    ast_node_free(expr);

    if (keys) {
        ast_node_free(keys);
    }

    if (values) {
        ast_node_free(values);
    }

    return NULL;
}
Example #10
0
void ast_node_free(ast_node* p)
{
	if(!p)
		return;
	switch(p->type) {
		case AST_NODE_TYPE_UNARY_OP:
			ast_node_free(p->u1.unary_node.expr);
			free(p);
		break;
		case AST_NODE_TYPE_POSTFIX:
			ast_node_free(p->u1.postfix_node.expr);
			free(p);
		break;
		case AST_NODE_TYPE_WHILE:
			ast_node_free(p->u1.while_node.condition);
			ast_node_free(p->u1.while_node.body);
			free(p);
		break;
		case AST_NODE_TYPE_FOR:
			ast_node_free(p->u1.for_node.initialization);
			ast_node_free(p->u1.for_node.condition);
			ast_node_free(p->u1.for_node.final_expression);			
			ast_node_free(p->u1.for_node.body);	
			free(p);
		break;
		case AST_NODE_TYPE_STRING:
			free(p->u1.string_value.value);
			free(p);
		break;
		case AST_NODE_TYPE_RET:
			ast_node_free(p->u1.return_node.expr);
			free(p);
		break;
		case AST_NODE_TYPE_IF:
			ast_node_free(p->u1.if_node.condition);
			ast_node_free(p->u1.if_node.b1);
			ast_node_free(p->u1.if_node.b2);
			free(p);
		break;
		case AST_NODE_TYPE_NUMBER:
			free(p);
		break;
		case AST_NODE_TYPE_STATEMENT_LIST: {
			size_t i;
			for(i = 0; i < p->u1.statements_node.count; i++) {
				ast_node_free(p->u1.statements_node.statement_list[i]);
			}
			free(p->u1.statements_node.statement_list);
			free(p);
		} 
		break;
		case AST_NODE_TYPE_BIN_OP:
			ast_node_free(p->u1.binary_node.left);
			ast_node_free(p->u1.binary_node.right);
			free(p);
		break;
		case AST_NODE_TYPE_ID:
			free(p->u1.id_node.name);
			free(p);
		break;
		case AST_NODE_TYPE_FUNC_DECL:
			free(p->u1.function_node.name);
			ast_node_free(p->u1.function_node.parameter_list);
			ast_node_free(p->u1.function_node.body);
			free(p);		
		break;
		case AST_NODE_TYPE_PRINT:
			ast_node_free(p->u1.print_node.expr);
			free(p);		
		break;
		case AST_NODE_TYPE_CALL:
			ast_node_free(p->u1.call_node.id);
			ast_node_free(p->u1.call_node.arguments);
			free(p);		
		break;
		default:
			como_error_noreturn("p->type not implemented (%d)", p->type);
		break;
	}
}