All pastes #831639 Raw Edit

k4st

public c v1 · immutable
#831639 ·published 2007-12-25 05:51 UTC
rendered paste body
#include <stdlib.h>#include <stdio.h>#include <string.h>#include "../global/macros.h"#include "../tokenizer/tokenizer.h"#include "parser.h"#define PDEBUG/********************************** * Global variables. **********************************/char stream[] = "identifier(arg1, arg2, ...) => do: \n\twhile:\n\t;\n;\ntest = 1+2+3+!x\nmoo => 1*(5/6)";SwSymbol prev_symbol = 0;SwToken *token = NULL;SwTokenBuffer *buffer = NULL;SwOperator *operators[70];/********************************** * Deal with tokens. **********************************/int get_symbol(void) {    advance();    if(token) /* store the prev symbol. */        prev_symbol = token->symbol;    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) {    advance();    SwOperator *op = operators[token->symbol];    if(op != NULL && op->where == type) {        expect(token->symbol);        return 1;    }    return 0;}void expect(SwSymbol sy) {    PDEBUG printf("\tExpecting token [%d]\n", sy);    if(accept(sy)) {        PDEBUG printf("\t\tFound token [%d]\n", sy);        return;    }    PARSE_ERROR("Unexpected token found.\n");}void advance(void) {    token = current_token(buffer);}/********************************** * 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;    PDEBUG printf("Adding operator [%d]\n", tk);    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 def) {    PDEBUG printf("\tParsing function arguments... \n");    int more_args_allowed = 1;    do {        /* Named argument. */        if(accept(SW_TOKEN_IDENTIFIER))            ;                /* Simple argument with default value. */        else if(accept(SW_TOKEN_IDENT_DEF)) {            expect(SW_TOKEN_SET);            def ? term() : expression();                /* 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);            def ? term() : expression();                /* The more args symbol '...' must be at the end of the list. */        } else if(accept(SW_TOKEN_MORE_ARGS)) {            if(!def)                PARSE_ERROR("Unexpected '...' found. This symbol is only \                             allowed in function definitions.");            more_args_allowed = 0;        }    } while(more_args_allowed && accept(SW_TOKEN_COMMA));        expect(SW_TOKEN_PAREN_CLOSE);        /* Check for function calls returning functions (which are then being        called).     */    if(!def) {        if(accept(SW_TOKEN_PAREN_OPEN))            function_args(0);    }}/* Lambda funciton, call-only, not allowed to set a variable to the actual   lambda function itself. */void lambda(void) {    PDEBUG printf("Parsing lambda expression... \n");    expect(SW_TOKEN_PAREN_OPEN);    function_args(1);    expect(SW_TOKEN_PROCEDURE); /* lambdas are define-only */    procedure();}/* Parse a procedure */void procedure(void) {    PDEBUG printf("\tParsing procedure... \n");    if(accept(SW_TOKEN_PROCEDURE)) /* procedure in a procedure */        procedure();    else if(accept(SW_TOKEN_SET)) /* possible typo by programmer */        PARSE_ERROR("Expected '=>' or <expr> after '=>' but found '='.");    else        statement();}/* Parse a dictionary */void dictionary(void) {    PDEBUG printf("Parsing dictionary definition... \n");    do {        expect(SW_TOKEN_STRING_LITERAL);        expect(SW_TOKEN_COLON);        term();    } while(accept(SW_TOKEN_COMMA));    expect(SW_TOKEN_BRACE_CLOSE);}/* Parse a list */void list(void) {    PDEBUG printf("Parsing list definition... \n");    do {        term();                /* a range in a list */        if(accept(SW_TOKEN_TO)) { /* [term to term] */            term();            break;        }    } while(accept(SW_TOKEN_COMMA));    expect(SW_TOKEN_BRACKET_CLOSE);}/* Index or slice on a list/dict/string. */void index_or_slice(int allow_multi) {    PDEBUG printf("\tFound index or slice \n");    term();    if(accept(SW_TOKEN_COLON)) { /* array slice, [x:y] */        PDEBUG printf("\t\tIt was a slice.\n");        term();    }        expect(SW_TOKEN_BRACKET_CLOSE);        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);    }}/* The core types are allowed to be accessed directly as functions, eg:   "moo"()  123()   12.34() */void try_type_as_function(void) {    if(accept(SW_TOKEN_PAREN_OPEN)) {        PDEBUG printf("Found function call on literal, parsing arguments...\n");        function_args(0);    }}void factor(void) {    /* debugging */    advance();    char *val = token->value;        printf("value: %s\n", val);        /* deal with unary +/- */    if(accept(SW_TOKEN_ADD) || accept(SW_TOKEN_SUBTRACT)) {        advance();        PDEBUG printf("\tFound unary +/-\n");        token->symbol = token->symbol == SW_TOKEN_ADD ? SW_TOKEN_POSITIVE : \                                                        SW_TOKEN_NEGATIVE;        factor();            /* identifiers */    } else if(accept(SW_TOKEN_IDENTIFIER)) {        PDEBUG printf("\tFound identifier [%s] \n", val);        if(accept(SW_TOKEN_PAREN_OPEN)) { /* function call */            function_args(0);            if(accept(SW_TOKEN_COLON)) { /* macro call */                block();            }        } else if(accept(SW_TOKEN_BRACKET_OPEN)) /* array index/slice */            index_or_slice(1);        /* integer literals */          } else if(accept(SW_TOKEN_INTEGER)) {        PDEBUG printf("\tFound integer literal [%s] \n", val);        try_type_as_function();        /* floating-point literals */    } else if(accept(SW_TOKEN_FLOAT)) {        PDEBUG printf("\tFOund floating-point literal [%s] \n", val);        try_type_as_function();        /* string literals */    } else if(accept(SW_TOKEN_STRING_LITERAL)) {        PDEBUG printf("\tFound string literal [\"%s\"] \n", val);        try_type_as_function();        if(accept(SW_TOKEN_BRACKET_OPEN)) { /* allow direct access/slices on                                                string literals. */            index_or_slice(0);        }        /* booleans */    } else if(accept(SW_TOKEN_BOOL_TRUE) || accept(SW_TOKEN_BOOL_FALSE)) {        PDEBUG printf("\tFound boolean literal [true/false]\n");        try_type_as_function();    } else if(accept(SW_TOKEN_NULL)) {        PDEBUG printf("\tFound null literal \n");        try_type_as_function();        /* sub expression */    } else if(accept(SW_TOKEN_PAREN_OPEN)) {        expression();        expect(SW_TOKEN_PAREN_CLOSE);    } else if(accept(SW_TOKEN_BRACE_OPEN)) {        dictionary();    } else if(accept(SW_TOKEN_BRACKET_OPEN)) {        list();    }}void term(void) {    factor();}void rest_of_expression(void) {    while(accept_xfix(SW_INFIX)) {        while(accept_xfix(SW_PREFIX)) /* eg: you can have: !!x */            ;        term();    }    statement();}void expression(void) {    PDEBUG printf("Parsing expression... \n");    if(accept(SW_TOKEN_LAMBDA)) {        lambda();    }        term();    PDEBUG printf("Parsing rest of expression...\n");    rest_of_expression();}void block(void) {    PDEBUG printf("<block> \n");    statement();    expect(SW_TOKEN_SEMICOLON);    PDEBUG printf("</block>\n");    statement();}/* Deal with implicit returns in functions/procedures. We will only do this   if the previous symbol was a => */void check_implicit_return(void) {    if(prev_symbol == SW_TOKEN_PROCEDURE)        expression();}void statement(void) {    advance();    printf("statement\n");    PDEBUG printf("\tFound token [%d], value [%s]\n", token->symbol, token->value);            if(accept(SW_TOKEN_IDENTIFIER) || accept(SW_TOKEN_LAMBDA)) {        if(accept(SW_TOKEN_PAREN_OPEN)) { /* func call */            function_args(0);            if(accept(SW_TOKEN_PROCEDURE)) /* func def */                PARSE_ERROR("Unexpected function definition.");            else if(accept(SW_TOKEN_COLON)) /* macro call */                block();                        } else if(accept(SW_TOKEN_BRACKET_OPEN))            expression();        else if(accept(SW_TOKEN_COLON)) /* macro call, no args */            block();        else if(accept(SW_TOKEN_SET))            goto identifier_set;        else if(accept(SW_TOKEN_PROCEDURE))            goto procedure_set;    } else if(accept(SW_TOKEN_FUNC_DEF)) {        PDEBUG printf("\t\tStatement is function definition \n");        expect(SW_TOKEN_PAREN_OPEN);        function_args(1);        expect(SW_TOKEN_PROCEDURE);        procedure();    } else if(accept(SW_TOKEN_IDENT_DEF)) {        expect(SW_TOKEN_SET);                identifier_set:        PDEBUG printf("\t\tStatement is identifier definition \n");        expression();        /* Found a =>, send it off to the procedure function */    } else if(accept(SW_TOKEN_IDENT_DEF_PROC)) {        expect(SW_TOKEN_PROCEDURE);                procedure_set:        PDEBUG printf("\t\tStatement is procedure definition \n");        procedure();        /* Found a lambda */    } else if(accept(SW_TOKEN_LAMBDA)) {        lambda();        /* Likely in an implicitly returning procedure, statement can't handle       that. What we want is a way to make it explicit.     */    } else {        check_implicit_return();    }}int main() {        printf("\n\nTesting Swerve parser...\n");    printf("---------------\n");    printf("buffer to parse: \n%s\n\n", 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_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);    //add_operator(SW_TOKEN_RANGE, SW_INFIX, 9, 9);    buffer = init_tokenizer(stream);        PDEBUG printf("<swerve>\n");    get_symbol();    statement();    PDEBUG printf("</swerve>\n");    disable_tokenizer(buffer);        return 0;}