undar-lang/parser.c

391 lines
9.6 KiB
C

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