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] == '}') {
|
} else if(buf[0] == '}') {
|
||||||
vec_Token_push(&tokens, (Token) {.type = TOK_SQUIGGLY_R});
|
vec_Token_push(&tokens, (Token) {.type = TOK_SQUIGGLY_R});
|
||||||
buf++, len--;
|
buf++, len--;
|
||||||
|
} else if(buf[0] == '#') {
|
||||||
|
vec_Token_push(&tokens, (Token) {.type = TOK_SHARP});
|
||||||
|
buf++, len--;
|
||||||
} else if(len > 1 && buf[0] == '~' && buf[1] == '=') {
|
} else if(len > 1 && buf[0] == '~' && buf[1] == '=') {
|
||||||
vec_Token_push(&tokens, (Token) {.type = TOK_NOT_EQUAL});
|
vec_Token_push(&tokens, (Token) {.type = TOK_NOT_EQUAL});
|
||||||
buf++, len--;
|
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});
|
vec_Token_push(&tokens, (Token) {.text = strndup(buf, idlen), .type = TOK_NUMBER});
|
||||||
|
|
||||||
buf += idlen, len -= idlen;
|
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] == '\"') {
|
} else if(buf[0] == '\'' || buf[0] == '\"') {
|
||||||
bool single = buf[0] == '\'';
|
bool single = buf[0] == '\'';
|
||||||
|
|
||||||
|
137
parse.c
137
parse.c
@ -92,9 +92,12 @@ typedef enum ExprKind {
|
|||||||
EX_EQ,
|
EX_EQ,
|
||||||
EX_NEQ,
|
EX_NEQ,
|
||||||
EX_TBL_LIT,
|
EX_TBL_LIT,
|
||||||
|
EX_FUNC_LIT,
|
||||||
|
EX_DOT,
|
||||||
EX_INDEX,
|
EX_INDEX,
|
||||||
EX_CALL,
|
EX_CALL,
|
||||||
EX_STR,
|
EX_STR,
|
||||||
|
EX_LENGTH,
|
||||||
} ExprKind;
|
} ExprKind;
|
||||||
typedef struct Expr {
|
typedef struct Expr {
|
||||||
ExprKind kind;
|
ExprKind kind;
|
||||||
@ -414,7 +417,11 @@ Expr *desc_subexp(Parser *P, int priority) {
|
|||||||
} else if(priority == 3) {
|
} else if(priority == 3) {
|
||||||
Expr *e = NULL;
|
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 = new_expr(0);
|
||||||
e->kind = EX_BOOL;
|
e->kind = EX_BOOL;
|
||||||
e->b = true;
|
e->b = true;
|
||||||
@ -449,6 +456,25 @@ Expr *desc_subexp(Parser *P, int priority) {
|
|||||||
e = new_expr(0);
|
e = new_expr(0);
|
||||||
e->kind = EX_STR;
|
e->kind = EX_STR;
|
||||||
e->name = 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)) {
|
} else if(maybe(P, TOK_SQUIGGLY_L)) {
|
||||||
e = new_expr(0);
|
e = new_expr(0);
|
||||||
e->kind = EX_TBL_LIT;
|
e->kind = EX_TBL_LIT;
|
||||||
@ -471,7 +497,7 @@ Expr *desc_subexp(Parser *P, int priority) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(e) {
|
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) {
|
if(peek(P, -1).type == TOK_PAREN_L) {
|
||||||
Expr *call = new_expr(sizeof(Expr*) + sizeof(Expr*) * 32);
|
Expr *call = new_expr(sizeof(Expr*) + sizeof(Expr*) * 32);
|
||||||
call->kind = EX_CALL;
|
call->kind = EX_CALL;
|
||||||
@ -493,11 +519,20 @@ Expr *desc_subexp(Parser *P, int priority) {
|
|||||||
e = call;
|
e = call;
|
||||||
} else if(peek(P, -1).type == TOK_DOT) {
|
} else if(peek(P, -1).type == TOK_DOT) {
|
||||||
Expr *dot = new_expr(0);
|
Expr *dot = new_expr(0);
|
||||||
dot->kind = EX_INDEX;
|
dot->kind = EX_DOT;
|
||||||
dot->A = e;
|
dot->A = e;
|
||||||
dot->B_tok = expect(P, TOK_NAME);
|
dot->B_tok = expect(P, TOK_NAME);
|
||||||
|
|
||||||
e = dot;
|
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++) {
|
for(size_t i = 1; i < expr->sub_count; i++) {
|
||||||
int av = find_vreg(P);
|
int av = find_vreg(P);
|
||||||
emit_expr(P, av, expr->subs[i++]);
|
emit_expr(P, av, expr->subs[i]);
|
||||||
args[(*arg_count)++] = av;
|
args[(*arg_count)++] = av;
|
||||||
alloc_vreg(P, 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)});
|
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) {
|
} else if(expr->kind == EX_TBL_LIT) {
|
||||||
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_SETTABLE, .a = assigned_vreg, .bc = 16});
|
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;
|
P->i = expr->table_first_token;
|
||||||
|
|
||||||
expect(P, TOK_SQUIGGLY_L);
|
expect(P, TOK_SQUIGGLY_L);
|
||||||
|
|
||||||
|
alloc_vreg(P, assigned_vreg);
|
||||||
|
|
||||||
if(!maybe(P, TOK_SQUIGGLY_R)) {
|
if(!maybe(P, TOK_SQUIGGLY_R)) {
|
||||||
while(1) {
|
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;
|
P->i = old_idx;
|
||||||
} else if(expr->kind == EX_INDEX) {
|
} else if(expr->kind == EX_DOT) {
|
||||||
Token field = expr->B_tok;
|
Token field = expr->B_tok;
|
||||||
|
|
||||||
emit_expr(P, assigned_vreg, expr->A);
|
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});
|
vec_LInst_push(&P->current_chunk.instrs, (LInst) {.opcode = L_GETFIELD, .a = assigned_vreg, .b = assigned_vreg, .c = keyv});
|
||||||
|
|
||||||
free_vreg(P, assigned_vreg);
|
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 {
|
} 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);
|
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;
|
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;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -841,6 +953,19 @@ bool parse_assignment(Parser *P) {
|
|||||||
emit_expr(P, lhsv, lhs[i]->A);
|
emit_expr(P, lhsv, lhs[i]->A);
|
||||||
alloc_vreg(P, lhsv);
|
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;
|
Token field = lhs[i]->B_tok;
|
||||||
|
|
||||||
size_t abyss_idx = abyss_insert(P, NULL, sizeof(uint16_t) + strlen(field.text));
|
size_t abyss_idx = abyss_insert(P, NULL, sizeof(uint16_t) + strlen(field.text));
|
||||||
|
Loading…
Reference in New Issue
Block a user