more expression types
This commit is contained in:
parent
6b2b8944eb
commit
a29b250f30
11
lexer.c
11
lexer.c
@ -99,6 +99,9 @@ vec_Token ltokenize(const char *buf, size_t len) {
|
||||
} else if(buf[0] == '}') {
|
||||
vec_Token_push(&tokens, (Token) {.type = TOK_SQUIGGLY_R});
|
||||
buf++, len--;
|
||||
} else if(buf[0] == '#') {
|
||||
vec_Token_push(&tokens, (Token) {.type = TOK_SHARP});
|
||||
buf++, len--;
|
||||
} else if(len > 1 && buf[0] == '~' && buf[1] == '=') {
|
||||
vec_Token_push(&tokens, (Token) {.type = TOK_NOT_EQUAL});
|
||||
buf++, len--;
|
||||
@ -116,6 +119,14 @@ vec_Token ltokenize(const char *buf, size_t len) {
|
||||
vec_Token_push(&tokens, (Token) {.text = strndup(buf, idlen), .type = TOK_NUMBER});
|
||||
|
||||
buf += idlen, len -= idlen;
|
||||
} else if(buf[0] == '-' && (len == 1 || buf[1] != '-')) {
|
||||
vec_Token_push(&tokens, (Token) {.type = TOK_MINUS});
|
||||
buf++, len--;
|
||||
} else if(len >= 2 && buf[0] == '-' && buf[1] == '-') {
|
||||
while(*buf != '\n') {
|
||||
buf++, len--;
|
||||
}
|
||||
row++;
|
||||
} else if(buf[0] == '\'' || buf[0] == '\"') {
|
||||
bool single = buf[0] == '\'';
|
||||
|
||||
|
137
parse.c
137
parse.c
@ -92,9 +92,12 @@ typedef enum ExprKind {
|
||||
EX_EQ,
|
||||
EX_NEQ,
|
||||
EX_TBL_LIT,
|
||||
EX_FUNC_LIT,
|
||||
EX_DOT,
|
||||
EX_INDEX,
|
||||
EX_CALL,
|
||||
EX_STR,
|
||||
EX_LENGTH,
|
||||
} ExprKind;
|
||||
typedef struct Expr {
|
||||
ExprKind kind;
|
||||
@ -414,7 +417,11 @@ Expr *desc_subexp(Parser *P, int priority) {
|
||||
} else if(priority == 3) {
|
||||
Expr *e = NULL;
|
||||
|
||||
if(maybe(P, TOK_TRUE)) {
|
||||
if(maybe(P, TOK_SHARP)) {
|
||||
e = new_expr(0);
|
||||
e->kind = EX_LENGTH;
|
||||
e->A = desc_subexp(P, priority);
|
||||
} else if(maybe(P, TOK_TRUE)) {
|
||||
e = new_expr(0);
|
||||
e->kind = EX_BOOL;
|
||||
e->b = true;
|
||||
@ -449,6 +456,25 @@ Expr *desc_subexp(Parser *P, int priority) {
|
||||
e = new_expr(0);
|
||||
e->kind = EX_STR;
|
||||
e->name = str;
|
||||
} else if(maybe(P, TOK_FUNCTION)) {
|
||||
e = new_expr(0);
|
||||
e->kind = EX_FUNC_LIT;
|
||||
e->table_first_token = P->i - 1;
|
||||
|
||||
size_t depth = 1;
|
||||
while(1) {
|
||||
Token t = get(P);
|
||||
if(t.type == TOK_THEN || t.type == TOK_DO) {
|
||||
depth++;
|
||||
} else if(t.type == TOK_END) {
|
||||
depth--;
|
||||
if(depth == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e->table_last_token = P->i - 1;
|
||||
} else if(maybe(P, TOK_SQUIGGLY_L)) {
|
||||
e = new_expr(0);
|
||||
e->kind = EX_TBL_LIT;
|
||||
@ -471,7 +497,7 @@ Expr *desc_subexp(Parser *P, int priority) {
|
||||
}
|
||||
|
||||
if(e) {
|
||||
while(maybe(P, TOK_PAREN_L) || maybe(P, TOK_DOT)) {
|
||||
while(maybe(P, TOK_PAREN_L) || maybe(P, TOK_DOT) || maybe(P, TOK_SQUAREN_L)) {
|
||||
if(peek(P, -1).type == TOK_PAREN_L) {
|
||||
Expr *call = new_expr(sizeof(Expr*) + sizeof(Expr*) * 32);
|
||||
call->kind = EX_CALL;
|
||||
@ -493,11 +519,20 @@ Expr *desc_subexp(Parser *P, int priority) {
|
||||
e = call;
|
||||
} else if(peek(P, -1).type == TOK_DOT) {
|
||||
Expr *dot = new_expr(0);
|
||||
dot->kind = EX_INDEX;
|
||||
dot->kind = EX_DOT;
|
||||
dot->A = e;
|
||||
dot->B_tok = expect(P, TOK_NAME);
|
||||
|
||||
e = dot;
|
||||
} else if(peek(P, -1).type == TOK_SQUAREN_L) {
|
||||
Expr *index = new_expr(0);
|
||||
index->kind = EX_INDEX;
|
||||
index->A = e;
|
||||
index->B = desc_exp(P);
|
||||
|
||||
expect(P, TOK_SQUAREN_R);
|
||||
|
||||
e = index;
|
||||
}
|
||||
}
|
||||
|
||||
@ -654,7 +689,7 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) {
|
||||
|
||||
for(size_t i = 1; i < expr->sub_count; i++) {
|
||||
int av = find_vreg(P);
|
||||
emit_expr(P, av, expr->subs[i++]);
|
||||
emit_expr(P, av, expr->subs[i]);
|
||||
args[(*arg_count)++] = av;
|
||||
alloc_vreg(P, av);
|
||||
}
|
||||
@ -667,6 +702,66 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) {
|
||||
}
|
||||
|
||||
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_CALL, .a = vreg, .bc = abyss_insert(P, buf, 2 + *arg_count)});
|
||||
} else if(expr->kind == EX_FUNC_LIT) {
|
||||
size_t old_idx = P->i;
|
||||
|
||||
P->i = expr->table_first_token;
|
||||
|
||||
expect(P, TOK_FUNCTION);
|
||||
|
||||
expect(P, TOK_PAREN_L);
|
||||
|
||||
Chunk old_chunk = P->current_chunk;
|
||||
P->current_chunk = (Chunk) {};
|
||||
|
||||
Scope *new_scope = calloc(1, sizeof(*new_scope));
|
||||
new_scope->parent = P->scope;
|
||||
P->scope = new_scope;
|
||||
|
||||
size_t arg_count = 0;
|
||||
if(!maybe(P, TOK_PAREN_R)) {
|
||||
while(1) {
|
||||
expect(P, TOK_NAME);
|
||||
|
||||
P->i--;
|
||||
|
||||
ScopeItem *si = calloc(1, sizeof(*si));
|
||||
si->name = expect(P, TOK_NAME);
|
||||
si->vreg = arg_count++;
|
||||
scope_set_direct(P->scope, si);
|
||||
|
||||
if(maybe(P, TOK_PAREN_R)) {
|
||||
break;
|
||||
} else {
|
||||
expect(P, TOK_COMMA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parse_chunk(P);
|
||||
if(P->current_chunk.instrs.data[P->current_chunk.instrs.size - 1].opcode != L_RET) {
|
||||
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_RET, .argb = {0}});
|
||||
}
|
||||
|
||||
expect(P, TOK_END);
|
||||
|
||||
assert(P->unit_functions.size > 0);
|
||||
|
||||
LFunc lf = {};
|
||||
lf.unit = P->unit_functions.data[0].unit;
|
||||
lf.is_native = false;
|
||||
lf.lua_instrs = P->current_chunk.instrs.data;
|
||||
lf.env = P->environment;
|
||||
vec_LFunc_push(&P->unit_functions, lf);
|
||||
|
||||
size_t function_idx = P->unit_functions.size - 1;
|
||||
|
||||
P->current_chunk = old_chunk;
|
||||
scope_kill(P);
|
||||
|
||||
P->i = old_idx;
|
||||
|
||||
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_SETFUNC, .a = assigned_vreg, .bc = function_idx});
|
||||
} else if(expr->kind == EX_TBL_LIT) {
|
||||
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_SETTABLE, .a = assigned_vreg, .bc = 16});
|
||||
|
||||
@ -674,6 +769,8 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) {
|
||||
P->i = expr->table_first_token;
|
||||
|
||||
expect(P, TOK_SQUIGGLY_L);
|
||||
|
||||
alloc_vreg(P, assigned_vreg);
|
||||
|
||||
if(!maybe(P, TOK_SQUIGGLY_R)) {
|
||||
while(1) {
|
||||
@ -709,9 +806,11 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_vreg(P, assigned_vreg);
|
||||
|
||||
P->i = old_idx;
|
||||
} else if(expr->kind == EX_INDEX) {
|
||||
} else if(expr->kind == EX_DOT) {
|
||||
Token field = expr->B_tok;
|
||||
|
||||
emit_expr(P, assigned_vreg, expr->A);
|
||||
@ -728,6 +827,19 @@ void emit_expr(Parser *P, int assigned_vreg, Expr *expr) {
|
||||
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_GETFIELD, .a = assigned_vreg, .b = assigned_vreg, .c = keyv});
|
||||
|
||||
free_vreg(P, assigned_vreg);
|
||||
} else if(expr->kind == EX_INDEX) {
|
||||
emit_expr(P, assigned_vreg, expr->A);
|
||||
|
||||
alloc_vreg(P, assigned_vreg);
|
||||
int keyv = find_vreg(P);
|
||||
emit_expr(P, keyv, expr->B);
|
||||
free_vreg(P, assigned_vreg);
|
||||
|
||||
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_GETFIELD, .a = assigned_vreg, .b = assigned_vreg, .c = keyv});
|
||||
} else if(expr->kind == EX_LENGTH) {
|
||||
emit_expr(P, assigned_vreg, expr->A);
|
||||
|
||||
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_LEN, .a = assigned_vreg, .b = assigned_vreg, .c = 0});
|
||||
} else {
|
||||
assert(expr->kind == EX_ADD || expr->kind == EX_SUB || expr->kind == EX_MUL || expr->kind == EX_DIV || expr->kind == EX_IDIV || expr->kind == EX_MOD || expr->kind == EX_POW || expr->kind == EX_BAND || expr->kind == EX_BOR || expr->kind == EX_BXOR || expr->kind == EX_AND || expr->kind == EX_OR || expr->kind == EX_EQ || expr->kind == EX_NEQ);
|
||||
|
||||
@ -796,7 +908,7 @@ bool parse_assignment(Parser *P) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(lhs[lhsi - 1]->kind != EX_LOCAL && lhs[lhsi - 1]->kind != EX_GLOBAL && lhs[lhsi - 1]->kind != EX_INDEX) {
|
||||
if(lhs[lhsi - 1]->kind != EX_LOCAL && lhs[lhsi - 1]->kind != EX_GLOBAL && lhs[lhsi - 1]->kind != EX_DOT && lhs[lhsi - 1]->kind != EX_INDEX) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -841,6 +953,19 @@ bool parse_assignment(Parser *P) {
|
||||
emit_expr(P, lhsv, lhs[i]->A);
|
||||
alloc_vreg(P, lhsv);
|
||||
|
||||
int keyv = find_vreg(P);
|
||||
assert(keyv != -1);
|
||||
emit_expr(P, keyv, lhs[i]->B);
|
||||
|
||||
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_SETFIELD, .a = lhsv, .b = keyv, .c = rhsv[i]});
|
||||
|
||||
free_vreg(P, lhsv);
|
||||
} else if(lhs[i]->kind == EX_DOT) {
|
||||
int lhsv = find_vreg(P);
|
||||
assert(lhsv != -1);
|
||||
emit_expr(P, lhsv, lhs[i]->A);
|
||||
alloc_vreg(P, lhsv);
|
||||
|
||||
Token field = lhs[i]->B_tok;
|
||||
|
||||
size_t abyss_idx = abyss_insert(P, NULL, sizeof(uint16_t) + strlen(field.text));
|
||||
|
Loading…
Reference in New Issue
Block a user