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;}