All pastes #835171 Raw Edit

k4st

public c v1 · immutable
#835171 ·published 2007-12-28 18:48 UTC
rendered paste body
#include <stdlib.h>#include <stdio.h>#include <string.h>#include "parser.h"#include "parse_tree.h"/********************************** * Global variables. **********************************/SwToken *token = NULL;SwTokenBuffer *buffer = NULL;SwOperator *operators[70];SwSymbol prev_symbol = 0; /* the symbol of the last token */char *prev_value = NULL; /* the value of the last token *with* a value *//********************************** * Deal with tokens. **********************************/int get_symbol(void) {    advance();    if(token) {        /* store the prev symbol. */        prev_symbol = token->symbol;                /* If the previous symbol had a value to it then store that value.           Generally, we only know how a value is useful until after we've           gone past it.         */        if(token->value != NULL)            prev_value = token->value;    }    return next_token(buffer) != NULL ? 1 : 0;}int accept(SwSymbol sy) {    advance();    if(token->symbol == sy) {        get_symbol();        advance();        return 1;    }    return 0;}/* Try to accept an operator. */int accept_xfix(SwOperatorType type) {    SwOperator *op;    SwParseTree *leaf, *infix, *left, *parent;        advance();        if(token->symbol > 70)        return 0;        op = operators[token->symbol];        if(op != NULL && op->where == type) {        expect(token->symbol);                //if(type == SW_PREFIX) {        //  unary = create_token_node(SW_TOKEN_NEGATIVE);        //  attach_node_to_leaf(get_leaf_node());        //}                if(type == SW_INFIX) {            //leaf = get_leaf_node();            parent = get_leaf_parent();            parent->symbol = op->symbol;            //left = parent->left;            //infix = create_token_node(token->symbol);                        //infix->left = left;            //infix->right =                         //set_leaf_node(parent);                    }                return 1;    }    return 0;}void expect(SwSymbol sy) {    if(accept(sy)) {        return;    }    PARSE_ERROR("Unexpected token found.\n");}void expect_error(SwSymbol sy, char *error) {    if(accept(sy)) {        return;    }    printf("%s (\"%c%c%c\" found )\n", error, peek_char(buffer, -1), \                        current_char(buffer), peek_char(buffer, 1));    exit(EXIT_FAILURE);}void advance(void) {    token = current_token(buffer);}char *get_last_value(void) {    char *ret = prev_value;    prev_value = NULL;    return ret;}/********************************** * Symbols. **********************************/void clear_operators(void) {    int i = 0;        //if(!(operators = (SwOperator **)malloc(sizeof(SwOperator *) * 70)))    //  FATAL_ERROR("Could not allocate space for operators.");        for(; i < 70; i++) {        operators[i] = NULL;    }}void add_operator(SwSymbol sy, SwOperatorType type, int bind_left, int bind_right) {    SwOperator *o;    int tk = sy;        if(operators[tk] == NULL) {        if(!(o = (SwOperator *)malloc(sizeof(SwOperator))))            FATAL_ERROR("Could not allocate operator for symbol table.");                o->symbol = sy;        o->where = type;        o->bind_left = bind_left;        o->bind_right = bind_right;                operators[tk] = o;    }    return;}/********************************** * Parsing functions! **********************************//* Parse function arguments. Deals with function definitions and function   calls in slightly different ways. */void function_args(int is_def) {    int more_args_allowed = 1, has_arg = 0;    SwParseTree *leaf;    SwParseTree *arg = NULL, *set = NULL, *val = NULL;        /* empty argument list */    if(accept(SW_TOKEN_PAREN_CLOSE)) {        attach_node_to_leaf(create_token_node(SW_TOKEN_NO_ARGS), 0);        return;    }        do {        /* parse tree stuff */        leaf = get_leaf_node();                /* Named argument. */        if(accept(SW_TOKEN_IDENTIFIER)) {                        has_arg = 1;                    /* Simple argument with default value. */        } else if(accept(SW_TOKEN_IDENT_DEF)) {                        expect(SW_TOKEN_SET);                        /* parse tree stuff */            has_arg = 1;            set = create_token_node(SW_TOKEN_SET);            val = encapsulate_sub_tree();                        is_def ? term() : expression(IDENT_DEF);                /* function arguments can be specified to be accepted as procedures.           This type of argument is extremely useful when you don't want it           to be evaluated before being passed in.         */        } else if(accept(SW_TOKEN_IDENT_DEF_PROC)) {                        expect(SW_TOKEN_PROCEDURE);                        /* parse tree stuff */            has_arg = 1;            set = create_token_node(SW_TOKEN_PROCEDURE);            val = encapsulate_sub_tree();                        is_def ? term() : expression(PROC_DEF);                /* The more args symbol '...' must be at the end of the list. In           terms of the parse tree, this is ignored. It is simply a way for           the programmer to hint that a function that they are using will be           accepting a variable number of arguments. */        } else if(accept(SW_TOKEN_MORE_ARGS)) {            if(!is_def)                PARSE_ERROR("Unexpected '...' found. This symbol is only \                             allowed in function definitions.");            more_args_allowed = 0;            has_arg = 0;            val = NULL;        } else {            if(!is_def) {                val = encapsulate_sub_tree();                expression(NO_DEF);            }        }                set_leaf_node(leaf);                /* Add the argument and/or setter and value if they exist. */        if(has_arg) {            arg = create_token_node(SW_TOKEN_IDENTIFIER);            arg->value = get_last_value();                        /* setter and a value */            if(val && set) {                set->left = arg;                set->right = val;                            attach_node_to_leaf(set, 1);                        /* a setter but no value, this will be allowed. */            } else if(set && !val) {                set->left = arg;                set->right = create_token_node(SW_TOKEN_NULL);                            attach_node_to_leaf(set, 1);                        /* just an argument */            } else if(!set && !val) {                attach_node_to_leaf(arg, 1);                        /* hrmmm */            } else {                if(val) free(val);                if(set) free(set);                if(arg) free(arg);            }        } else if(val) {            attach_node_to_leaf(val, 1);        }            } while(more_args_allowed && accept(SW_TOKEN_COMMA));        expect(SW_TOKEN_PAREN_CLOSE);}/* Parse a procedure, this is everything following a =>. Procedures can have   implicit returns (eg: => 1 implicitly returns 1) and that is caught within   statement() and a further call to check_implicit_return(). */void procedure(SwDefTypes def_type) {    SwParseTree *leaf, *proc;        leaf = get_leaf_node();        /* create a tree context for this procedure */    proc = create_token_node(SW_TOKEN_PROC_CONTEXT);    set_leaf_node(proc);        /* procedure in a procedure */    if(accept(SW_TOKEN_PROCEDURE))        procedure(PROC_TO_PROC);        /* possible typo by programmer, tell them */    else if(accept(SW_TOKEN_SET))        PARSE_ERROR("Expected '=>' or <expr> after '=>' but found '='.");        /* procedures are implicit returns */    else {        //printf("before procedure call\n");        expression(def_type);        //printf("after procedure call\n");    }        set_leaf_node(leaf);    attach_node_to_leaf(proc, 0);}/* Function call. This also checks for function calls that return functions   that are then called. */void function_call(int has_args, int force_is_block) {    SwParseTree *leaf = get_leaf_node(), *main = NULL, *func = NULL;    SwParseTree *args = NULL, *context = NULL, *func_leaf;    int new_args = 0;        /* arguments */    if(accept(SW_TOKEN_PAREN_OPEN) || has_args) {        do {            /* create the function calls */            //func_leaf = get_leaf_node();            func = create_token_node(SW_TOKEN_FUNC_CALL);            func->value = get_last_value();                        if(!main) /* keep track of the first function called */                main = func;                        /* set the leaf for function arguments */            args = create_token_node(SW_TOKEN_FUNC_ARGS);            set_leaf_node(args);                        function_args(0);            new_args = accept(SW_TOKEN_PAREN_OPEN);                        set_leaf_node(func);            attach_node_to_leaf(args, new_args);                    } while(new_args);        /* no arguments, likely a macro call. */    } else {                func = create_token_node(SW_TOKEN_FUNC_CALL);        func->value = get_last_value();        main = func;                /* attach empty arguments node */        set_leaf_node(func);        attach_node_to_leaf(create_token_node(SW_TOKEN_FUNC_ARGS), 0);    }        /* attach the main function call to the leaf */    func_leaf = get_leaf_node();    //set_leaf_node(leaf);    //attach_node_to_leaf(main);        /* go to the last leaf left on the func */    set_leaf_node(func_leaf);        if(accept(SW_TOKEN_PROCEDURE)) /* func def */        PARSE_ERROR("Unexpected function definition.");        /* Macro call. Note: the 'func' used will be the last one found from the       above loop.     */    if(force_is_block || accept(SW_TOKEN_COLON)) {                context = create_token_node(SW_TOKEN_FUNC_CONTEXT);        set_leaf_node(context);                block();                set_leaf_node(func_leaf);        attach_node_to_leaf(context, 0);    }        /* Attach this to the leaf and reset. Note: this uses 'main' which is the       first function called.     */    set_leaf_node(leaf);    attach_node_to_leaf(main, 1);}/* The core types are allowed to be accessed directly as functions, format:   "moo"()  123()   12.34() */void try_type_as_function(void) {    if(accept(SW_TOKEN_PAREN_OPEN)) {                prev_value = NULL;        function_call(1, 0);    }/* else if(accept(SW_TOKEN_COLON)) {        prev_value = NULL;        function_call(1, 1);    }*/}/* Parse a function definition. */void function_definition(int is_local, int is_const) {    int is_lambda = (prev_symbol == SW_TOKEN_LAMBDA);        SwParseTree *leaf, *func, *context, *args, *func_leaf;            /* deal with the parse tree */    leaf = get_leaf_node(); /* get the current leaf */    /* information for the function */    func = create_token_node(prev_symbol);    func->value = is_lambda ? NULL : get_last_value();        /* Argument list. We set the leaf node here before function_args() is       called that way it picks up on being under the right branch.     */    args = create_token_node(SW_TOKEN_FUNC_ARGS);    set_leaf_node(args);        expect(SW_TOKEN_PAREN_OPEN);    function_args(1);        set_leaf_node(func);    attach_node_to_leaf(args, 1);        func_leaf = get_leaf_node();            //proc = func;        /* Do tree modifiers manually--this is fugly! Rethink! */    /*if(is_local || is_const) {        mods = create_parse_tree();        if(is_local) {            mods->left = create_token_node(SW_TOKEN_MY);        }        if(is_const) {            mods->right = create_token_node(SW_TOKEN_CONST);        }                func->right = create_parse_tree();        //func->right->left = mods;    }*/    /* Now deal with the body of the function. This is very similar to how       function arguments was done.     */    context = create_token_node(SW_TOKEN_FUNC_CONTEXT);    set_leaf_node(context);    expect(SW_TOKEN_PROCEDURE);    expression(FUNC_DEF); // procedure(FUNC_DEF);            /* we're back to the leaf we started on */        set_leaf_node(func_leaf);    attach_node_to_leaf(context, 0);        set_leaf_node(leaf);    attach_node_to_leaf(func, 1);        /* look for a statement *after* the function */     //statement();}/* A function call in a block. This uses alternate function call syntax that   acts as a language construct. This is really just syntactic sugar but it   lets the language encapsulate many statements where the implicit return   or procedures would not allow. We don't need to do any parse tree stuff in   here because all context things are implicitly done through the function_   call() function. */void block(void) {    SwParseTree *leaf;    statement();    expect_error(SW_TOKEN_SEMICOLON, "Unexpected token found. Expected ';' " \                                     "at end of block-function call.");}/* Lambda funciton, call-only, not allowed to set a variable to the actual   lambda function itself.   Format:  \(arg1, arg2, ...) => expression   Note: lambdas are define-only. The lambda '\' operator cannot be passed         as an argument or set as the value to something. */void lambda(void) {    function_definition(1, 1); /* *** revise is_local/const for lambda? */}/* Parse a dictionary, format:   {"key": val, "key": val, ...} */void dictionary(void) {    SwParseTree *leaf, *dict, *items, *key, *curr, *val;    int first_it = 1;        leaf = get_leaf_node();    dict = create_token_node(SW_TOKEN_TYPE_DICT);    items = create_token_node(SW_TOKEN_DICT_ITEMS);        /* curr represents where we can attach a key/value pair to the dict */    curr = items;        do {                /* double-comma */        if(accept(SW_TOKEN_COMMA))            PARSE_ERROR("Cannot have two commas side-by-side or " \                        "leading/trailing comma in dictionary definition.");                /* wrong item key type */        if(!accept(SW_TOKEN_STRING_LITERAL) && !accept(SW_TOKEN_IDENTIFIER))            PARSE_ERROR("Unexpected token found as key in dictionary.");                /* key/value pairs must be separated with a colon */        expect_error(SW_TOKEN_COLON, "Error: expected ':' in dictionary to " \                                     "separate item key from value.");                        key = create_token_node(SW_TOKEN_DICT_KEY);        key->value = get_last_value();        val = create_token_node(SW_TOKEN_DICT_VALUE);                /* get the parse for the value expression */        set_leaf_node(val);        expression(NO_DEF);                /* attach the dictionary item value to the key */        set_leaf_node(key);        attach_node_to_leaf(val, 0);                /* attach the dictionary item key to the dictionary */        set_leaf_node(curr);        attach_node_to_leaf(key, 1);                /* find the next place that we can put a key/value pair */        curr = get_leaf_node();                first_it = 0;            } while(accept(SW_TOKEN_COMMA));        expect_error(SW_TOKEN_BRACE_CLOSE, "Unexpected token found. Expexted " \                                       "closing '}' at end of dictionary.");        /* attach the dictionary items to the dict */    set_leaf_node(dict);    attach_node_to_leaf(items, 0);        /* attach the dictionary to whatever uses/contains the dict */    set_leaf_node(leaf);    attach_node_to_leaf(dict, 1);}/* Parse a list [1,2,3...] */void list(void) {    SwParseTree *leaf, *ls, *node, *node_leaf, *to = NULL, *top = NULL;    int first_it = 1;        leaf = get_leaf_node();    ls = create_token_node(SW_TOKEN_TYPE_LIST);    node_leaf = ls;        do {        /* double-comma */        if(accept(SW_TOKEN_COMMA))            PARSE_ERROR("Cannot have two commas side-by-side or " \                        "leading/trailing comma in list definition.");                /* Since node_leaf starts as ls, and since list_node() calls term(),           then anything in term is attached to ls (first) and then then the           future leaves.         */        set_leaf_node(node_leaf);        term();        node_leaf = get_leaf_node();                /* a range in a list */        if(first_it && accept(SW_TOKEN_TO)) { /* [term to term] */            attach_node_to_leaf(create_token_node(SW_TOKEN_TO), 1);                    term();            break;        }                first_it = 0;        /* keep looking for commas */    } while(accept(SW_TOKEN_COMMA));        /* end of list */    expect_error(SW_TOKEN_BRACKET_CLOSE, "Error. Expected closing ']' for " \                                         "list definition.");        /* attach the list */    set_leaf_node(leaf);    attach_node_to_leaf(ls, 1);}/* Index or slice on a list/dict/string. Format:   var[0], var[0:2], etc. */void index_or_slice(int allow_multi) {    SwParseTree *leaf, *index;        leaf = get_leaf_node();    index = create_token_node(SW_TOKEN_INDEX_ACCESS);        set_leaf_node(index);    term();        if(accept(SW_TOKEN_COLON)) { /* array slice, [x:y] */               set_leaf_node(index->right);        term();    }    set_leaf_node(leaf);    attach_node_to_leaf(index, 1);        expect_error(SW_TOKEN_BRACKET_CLOSE, "Error. Eexpected closing ']' for" \                                         " list/string accessor/slice.");    if(accept(SW_TOKEN_BRACKET_OPEN)) { /* another list index, recurse */        if(!allow_multi)            PARSE_ERROR("Unexpected index accesor or slice found on non " \                        "multi-dimension list.");        index_or_slice(allow_multi);    }}/* Any entity; identifier, literal, etc. */void add_last_token_to_leaf(void) {    SwParseTree *node, *leaf;        leaf = get_leaf_node();        node = create_token_node(prev_symbol);    node->value = get_last_value();          attach_node_to_leaf(node, 1);}void factor(void) {    SwParseTree *leaf = get_leaf_node();            advance();    //printf("factor \n");        //printf("rest of buffer: \n%s\n", buffer->stream+buffer->pos);        /* ignore unary + */    if(accept(SW_TOKEN_ADD))        factor();        /* deal with unary minus (negative number) */    else if(accept(SW_TOKEN_SUBTRACT)) {        //printf("\tunary negative \n");        //unary = create_token_node(SW_TOKEN_NEGATIVE);        //attach_node_to_leaf(unary);                unary(SW_TOKEN_NEGATIVE);    /* identifiers */    } else if(accept(SW_TOKEN_IDENTIFIER)) {        //printf("\tidentifier \n");        /* function call */        if(accept(SW_TOKEN_PAREN_OPEN)) {            //printf("\tfunc call \n");            function_call(1, 0);                /* macro call without args, force it to go to block */        } else if(accept(SW_TOKEN_COLON)) {            //printf("\tmacro call \n");            function_call(0, 1);        }                /* general identifier */        else {            //printf("\tgeneral ident \n");            add_last_token_to_leaf(); /* adds the identifier as a tree */                        /* array index/slice */            if(accept(SW_TOKEN_BRACKET_OPEN)) {                index_or_slice(1);            }        }        /* integer literals */          } else if(accept(SW_TOKEN_INTEGER)) {        //printf("\tint literal %s \n", prev_value);        add_last_token_to_leaf();        try_type_as_function();        //printf("\t\ttried as function \n");        /* floating-point literals */    } else if(accept(SW_TOKEN_FLOAT)) {        //printf("\tfloat literal \n");        add_last_token_to_leaf();        try_type_as_function();        /* string literals */    } else if(accept(SW_TOKEN_STRING_LITERAL)) {        //printf("\tstring literal \n");        add_last_token_to_leaf();        try_type_as_function();                if(accept(SW_TOKEN_BRACKET_OPEN)) { /* allow direct access/slices on                                                string literals. */            //printf("\t\tindex/slice \n");            index_or_slice(0);        }    /* booleans */    } else if(accept(SW_TOKEN_BOOL_TRUE) || accept(SW_TOKEN_BOOL_FALSE)) {        add_last_token_to_leaf();        try_type_as_function();            /* null */    } else if(accept(SW_TOKEN_NULL)) {                add_last_token_to_leaf();        try_type_as_function();        /* sub expression */    } else if(accept(SW_TOKEN_PAREN_OPEN)) {        //printf("rest of buffer: \n%s\n", buffer->stream+buffer->pos);        expression(NO_DEF);        //printf("rest of buffer: \n%s\n", buffer->stream+buffer->pos);                //printf("before paren close\n");        expect(SW_TOKEN_PAREN_CLOSE);        //printf("after paren close\n");            /* dictionary */    } else if(accept(SW_TOKEN_BRACE_OPEN)) {        //printf("\tdict def \n");        dictionary();        try_type_as_function();            /* list */    } else if(accept(SW_TOKEN_BRACKET_OPEN)) {        //printf("\tlist def \n");        list();        try_type_as_function();    } else {        //printf("\tflow \n");        flow_controls();    }    //printf("end of factor\n");}/* Deal with unary operators (!, -, etc) */void unary(SwSymbol sy) {    SwParseTree *leaf = get_leaf_node(), *unary;        unary = create_token_node(sy);        /* allow for multiple unary nodes, eg: !!x (cast to bool) */    while(accept_xfix(SW_PREFIX)) {        set_leaf_node(unary);        attach_node_to_leaf(create_token_node(prev_symbol), 1);        unary = get_leaf_node();    }        set_leaf_node(unary);    factor();        set_leaf_node(leaf);    attach_node_to_leaf(unary, 1);}/* A single term including any prefix operators. */void term(void) {    int has_prefix = accept_xfix(SW_PREFIX);        if(has_prefix) {        unary(prev_symbol); /* unary calls factor() */        //printf("end of term-unary\n");    } else {        factor();        //printf("end of term-factor\n");    }    //printf("end of term\n");}/* Flow control operators */void flow_controls(void) {    SwParseTree *leaf = get_leaf_node();        if(accept(SW_TOKEN_RETURN)) {                add_last_token_to_leaf();                set_leaf_node(get_leaf_node());                /* acting as function */        if(accept(SW_TOKEN_PAREN_OPEN)) {                        function_args(0);                /* acting as expression */          } else {            expression(NO_DEF);        }                /* pop out of the return */        set_leaf_node(leaf);            } else if(accept(SW_TOKEN_CONT)) {            } else if(accept(SW_TOKEN_BREAK)) {            } else if(accept(SW_TOKEN_YIELD)) {            }}/* Parse the rest of an expression. The start of an expression is meant to   find the first term, then the rest of the expression looks to see if this   is an infix operation. When no infix terms are left, we assume a new that   the next thing we will find is part of an entirely new statement. */void rest_of_expression(void) {    while(accept_xfix(SW_INFIX)) {        term();        //printf("out of term\n");    }    //printf("end of rest of expression\n");}void expression(SwDefTypes def_type) {    if(accept(SW_TOKEN_LAMBDA)) {        lambda();    } else {        term();        //printf("begin rest of expression\n");        rest_of_expression();        //printf("end rest of expression\n");    }}/* Deal with implicit returns in functions/procedures. We will only do this   if the previous symbol was a => */int check_implicit_return(void) {    if(prev_symbol == SW_TOKEN_PROCEDURE) {        expression(PROC_DEF);        return 1;    }    return 0;}/* If there were modifiers either in the wrong place or they were repeated   then error. */void error_if_ident_modified(int is_local, int is_const) {    if(is_local || is_const)        PARSE_ERROR("Repeated modifiers 'my' or 'const' or modifiers modify" \                    " function call.");}/* Parse a new statement. A statement could be a function call, definition,   variable definition, etc. Many tokens are known to be, for example,   function definitions already because the tokenizer looked ahead to try   to figure that out. */void statement(void) {    SwParseTree *leaf, *node;    int is_local = 0, is_const = 0;            statement_check: /* !!! goto comes here */        leaf = get_leaf_node();    //printf("statement\n");    /* Identifier, could be many things! */    if(accept(SW_TOKEN_IDENTIFIER)) {                /* func call */        if(accept(SW_TOKEN_PAREN_OPEN)) {            error_if_ident_modified(is_local, is_const);            function_call(1, 0);            statement();                /* slice/index */        } else if(accept(SW_TOKEN_BRACKET_OPEN))            index_or_slice(1);                /* These cases should only happen if for some reason the interpreter           wasn't able to properly identify the IDENT_DEF, or IDENT_DEF_PROC.         */        else if(accept(SW_TOKEN_SET))            goto identifier_set;                else if(accept(SW_TOKEN_PROCEDURE))            goto procedure_set;                /* try for a function call as construct, no args */        else {            function_call(0, 0);            statement();        }        /* Function definition */    } else if(accept(SW_TOKEN_FUNC_DEF)) {        function_definition(is_local, is_const);        statement();        /* lambda */    } else if(accept(SW_TOKEN_LAMBDA)) {        lambda();        /* Identifier definition */    } else if(accept(SW_TOKEN_IDENT_DEF)) {                expect(SW_TOKEN_SET);                identifier_set: /* !!! goto comes here */                node = create_token_node(SW_TOKEN_SET);        node->left = create_token_node(SW_TOKEN_IDENTIFIER);        node->left->value = get_last_value();        node->right = create_token_node(SW_EXPRESSION);                set_leaf_node(node->right);        expression(IDENT_DEF);                set_leaf_node(leaf);        attach_node_to_leaf(node, 1);                        statement();        /* Found a =>, send it off to the procedure function */    } else if(accept(SW_TOKEN_IDENT_DEF_PROC)) {        expect(SW_TOKEN_PROCEDURE);                procedure_set: /* !!! goto comes here */                node = create_token_node(SW_TOKEN_PROCEDURE);        node->left = create_token_node(SW_TOKEN_IDENTIFIER);        node->left->value = get_last_value();        node->right = create_parse_tree();                set_leaf_node(node->right);        procedure(PROC_DEF);                set_leaf_node(leaf);        attach_node_to_leaf(node, 0);                statement();        /* Ugly check to see if an identifier should be local or const (or       both).     */    } else if(accept(SW_TOKEN_MY) || accept(SW_TOKEN_CONST)) {                error_if_ident_modified(is_local, is_const);                if(!is_local && prev_symbol == SW_TOKEN_MY) {            is_local = 1;            if(accept(SW_TOKEN_CONST))                is_const = 1;        }        if(!is_const && prev_symbol == SW_TOKEN_CONST) {            is_const = 1;            if(accept(SW_TOKEN_MY))                is_local = 1;        }                goto statement_check;            /* Found a lambda */    } else if(accept(SW_TOKEN_LAMBDA))                lambda();        /* It's possible that we're in an implicitly returning procedure */    else {        if(!check_implicit_return()) {            expression(NO_DEF);        } else {            flow_controls();        }    }}/* Parse away! */SwParseTree *parse_stream(char *stream) {        clear_operators();        add_operator(SW_TOKEN_NOT, SW_PREFIX, 1, 10);    add_operator(SW_TOKEN_POSITIVE, SW_PREFIX, 1, 10);    add_operator(SW_TOKEN_NEGATIVE, SW_PREFIX, 1, 10);    add_operator(SW_TOKEN_MY, SW_PREFIX, 1, 10);    add_operator(SW_TOKEN_CONST, SW_PREFIX, 1, 10);    add_operator(SW_TOKEN_ADD, SW_INFIX, 4, 4);    add_operator(SW_TOKEN_SUBTRACT, SW_INFIX, 4, 4);    add_operator(SW_TOKEN_DIVIDE, SW_INFIX, 5, 5);    add_operator(SW_TOKEN_MODULO, SW_INFIX, 5, 5);    add_operator(SW_TOKEN_MULTIPLY, SW_INFIX, 6, 6);    add_operator(SW_TOKEN_EXPONENT, SW_INFIX, 6, 7);    add_operator(SW_TOKEN_BIT_OR, SW_INFIX, 3, 3);    add_operator(SW_TOKEN_BIT_XOR, SW_INFIX, 3, 3);    add_operator(SW_TOKEN_BIT_AND, SW_INFIX, 3, 3);    add_operator(SW_TOKEN_BIT_LSHIFT, SW_INFIX, 5, 4);    add_operator(SW_TOKEN_BIT_RSHIFT, SW_INFIX, 4, 5);    add_operator(SW_TOKEN_BIT_COMPLEMENT, SW_INFIX, 3, 3);    add_operator(SW_TOKEN_IS, SW_INFIX, 2, 2);    add_operator(SW_TOKEN_IN, SW_INFIX, 2, 2);    //add_operator(SW_TOKEN_TO, SW_INFIX, 5, 5);        add_operator(SW_TOKEN_EQUALS, SW_INFIX, 2, 2);    add_operator(SW_TOKEN_NOT_EQUALS, SW_INFIX, 2, 2);    add_operator(SW_TOKEN_LOGICAL_AND, SW_INFIX, 1, 1);    add_operator(SW_TOKEN_LOGICAL_OR, SW_INFIX, 0, 0);    add_operator(SW_TOKEN_LOGICAL_XOR, SW_INFIX, 0, 0);    add_operator(SW_TOKEN_LT, SW_INFIX, 4, 4);    add_operator(SW_TOKEN_GT, SW_INFIX, 4, 4);    add_operator(SW_TOKEN_LT_EQUAL, SW_INFIX, 4, 4);    add_operator(SW_TOKEN_GT_EQUAL, SW_INFIX, 4, 4);    init_parse_tree();    buffer = init_tokenizer(stream);    get_symbol();        while(!end_of_buffer(buffer)) {        statement();    }        /* set an end-of-file marker */    attach_node_to_leaf(create_token_node(SW_TOKEN_EOF), 0);    disable_tokenizer(buffer);    return getParseTree();}