#include "parser.h" #include "emit.h" Parser parser; /**************************************************** * Scope ***************************************************/ void scope_push(Arena *arena) { Scope *child = aalloc(arena, sizeof(Scope)); child->symbols = new_list(arena); child->parent = parser.current_scope; parser.current_scope = child; } void scope_pop() { Scope *prev = parser.current_scope->parent; parser.current_scope = prev; } Symbol * scope_get_symbol(Scope *scope, const char *name, u32 name_length) { u32 count, i; if(!scope) return nil; count = scope->symbols->count; for(i = 0; i < count; i++) { Symbol *sym = list_get(scope->symbols, i); if(sleq(sym->name, name, name_length)) return sym; } return scope_get_symbol(scope->parent, name, name_length); } Symbol * scope_add_symbol(Arena *arena, const char *name, u32 name_length, SymbolType type, u32 size) { Symbol *sym = scope_get_symbol(parser.current_scope, name, name_length); if(sym != nil) return sym; sym = aalloc(arena, sizeof(Symbol)); scpy(sym->name, name, slen(name)); sym->name_length = slen(name); sym->type = type; sym->secondary_type = VOID; sym->size = size; sym->ref = 0; if(type == PLEX || type == METHOD || type == TRAIT) { sym->args = new_list(arena); sym->fields = new_list(arena); } list_push(arena, parser.current_scope->symbols, sym, sizeof(Symbol)); return sym; } /**************************************************** * Parser ***************************************************/ bool advance() { parser.previous = parser.current; for(;;) { parser.current = next_token(); if(parser.current.type != TOKEN_ERROR) return true; return false; } } static bool check(TokenType type) { return parser.current.type == type; } bool consume(TokenType type) { if(check(type)) { advance(); return true; } return false; } static bool match(TokenType type) { if(!check(type)) return false; advance(); return true; } static void expression(); static void statement(); static void declaration(); static ParseRule *get_rule(TokenType type); static void parse_precedence(Precedence precedence); static void binary() { TokenType operatorType = parser.previous.type; ParseRule *rule = get_rule(operatorType); switch(operatorType) { case TOKEN_BANG_EQ: emit_ne(); break; case TOKEN_EQ_EQ: emit_eq(); break; case TOKEN_GT: emit_ge(); break; case TOKEN_GTE: emit_ge(); break; case TOKEN_LT: emit_lt(); break; case TOKEN_LTE: emit_le(); break; case TOKEN_PLUS: emit_add(); break; case TOKEN_MINUS: emit_sub(); break; case TOKEN_STAR: emit_mul(); break; case TOKEN_SLASH: emit_div(); break; default: return; } /* Move to above switch statement for postfix */ parse_precedence((Precedence)(rule->precedence + 1)); } static void literal() { switch(parser.previous.type) { case TOKEN_KEYWORD_FALSE: emit_false(); break; case TOKEN_KEYWORD_TRUE: emit_true(); break; case TOKEN_KEYWORD_NIL: emit_nil(); break; default: return; } } static void expression() { parse_precedence(PREC_ASSIGNMENT); } static void declaration() { if(match(TOKEN_TYPE_INT)) { emit_int_type(); } else if(match(TOKEN_TYPE_NAT)) { emit_nat_type(); } else if(match(TOKEN_TYPE_REAL)) { emit_real_type(); } else if(match(TOKEN_TYPE_STR)) { emit_str_type(); } else if(match(TOKEN_TYPE_BOOL)) { emit_bool_type(); } else if(match(TOKEN_TYPE_BYTE)) { emit_byte_type(); } else if(match(TOKEN_TYPE_U8)) { emit_u8_type(); } else if(match(TOKEN_TYPE_I8)) { emit_i8_type(); } else if(match(TOKEN_TYPE_U16)) { emit_u16_type(); } else if(match(TOKEN_TYPE_I16)) { emit_i16_type(); } else if(match(TOKEN_IDENTIFIER)) { /** * maybe a Plex? * lookup plex defs * if not then */ } statement(); } static void statement() { if(match(TOKEN_KEYWORD_PRINT)) emit_print(); else expression(); } static void grouping() { emit_open_paren(); expression(); emit_close_paren(); consume(TOKEN_RPAREN); } static void number() { emit_int(parser.previous.start, parser.previous.length); } static void string() { emit_str(parser.previous.start, parser.previous.length); } static void unary() { TokenType operatorType = parser.previous.type; switch(operatorType) { case TOKEN_MINUS: emit_neg(); break; case TOKEN_BANG: emit_not(); break; default: return; } /* Move to above switch statement for postfix */ parse_precedence(PREC_UNARY); } ParseRule rules[] = { /* 0 */ {NULL, NULL, PREC_NONE}, /* 1 */ {NULL, NULL, PREC_NONE}, /* 2 */ {NULL, NULL, PREC_NONE}, /* 3 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_INT */ /* 4 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_NAT */ /* 5 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_REAL */ /* 6 */ {string, NULL, PREC_NONE}, /* TOKEN_LITERAL_STR */ /* 7 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_I8 */ /* 8 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_I16 */ /* 9 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_INT */ /*10 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_U8 */ /*11 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_U16 */ /*12 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_NAT */ /*13 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_REAL */ /*14 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_STR */ /*15 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_BOOL */ /*16 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_BYTE */ /*17 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_VOID */ /*18 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_PTR */ /*19 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_PLEX */ /*20 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_FN */ /*21 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_CONST */ /*22 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_IF */ /*23 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_IS */ /*24 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_AS */ /*25 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_ELSE */ /*26 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_WHILE */ /*27 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_FOR */ /*28 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_RETURN */ /*29 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_USE */ /*30 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_INIT */ /*31 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_THIS */ /*32 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_GLOBAL */ /*33 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_OPEN */ /*34 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_READ */ /*35 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_WRITE */ /*36 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_STAT */ /*37 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_CLOSE */ /*38 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_LOOP */ /*39 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_DO */ /*40 */ {literal, NULL, PREC_NONE}, /* TOKEN_KEYWORD_NIL */ /*41 */ {literal, NULL, PREC_NONE}, /* TOKEN_KEYWORD_TRUE */ /*42 */ {literal, NULL, PREC_NONE}, /* TOKEN_KEYWORD_FALSE */ /*43 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_PRINT */ /*44 */ {NULL, NULL, PREC_NONE}, /* TOKEN_OPERATOR_NOT */ /*45 */ {NULL, NULL, PREC_NONE}, /* TOKEN_OPERATOR_AND */ /*46 */ {NULL, NULL, PREC_NONE}, /* TOKEN_OPERATOR_OR */ /*47 */ {unary, NULL, PREC_NONE}, /* TOKEN_BANG */ /*48 */ {NULL, binary, PREC_EQUALITY}, /* TOKEN_BANG_EQ */ /*49 */ {NULL, NULL, PREC_NONE}, /* TOKEN_EQ */ /*50 */ {NULL, binary, PREC_EQUALITY}, /* TOKEN_EQ_EQ */ /*51 */ {NULL, NULL, PREC_NONE}, /* TOKEN_AND */ /*52 */ {NULL, NULL, PREC_NONE}, /* TOKEN_AND_AND */ /*53 */ {NULL, NULL, PREC_NONE}, /* TOKEN_PIPE */ /*54 */ {NULL, NULL, PREC_NONE}, /* TOKEN_PIPE_PIPE */ /*55 */ {NULL, NULL, PREC_NONE}, /* TOKEN_QUESTION */ /*56 */ {NULL, NULL, PREC_NONE}, /* TOKEN_QUESTION_DOT */ /*57 */ {NULL, binary, PREC_TERM}, /* TOKEN_PLUS */ /*58 */ {unary, binary, PREC_TERM}, /* TOKEN_MINUS */ /*59 */ {NULL, binary, PREC_FACTOR}, /* TOKEN_STAR */ /*60 */ {NULL, binary, PREC_FACTOR}, /* TOKEN_SLASH */ /*61 */ {NULL, NULL, PREC_NONE}, /* TOKEN_MESH */ /*62 */ {NULL, NULL, PREC_NONE}, /* TOKEN_BIG_MONEY */ /*63 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_GT */ /*64 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_LT */ /*65 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_GTE */ /*66 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_LTE */ /*67 */ {NULL, NULL, PREC_NONE}, /* TOKEN_DOT */ /*68 */ {NULL, NULL, PREC_NONE}, /* TOKEN_COMMA */ /*69 */ {NULL, NULL, PREC_NONE}, /* TOKEN_COLON */ /*70 */ {NULL, NULL, PREC_NONE}, /* TOKEN_CARET */ /*71 */ {NULL, NULL, PREC_NONE}, /* TOKEN_SEMICOLON */ /*72 */ {grouping, NULL, PREC_NONE}, /* TOKEN_LPAREN */ /*73 */ {NULL, NULL, PREC_NONE}, /* TOKEN_RPAREN */ /*74 */ {NULL, NULL, PREC_NONE}, /* TOKEN_LBRACE */ /*75 */ {NULL, NULL, PREC_NONE}, /* TOKEN_RBRACE */ /*76 */ {NULL, NULL, PREC_NONE}, /* TOKEN_LBRACKET */ /*77 */ {NULL, NULL, PREC_NONE}, /* TOKEN_RBRACKET */ /*78 */ {NULL, NULL, PREC_NONE} /* TOKEN_ARROW_RIGHT */ }; static void parse_precedence(Precedence precedence) { ParseFn prefixRule; ParseFn infixRule; advance(); prefixRule = get_rule(parser.previous.type)->prefix; if(prefixRule == NULL) { return; } prefixRule(); while(precedence <= get_rule(parser.current.type)->precedence) { advance(); infixRule = get_rule(parser.previous.type)->infix; infixRule(); } } static ParseRule * get_rule(TokenType type) { return &rules[type]; } bool compile(char *source) { init_lexer(source); advance(); prolog(); while(!match(TOKEN_EOF)) declaration(); epilogue(); return true; }