Compare commits
No commits in common. "74e5f5225d6203fa6965bb49af3c50ef7c302986" and "441acdeea2e29b8df598408a3405a8866ded2130" have entirely different histories.
74e5f5225d
...
441acdeea2
|
@ -2,16 +2,6 @@ ROOT ::= EXPR*
|
||||||
EXPR ::=
|
EXPR ::=
|
||||||
| OR
|
| OR
|
||||||
| ASSERT
|
| ASSERT
|
||||||
| VAR_DECL
|
|
||||||
| CONST_DECL
|
|
||||||
| ASSIGN
|
|
||||||
| BLOCK
|
|
||||||
| IF
|
|
||||||
IF ::= if EXPR BLOCK (else (BLOCK | IF))?
|
|
||||||
BLOCK ::= begin EXPR* end
|
|
||||||
ASSIGN ::= ident assign EXPR
|
|
||||||
VAR_DECL ::= var ident assign EXPR
|
|
||||||
CONST_DECL ::= const ident assign EXPR
|
|
||||||
ASSERT ::= assert EXPR eq EXPR
|
ASSERT ::= assert EXPR eq EXPR
|
||||||
OR ::= AND (or AND)*
|
OR ::= AND (or AND)*
|
||||||
AND ::= EQ (and EQ)*
|
AND ::= EQ (and EQ)*
|
||||||
|
@ -25,7 +15,6 @@ POW ::= LITERAL (pow LITERAL)?
|
||||||
LITERAL ::=
|
LITERAL ::=
|
||||||
| BUILTIN
|
| BUILTIN
|
||||||
| opar EXPR cpar
|
| opar EXPR cpar
|
||||||
| ident
|
|
||||||
BUILTIN ::=
|
BUILTIN ::=
|
||||||
| int
|
| int
|
||||||
| bool
|
| bool
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
var a = 4
|
|
||||||
|
|
||||||
if true
|
|
||||||
a = 5
|
|
||||||
end
|
|
||||||
|
|
||||||
assert a eq 5
|
|
||||||
|
|
||||||
if false
|
|
||||||
a = 12
|
|
||||||
end
|
|
||||||
|
|
||||||
assert a eq 5
|
|
||||||
|
|
||||||
if true
|
|
||||||
a = 1
|
|
||||||
else if true
|
|
||||||
a = 2
|
|
||||||
else if true
|
|
||||||
a = 3
|
|
||||||
else
|
|
||||||
a = 4
|
|
||||||
end
|
|
||||||
|
|
||||||
assert a eq 1
|
|
||||||
|
|
||||||
if false
|
|
||||||
a = 1
|
|
||||||
else if true
|
|
||||||
a = 2
|
|
||||||
else if true
|
|
||||||
a = 3
|
|
||||||
else
|
|
||||||
a = 4
|
|
||||||
end
|
|
||||||
|
|
||||||
assert a eq 2
|
|
||||||
|
|
||||||
if false
|
|
||||||
a = 1
|
|
||||||
else if false
|
|
||||||
a = 2
|
|
||||||
else if true
|
|
||||||
a = 3
|
|
||||||
else
|
|
||||||
a = 4
|
|
||||||
end
|
|
||||||
|
|
||||||
assert a eq 3
|
|
||||||
|
|
||||||
if false
|
|
||||||
a = 1
|
|
||||||
else if false
|
|
||||||
a = 2
|
|
||||||
else if false
|
|
||||||
a = 3
|
|
||||||
else
|
|
||||||
a = 4
|
|
||||||
end
|
|
||||||
|
|
||||||
assert a eq 4
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
var a = 32
|
|
||||||
assert a eq 32
|
|
||||||
|
|
||||||
a = 7
|
|
||||||
2
|
|
||||||
assert a eq 7
|
|
||||||
|
|
||||||
a = a + 1
|
|
||||||
assert a eq 8
|
|
||||||
|
|
||||||
begin
|
|
||||||
assert a eq 8
|
|
||||||
a = 9
|
|
||||||
var a = "hop"
|
|
||||||
assert a eq "hop"
|
|
||||||
a = 27
|
|
||||||
assert a eq 27
|
|
||||||
end
|
|
||||||
|
|
||||||
assert a eq 9
|
|
|
@ -22,8 +22,6 @@ add_library(skopy-lib SHARED
|
||||||
src/module.c
|
src/module.c
|
||||||
|
|
||||||
src/errors.c
|
src/errors.c
|
||||||
|
|
||||||
src/sym.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
file(GLOB_RECURSE
|
file(GLOB_RECURSE
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "prog.h"
|
#include "prog.h"
|
||||||
#include "sym.h"
|
|
||||||
|
|
||||||
struct compiler
|
struct compiler
|
||||||
{
|
{
|
||||||
|
@ -14,13 +13,11 @@ void compiler_free(struct compiler* self);
|
||||||
|
|
||||||
void compiler_compile(struct compiler* self,
|
void compiler_compile(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct prog* prog,
|
struct prog* prog);
|
||||||
struct sym* sym);
|
|
||||||
|
|
||||||
void compiler_compile_children(struct compiler* self,
|
void compiler_compile_children(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct prog* prog,
|
struct prog* prog);
|
||||||
struct sym* sym);
|
|
||||||
|
|
||||||
void compiler_compile_value(struct compiler* self,
|
void compiler_compile_value(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
|
@ -30,18 +27,10 @@ void compiler_compile_value(struct compiler* self,
|
||||||
|
|
||||||
void compiler_compile_and(struct compiler* self,
|
void compiler_compile_and(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct prog* prog,
|
struct prog* prog);
|
||||||
struct sym* sym);
|
|
||||||
|
|
||||||
void compiler_compile_or(struct compiler* self,
|
void compiler_compile_or(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct prog* prog,
|
struct prog* prog);
|
||||||
struct sym* sym);
|
|
||||||
|
|
||||||
void compiler_compile_if(struct compiler* self,
|
|
||||||
struct node* node,
|
|
||||||
struct prog* prog,
|
|
||||||
struct sym* sym,
|
|
||||||
struct vec* to_end);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -26,15 +26,12 @@ void lexer_skip_comments(struct lexer* self);
|
||||||
bool lexer_is_sep(struct lexer* self, size_t index);
|
bool lexer_is_sep(struct lexer* self, size_t index);
|
||||||
|
|
||||||
bool lexer_next_is(struct lexer* self, TokenKind kind);
|
bool lexer_next_is(struct lexer* self, TokenKind kind);
|
||||||
bool lexer_next_nth_is(struct lexer* self, TokenKind kind, int nth);
|
|
||||||
|
|
||||||
void lexer_consume_next(struct lexer* self);
|
void lexer_consume_next(struct lexer* self);
|
||||||
struct token* lexer_try_new_next(struct lexer* self);
|
struct token* lexer_try_new_next(struct lexer* self);
|
||||||
struct token* lexer_try_scan_int(struct lexer* self);
|
struct token* lexer_try_scan_int(struct lexer* self);
|
||||||
struct token* lexer_try_scan_float(struct lexer* self);
|
struct token* lexer_try_scan_float(struct lexer* self);
|
||||||
struct token* lexer_try_scan_string(struct lexer* self);
|
struct token* lexer_try_scan_string(struct lexer* self);
|
||||||
struct token* lexer_try_scan_ident(struct lexer* self);
|
|
||||||
bool lexer_is_ident(struct lexer* self, size_t index);
|
|
||||||
struct token* lexer_try_scan_text(struct lexer* self,
|
struct token* lexer_try_scan_text(struct lexer* self,
|
||||||
char const* text,
|
char const* text,
|
||||||
TokenKind kind);
|
TokenKind kind);
|
||||||
|
|
|
@ -3,13 +3,11 @@
|
||||||
|
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "prog.h"
|
#include "prog.h"
|
||||||
#include "sym.h"
|
|
||||||
|
|
||||||
struct module
|
struct module
|
||||||
{
|
{
|
||||||
struct str source;
|
struct str source;
|
||||||
struct prog prog;
|
struct prog prog;
|
||||||
struct sym sym;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void module_init(struct module* self);
|
void module_init(struct module* self);
|
||||||
|
|
|
@ -12,9 +12,7 @@ G(NODE_USUB), G(NODE_ASSERT_EQ), \
|
||||||
G(NODE_BOOL), G(NODE_AND), G(NODE_OR), \
|
G(NODE_BOOL), G(NODE_AND), G(NODE_OR), \
|
||||||
G(NODE_NOT), G(NODE_FLOAT), G(NODE_STRING), \
|
G(NODE_NOT), G(NODE_FLOAT), G(NODE_STRING), \
|
||||||
G(NODE_LT), G(NODE_LE), G(NODE_GT), G(NODE_GE), \
|
G(NODE_LT), G(NODE_LE), G(NODE_GT), G(NODE_GE), \
|
||||||
G(NODE_EQUAL), G(NODE_NOT_EQUAL), G(NODE_VAR_DECL), \
|
G(NODE_EQUAL), G(NODE_NOT_EQUAL)
|
||||||
G(NODE_CONST_DECL), G(NODE_IDENT), G(NODE_ASSIGN), \
|
|
||||||
G(NODE_BLOCK), G(NODE_IF)
|
|
||||||
|
|
||||||
SK_ENUM_H(NodeKind, NODE_KIND);
|
SK_ENUM_H(NodeKind, NODE_KIND);
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,6 @@ struct node* parser_try(struct parser* self,
|
||||||
struct node* parser_try_parse(struct parser* self);
|
struct node* parser_try_parse(struct parser* self);
|
||||||
struct node* parser_try_root(struct parser* self);
|
struct node* parser_try_root(struct parser* self);
|
||||||
struct node* parser_try_expr(struct parser* self);
|
struct node* parser_try_expr(struct parser* self);
|
||||||
struct node* parser_try_block(struct parser* self);
|
|
||||||
struct node* parser_try_inner_block(struct parser* self);
|
|
||||||
struct node* parser_try_if(struct parser* self);
|
|
||||||
struct node* parser_try_assign(struct parser* self);
|
|
||||||
struct node* parser_try_var_decl(struct parser* self);
|
|
||||||
struct node* parser_try_const_decl(struct parser* self);
|
|
||||||
struct node* parser_try_assert(struct parser* self);
|
struct node* parser_try_assert(struct parser* self);
|
||||||
struct node* parser_try_or(struct parser* self);
|
struct node* parser_try_or(struct parser* self);
|
||||||
struct node* parser_try_and(struct parser* self);
|
struct node* parser_try_and(struct parser* self);
|
||||||
|
|
|
@ -12,7 +12,7 @@ G(OP_DIV), G(OP_MOD), G(OP_POW), \
|
||||||
G(OP_USUB), G(OP_ASSERT_EQ), \
|
G(OP_USUB), G(OP_ASSERT_EQ), \
|
||||||
G(OP_NOT), G(OP_AND), G(OP_OR), \
|
G(OP_NOT), G(OP_AND), G(OP_OR), \
|
||||||
G(OP_BR), G(OP_BRF), G(OP_LT), G(OP_GT), \
|
G(OP_BR), G(OP_BRF), G(OP_LT), G(OP_GT), \
|
||||||
G(OP_EQUAL), G(OP_LOCAL_STORE), G(OP_LOCAL_LOAD)
|
G(OP_EQUAL)
|
||||||
|
|
||||||
SK_ENUM_H(Opcode, OPCODE);
|
SK_ENUM_H(Opcode, OPCODE);
|
||||||
|
|
||||||
|
|
|
@ -3,17 +3,9 @@
|
||||||
|
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
|
||||||
#define SK size_t
|
#define SK size_t
|
||||||
#define SK_NO_ID (-1)
|
|
||||||
|
|
||||||
struct local
|
struct local
|
||||||
{
|
|
||||||
int id;
|
|
||||||
size_t addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stack_value
|
|
||||||
{
|
{
|
||||||
size_t addr;
|
size_t addr;
|
||||||
struct value* value;
|
struct value* value;
|
||||||
|
@ -21,7 +13,6 @@ struct stack_value
|
||||||
|
|
||||||
struct frame
|
struct frame
|
||||||
{
|
{
|
||||||
struct vec stack_values;
|
|
||||||
struct vec locals;
|
struct vec locals;
|
||||||
struct vec stack;
|
struct vec stack;
|
||||||
};
|
};
|
||||||
|
@ -32,11 +23,11 @@ struct state
|
||||||
size_t addr;
|
size_t addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
void stack_value_init(struct stack_value* self,
|
void local_init(struct local* self,
|
||||||
size_t addr,
|
size_t addr,
|
||||||
struct value* new_value);
|
struct value* new_value);
|
||||||
|
|
||||||
void stack_value_free(struct stack_value* self);
|
void local_free(struct local* self);
|
||||||
|
|
||||||
void frame_init(struct frame* self);
|
void frame_init(struct frame* self);
|
||||||
void frame_free(struct frame* self);
|
void frame_free(struct frame* self);
|
||||||
|
@ -53,9 +44,9 @@ struct value* state_try_get_value(struct state* self, SK value);
|
||||||
|
|
||||||
SK state_pop(struct state* self);
|
SK state_pop(struct state* self);
|
||||||
|
|
||||||
SK state_push(struct state* self,
|
SK state_push(struct state* self,
|
||||||
TypeKind type,
|
TypeKind type,
|
||||||
union val val,
|
union val val,
|
||||||
int line);
|
int line);
|
||||||
|
|
||||||
SK state_push_int(struct state* self, int integer, int line);
|
SK state_push_int(struct state* self, int integer, int line);
|
||||||
|
@ -63,14 +54,6 @@ SK state_push_bool(struct state* self, bool boolean, int line);
|
||||||
SK state_push_float(struct state* self, double real, int line);
|
SK state_push_float(struct state* self, double real, int line);
|
||||||
SK state_push_string(struct state* self, char const* str, int line);
|
SK state_push_string(struct state* self, char const* str, int line);
|
||||||
|
|
||||||
struct local* state_try_get_local(struct state* self, int id);
|
|
||||||
|
|
||||||
SK state_local_store(struct state* self,
|
|
||||||
int id);
|
|
||||||
|
|
||||||
void state_local_load(struct state* self,
|
|
||||||
int id);
|
|
||||||
|
|
||||||
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs);
|
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs);
|
||||||
TypeKind state_type(struct state* self, SK value);
|
TypeKind state_type(struct state* self, SK value);
|
||||||
double state_as_real(struct state* self, SK lhs);
|
double state_as_real(struct state* self, SK lhs);
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
#ifndef SK_SYM_H
|
|
||||||
#define SK_SYM_H
|
|
||||||
|
|
||||||
#include "commons.h"
|
|
||||||
|
|
||||||
struct symbol
|
|
||||||
{
|
|
||||||
int id;
|
|
||||||
char* name;
|
|
||||||
bool is_const;
|
|
||||||
struct env* env;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct env
|
|
||||||
{
|
|
||||||
struct vec symbols;
|
|
||||||
struct env* parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sym
|
|
||||||
{
|
|
||||||
int id_counter;
|
|
||||||
struct env* env;
|
|
||||||
};
|
|
||||||
|
|
||||||
void env_init(struct env* self);
|
|
||||||
void env_free(struct env* self);
|
|
||||||
struct symbol* env_try_get(struct env* self, char const* name);
|
|
||||||
|
|
||||||
void symbol_init(struct symbol* self,
|
|
||||||
int id,
|
|
||||||
char const* name,
|
|
||||||
struct env* env);
|
|
||||||
|
|
||||||
void symbol_free(struct symbol* self);
|
|
||||||
|
|
||||||
void sym_init(struct sym* self);
|
|
||||||
void sym_free(struct sym* self);
|
|
||||||
|
|
||||||
int sym_decl_var(struct sym* self, char const* name);
|
|
||||||
int sym_decl_const(struct sym* self, char const* name);
|
|
||||||
|
|
||||||
void sym_open_scope(struct sym* self);
|
|
||||||
void sym_close_scope(struct sym* self);
|
|
||||||
|
|
||||||
struct symbol* sym_try_get(struct sym* self, char const* name);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -13,9 +13,7 @@ G(TOKEN_ASSERT), G(TOKEN_ASSERT_EQ), \
|
||||||
G(TOKEN_BOOL), G(TOKEN_AND), G(TOKEN_OR), \
|
G(TOKEN_BOOL), G(TOKEN_AND), G(TOKEN_OR), \
|
||||||
G(TOKEN_NOT), G(TOKEN_FLOAT), G(TOKEN_STRING), \
|
G(TOKEN_NOT), G(TOKEN_FLOAT), G(TOKEN_STRING), \
|
||||||
G(TOKEN_LT), G(TOKEN_LE), G(TOKEN_GT), G(TOKEN_GE), \
|
G(TOKEN_LT), G(TOKEN_LE), G(TOKEN_GT), G(TOKEN_GE), \
|
||||||
G(TOKEN_EQUAL), G(TOKEN_NOT_EQUAL), G(TOKEN_VAR), \
|
G(TOKEN_EQUAL), G(TOKEN_NOT_EQUAL)
|
||||||
G(TOKEN_CONST), G(TOKEN_ASSIGN), G(TOKEN_IDENT), \
|
|
||||||
G(TOKEN_BEGIN), G(TOKEN_END), G(TOKEN_IF), G(TOKEN_ELSE)
|
|
||||||
|
|
||||||
SK_ENUM_H(TokenKind, TOKEN_KIND);
|
SK_ENUM_H(TokenKind, TOKEN_KIND);
|
||||||
|
|
||||||
|
@ -26,9 +24,9 @@ struct token
|
||||||
int line;
|
int line;
|
||||||
};
|
};
|
||||||
|
|
||||||
void token_init(struct token* self,
|
void token_init(struct token* self,
|
||||||
TokenKind kind,
|
TokenKind kind,
|
||||||
char const* value,
|
char const* value,
|
||||||
int line);
|
int line);
|
||||||
|
|
||||||
void token_free(struct token* self);
|
void token_free(struct token* self);
|
||||||
|
|
|
@ -13,8 +13,7 @@ void compiler_free(struct compiler* self)
|
||||||
|
|
||||||
void compiler_compile(struct compiler* self,
|
void compiler_compile(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct prog* prog,
|
struct prog* prog)
|
||||||
struct sym* sym)
|
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(node);
|
assert(node);
|
||||||
|
@ -26,113 +25,28 @@ void compiler_compile(struct compiler* self,
|
||||||
for (size_t i=0; i<node->children.size; i++)
|
for (size_t i=0; i<node->children.size; i++)
|
||||||
{
|
{
|
||||||
compiler_compile(self, node->children.data[i],
|
compiler_compile(self, node->children.data[i],
|
||||||
prog, sym);
|
prog);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_BLOCK: {
|
|
||||||
sym_open_scope(sym);
|
|
||||||
for (size_t i=0; i<node->children.size; i++)
|
|
||||||
{
|
|
||||||
compiler_compile(self, node->children.data[i],
|
|
||||||
prog, sym);
|
|
||||||
}
|
|
||||||
sym_close_scope(sym);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_IF: {
|
|
||||||
struct vec to_end;
|
|
||||||
vec_init(&to_end);
|
|
||||||
|
|
||||||
compiler_compile_if(self, node, prog, sym, &to_end);
|
|
||||||
size_t end_point = prog->params.size;
|
|
||||||
|
|
||||||
for (size_t i=0; i<to_end.size; i++)
|
|
||||||
{
|
|
||||||
size_t addr = (size_t) to_end.data[i];
|
|
||||||
((size_t*) prog->params.data)[addr] = end_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec_free(&to_end);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_NOT: {
|
case NODE_NOT: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
|
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_AND: {
|
case NODE_AND: {
|
||||||
compiler_compile_and(self, node, prog, sym);
|
compiler_compile_and(self, node, prog);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_OR: {
|
case NODE_OR: {
|
||||||
compiler_compile_or(self, node, prog, sym);
|
compiler_compile_or(self, node, prog);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_ASSERT_EQ: {
|
case NODE_ASSERT_EQ: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_ASSERT_EQ, SK_NO_PARAM);
|
prog_add_instr(prog, OP_ASSERT_EQ, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_VAR_DECL: {
|
|
||||||
struct node* ident = node->children.data[0];
|
|
||||||
struct symbol const* s = sym_try_get(sym, ident->token->value);
|
|
||||||
|
|
||||||
if (s && s->env == sym->env)
|
|
||||||
{
|
|
||||||
errors_push(node->token->line, "'%s' is already defined",
|
|
||||||
ident->token->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* expr = node->children.data[1];
|
|
||||||
compiler_compile(self, expr, prog, sym);
|
|
||||||
int id = sym_decl_var(sym, ident->token->value);
|
|
||||||
prog_add_instr(prog, OP_LOCAL_STORE, id);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_CONST_DECL: {
|
|
||||||
struct node* ident = node->children.data[0];
|
|
||||||
struct symbol const* s = sym_try_get(sym, ident->token->value);
|
|
||||||
if (s && s->env == sym->env)
|
|
||||||
{
|
|
||||||
errors_push(node->token->line, "'%s' is already defined",
|
|
||||||
ident->token->value);
|
|
||||||
}
|
|
||||||
struct node* expr = node->children.data[1];
|
|
||||||
compiler_compile(self, expr, prog, sym);
|
|
||||||
int id = sym_decl_const(sym, ident->token->value);
|
|
||||||
prog_add_instr(prog, OP_LOCAL_STORE, id);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_ASSIGN: {
|
|
||||||
struct node* ident = node->children.data[0];
|
|
||||||
struct node* expr = node->children.data[1];
|
|
||||||
struct symbol* symbol = sym_try_get(sym, ident->token->value);
|
|
||||||
|
|
||||||
if (!symbol)
|
|
||||||
{
|
|
||||||
errors_push(ident->token->line, "'%s' is not defined",
|
|
||||||
ident->token->value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (symbol->is_const)
|
|
||||||
{
|
|
||||||
errors_push(ident->token->line, "'%s' is not mutable",
|
|
||||||
ident->token->value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
compiler_compile(self, expr, prog, sym);
|
|
||||||
prog_add_instr(prog, OP_LOCAL_STORE, symbol->id);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_IDENT: {
|
|
||||||
struct symbol* symbol = sym_try_get(sym,
|
|
||||||
node->token->value);
|
|
||||||
assert(symbol);
|
|
||||||
prog_add_instr(prog, OP_LOCAL_LOAD, symbol->id);
|
|
||||||
} break;
|
|
||||||
case NODE_BOOL: {
|
case NODE_BOOL: {
|
||||||
union val val;
|
union val val;
|
||||||
val.boolean =
|
val.boolean =
|
||||||
|
@ -163,70 +77,70 @@ void compiler_compile(struct compiler* self,
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_LT: {
|
case NODE_LT: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_LT, SK_NO_PARAM);
|
prog_add_instr(prog, OP_LT, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_LE: {
|
case NODE_LE: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_GT, SK_NO_PARAM);
|
prog_add_instr(prog, OP_GT, SK_NO_PARAM);
|
||||||
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
|
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_GT: {
|
case NODE_GT: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_GT, SK_NO_PARAM);
|
prog_add_instr(prog, OP_GT, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_GE: {
|
case NODE_GE: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_LT, SK_NO_PARAM);
|
prog_add_instr(prog, OP_LT, SK_NO_PARAM);
|
||||||
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
|
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_EQUAL: {
|
case NODE_EQUAL: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM);
|
prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_NOT_EQUAL: {
|
case NODE_NOT_EQUAL: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM);
|
prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM);
|
||||||
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
|
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_ADD: {
|
case NODE_ADD: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_ADD, SK_NO_PARAM);
|
prog_add_instr(prog, OP_ADD, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_SUB: {
|
case NODE_SUB: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_SUB, SK_NO_PARAM);
|
prog_add_instr(prog, OP_SUB, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_MUL: {
|
case NODE_MUL: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_MUL, SK_NO_PARAM);
|
prog_add_instr(prog, OP_MUL, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_DIV: {
|
case NODE_DIV: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_DIV, SK_NO_PARAM);
|
prog_add_instr(prog, OP_DIV, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_MOD: {
|
case NODE_MOD: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_MOD, SK_NO_PARAM);
|
prog_add_instr(prog, OP_MOD, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_POW: {
|
case NODE_POW: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_POW, SK_NO_PARAM);
|
prog_add_instr(prog, OP_POW, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_USUB: {
|
case NODE_USUB: {
|
||||||
compiler_compile_children(self, node, prog, sym);
|
compiler_compile_children(self, node, prog);
|
||||||
prog_add_instr(prog, OP_USUB, SK_NO_PARAM);
|
prog_add_instr(prog, OP_USUB, SK_NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -240,8 +154,7 @@ void compiler_compile(struct compiler* self,
|
||||||
|
|
||||||
void compiler_compile_children(struct compiler* self,
|
void compiler_compile_children(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct prog* prog,
|
struct prog* prog)
|
||||||
struct sym* sym)
|
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(node);
|
assert(node);
|
||||||
|
@ -250,7 +163,7 @@ void compiler_compile_children(struct compiler* self,
|
||||||
for (size_t i=0; i<node->children.size; i++)
|
for (size_t i=0; i<node->children.size; i++)
|
||||||
{
|
{
|
||||||
struct node* child = node->children.data[i];
|
struct node* child = node->children.data[i];
|
||||||
compiler_compile(self, child, prog, sym);
|
compiler_compile(self, child, prog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,13 +184,11 @@ void compiler_compile_value(struct compiler* self,
|
||||||
|
|
||||||
void compiler_compile_and(struct compiler* self,
|
void compiler_compile_and(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct prog* prog,
|
struct prog* prog)
|
||||||
struct sym* sym)
|
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(node);
|
assert(node);
|
||||||
assert(prog);
|
assert(prog);
|
||||||
assert(sym);
|
|
||||||
|
|
||||||
struct vec to_false;
|
struct vec to_false;
|
||||||
vec_init(&to_false);
|
vec_init(&to_false);
|
||||||
|
@ -285,7 +196,7 @@ void compiler_compile_and(struct compiler* self,
|
||||||
for (size_t i =0; i<node->children.size; i++)
|
for (size_t i =0; i<node->children.size; i++)
|
||||||
{
|
{
|
||||||
struct node* child = node->children.data[i];
|
struct node* child = node->children.data[i];
|
||||||
compiler_compile(self, child, prog, sym);
|
compiler_compile(self, child, prog);
|
||||||
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to false
|
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to false
|
||||||
vec_push(&to_false, (void*) brf);
|
vec_push(&to_false, (void*) brf);
|
||||||
}
|
}
|
||||||
|
@ -314,20 +225,19 @@ void compiler_compile_and(struct compiler* self,
|
||||||
|
|
||||||
void compiler_compile_or(struct compiler* self,
|
void compiler_compile_or(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct prog* prog,
|
struct prog* prog)
|
||||||
struct sym* sym)
|
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(node);
|
assert(node);
|
||||||
assert(prog);
|
assert(prog);
|
||||||
assert(sym);
|
|
||||||
struct vec to_true;
|
struct vec to_true;
|
||||||
vec_init(&to_true);
|
vec_init(&to_true);
|
||||||
|
|
||||||
for (size_t i =0; i<node->children.size; i++)
|
for (size_t i =0; i<node->children.size; i++)
|
||||||
{
|
{
|
||||||
struct node* child = node->children.data[i];
|
struct node* child = node->children.data[i];
|
||||||
compiler_compile(self, child, prog, sym);
|
compiler_compile(self, child, prog);
|
||||||
prog_add_instr(prog, OP_NOT, 0);
|
prog_add_instr(prog, OP_NOT, 0);
|
||||||
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to true
|
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to true
|
||||||
vec_push(&to_true, (void*) brf);
|
vec_push(&to_true, (void*) brf);
|
||||||
|
@ -354,37 +264,3 @@ void compiler_compile_or(struct compiler* self,
|
||||||
|
|
||||||
vec_free(&to_true);
|
vec_free(&to_true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler_compile_if(struct compiler* self,
|
|
||||||
struct node* node,
|
|
||||||
struct prog* prog,
|
|
||||||
struct sym* sym,
|
|
||||||
struct vec* to_end)
|
|
||||||
{
|
|
||||||
struct node* cond = node->children.data[0];
|
|
||||||
struct node* block = node->children.data[1];
|
|
||||||
|
|
||||||
compiler_compile(self, cond, prog, sym);
|
|
||||||
size_t brf = prog_add_instr(prog, OP_BRF, 40); // to next
|
|
||||||
|
|
||||||
compiler_compile(self, block, prog, sym);
|
|
||||||
|
|
||||||
size_t br = prog_add_instr(prog, OP_BR, 0); // to end
|
|
||||||
vec_push(to_end, (void*) br);
|
|
||||||
|
|
||||||
size_t next_point = prog->opcodes.size;
|
|
||||||
((size_t*)prog->params.data)[brf] = next_point;
|
|
||||||
|
|
||||||
if (node->children.size == 3)
|
|
||||||
{
|
|
||||||
struct node* next = node->children.data[2];
|
|
||||||
if (next->kind == NODE_IF)
|
|
||||||
{
|
|
||||||
compiler_compile_if(self, next, prog, sym, to_end);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
compiler_compile(self, next, prog, sym);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,16 +27,6 @@ void exec_execute(struct exec* self,
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case OP_LOCAL_STORE: {
|
|
||||||
state_local_store(state, param);
|
|
||||||
self->pc++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case OP_LOCAL_LOAD: {
|
|
||||||
state_local_load(state, param);
|
|
||||||
self->pc++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case OP_ASSERT_EQ: {
|
case OP_ASSERT_EQ: {
|
||||||
SK rhs = state_pop(state);
|
SK rhs = state_pop(state);
|
||||||
SK lhs = state_pop(state);
|
SK lhs = state_pop(state);
|
||||||
|
|
|
@ -92,34 +92,6 @@ bool lexer_is_sep(struct lexer* self, size_t index)
|
||||||
|| c == '=';
|
|| c == '=';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lexer_next_nth_is(struct lexer* self, TokenKind kind, int nth)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
struct context ctx = self->context;
|
|
||||||
|
|
||||||
bool res = false;
|
|
||||||
|
|
||||||
for (int i=0; i<=nth; i++)
|
|
||||||
{
|
|
||||||
struct token* tok = lexer_try_new_next(self);
|
|
||||||
|
|
||||||
if (!tok)
|
|
||||||
{
|
|
||||||
self->context = ctx;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = tok->kind == kind;
|
|
||||||
token_free(tok);
|
|
||||||
free(tok);
|
|
||||||
}
|
|
||||||
|
|
||||||
self->context = ctx;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lexer_next_is(struct lexer* self, TokenKind kind)
|
bool lexer_next_is(struct lexer* self, TokenKind kind)
|
||||||
{
|
{
|
||||||
struct context ctx = self->context;
|
struct context ctx = self->context;
|
||||||
|
@ -128,7 +100,6 @@ bool lexer_next_is(struct lexer* self, TokenKind kind)
|
||||||
|
|
||||||
if (!tok)
|
if (!tok)
|
||||||
{
|
{
|
||||||
self->context = ctx;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +108,7 @@ bool lexer_next_is(struct lexer* self, TokenKind kind)
|
||||||
free(tok);
|
free(tok);
|
||||||
|
|
||||||
self->context = ctx;
|
self->context = ctx;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,13 +164,6 @@ struct token* lexer_try_new_next(struct lexer* self)
|
||||||
SK_SCAN_TEXT(")", TOKEN_CPAR);
|
SK_SCAN_TEXT(")", TOKEN_CPAR);
|
||||||
SK_SCAN_TEXT(">", TOKEN_GT);
|
SK_SCAN_TEXT(">", TOKEN_GT);
|
||||||
SK_SCAN_TEXT("<", TOKEN_LT);
|
SK_SCAN_TEXT("<", TOKEN_LT);
|
||||||
SK_SCAN_TEXT("=", TOKEN_ASSIGN);
|
|
||||||
SK_SCAN_KEYWORD("if", TOKEN_IF, NULL);
|
|
||||||
SK_SCAN_KEYWORD("else", TOKEN_ELSE, NULL);
|
|
||||||
SK_SCAN_KEYWORD("begin", TOKEN_BEGIN, NULL);
|
|
||||||
SK_SCAN_KEYWORD("end", TOKEN_END, NULL);
|
|
||||||
SK_SCAN_KEYWORD("var", TOKEN_VAR, NULL);
|
|
||||||
SK_SCAN_KEYWORD("const", TOKEN_CONST, NULL);
|
|
||||||
SK_SCAN_KEYWORD("assert", TOKEN_ASSERT, NULL);
|
SK_SCAN_KEYWORD("assert", TOKEN_ASSERT, NULL);
|
||||||
SK_SCAN_KEYWORD("eq", TOKEN_ASSERT_EQ, NULL);
|
SK_SCAN_KEYWORD("eq", TOKEN_ASSERT_EQ, NULL);
|
||||||
SK_SCAN_KEYWORD("true", TOKEN_BOOL, "true");
|
SK_SCAN_KEYWORD("true", TOKEN_BOOL, "true");
|
||||||
|
@ -208,11 +173,6 @@ struct token* lexer_try_new_next(struct lexer* self)
|
||||||
SK_SCAN_KEYWORD("not", TOKEN_NOT, NULL);
|
SK_SCAN_KEYWORD("not", TOKEN_NOT, NULL);
|
||||||
|
|
||||||
|
|
||||||
if ( (tok=lexer_try_scan_ident(self)) )
|
|
||||||
{
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->context.cursor < self->len)
|
if (self->context.cursor < self->len)
|
||||||
{
|
{
|
||||||
struct str str;
|
struct str str;
|
||||||
|
@ -392,47 +352,6 @@ struct token* lexer_try_scan_string(struct lexer* self)
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct token* lexer_try_scan_ident(struct lexer* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
size_t cursor = self->context.cursor;
|
|
||||||
struct str value;
|
|
||||||
str_init(&value);
|
|
||||||
|
|
||||||
while (cursor < self->len
|
|
||||||
&& lexer_is_ident(self, cursor))
|
|
||||||
{
|
|
||||||
str_push(&value, self->source[cursor]);
|
|
||||||
cursor++;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct token* tok = NULL;
|
|
||||||
|
|
||||||
if (value.size > 0 && !isdigit(value.value[0]))
|
|
||||||
{
|
|
||||||
tok = malloc(sizeof(struct token));
|
|
||||||
token_init(tok, TOKEN_IDENT,
|
|
||||||
value.value, self->context.line);
|
|
||||||
|
|
||||||
self->context.cursor = cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
str_free(&value);
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lexer_is_ident(struct lexer* self, size_t index)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
if (index >= self->len) { return false; }
|
|
||||||
|
|
||||||
char c = self->source[index];
|
|
||||||
return isalnum(c)
|
|
||||||
|| c == '_'
|
|
||||||
|| c == '!'
|
|
||||||
|| c == '?';
|
|
||||||
}
|
|
||||||
|
|
||||||
struct token* lexer_try_scan_text(struct lexer* self,
|
struct token* lexer_try_scan_text(struct lexer* self,
|
||||||
char const* text,
|
char const* text,
|
||||||
TokenKind kind)
|
TokenKind kind)
|
||||||
|
|
|
@ -9,7 +9,6 @@ void module_init(struct module* self)
|
||||||
assert(self);
|
assert(self);
|
||||||
str_init(&self->source);
|
str_init(&self->source);
|
||||||
prog_init(&self->prog);
|
prog_init(&self->prog);
|
||||||
sym_init(&self->sym);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void module_free(struct module* self)
|
void module_free(struct module* self)
|
||||||
|
@ -17,7 +16,6 @@ void module_free(struct module* self)
|
||||||
assert(self);
|
assert(self);
|
||||||
str_free(&self->source);
|
str_free(&self->source);
|
||||||
prog_free(&self->prog);
|
prog_free(&self->prog);
|
||||||
sym_free(&self->sym);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void module_load_source(struct module* self,
|
void module_load_source(struct module* self,
|
||||||
|
@ -54,7 +52,7 @@ int module_compile(struct module* self)
|
||||||
struct compiler compiler;
|
struct compiler compiler;
|
||||||
compiler_init(&compiler);
|
compiler_init(&compiler);
|
||||||
|
|
||||||
compiler_compile(&compiler, root, &self->prog, &self->sym);
|
compiler_compile(&compiler, root, &self->prog);
|
||||||
|
|
||||||
struct exec exec;
|
struct exec exec;
|
||||||
exec_init(&exec);
|
exec_init(&exec);
|
||||||
|
|
306
lib/src/parser.c
306
lib/src/parser.c
|
@ -94,304 +94,9 @@ struct node* parser_try_expr(struct parser* self)
|
||||||
return SK_TRY(parser_try_assert);
|
return SK_TRY(parser_try_assert);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lexer_next_is(&self->lexer, TOKEN_CONST))
|
|
||||||
{
|
|
||||||
return SK_TRY(parser_try_const_decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lexer_next_is(&self->lexer, TOKEN_IDENT)
|
|
||||||
&& lexer_next_nth_is(&self->lexer, TOKEN_ASSIGN, 1))
|
|
||||||
{
|
|
||||||
return SK_TRY(parser_try_assign);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lexer_next_is(&self->lexer, TOKEN_VAR))
|
|
||||||
{
|
|
||||||
return SK_TRY(parser_try_var_decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lexer_next_is(&self->lexer, TOKEN_BEGIN))
|
|
||||||
{
|
|
||||||
return SK_TRY(parser_try_block);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lexer_next_is(&self->lexer, TOKEN_IF))
|
|
||||||
{
|
|
||||||
return SK_TRY(parser_try_if);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SK_TRY(parser_try_or);
|
return SK_TRY(parser_try_or);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node* parser_try_block(struct parser* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_BEGIN))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct token* tok = lexer_try_new_next(&self->lexer);
|
|
||||||
|
|
||||||
struct node* node = SK_TRY(parser_try_inner_block);
|
|
||||||
|
|
||||||
if (!node)
|
|
||||||
{
|
|
||||||
token_free(tok); free(tok);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_END))
|
|
||||||
{
|
|
||||||
node_free(node); free(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(&self->lexer);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* parser_try_inner_block(struct parser* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
struct node* node = malloc(sizeof(struct node));
|
|
||||||
struct token* tok = malloc(sizeof(struct token));
|
|
||||||
token_init(tok, TOKEN_BEGIN, "", self->lexer.context.line);
|
|
||||||
node_init(node, NODE_BLOCK, tok);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
struct node* child = SK_TRY(parser_try_expr);
|
|
||||||
|
|
||||||
if (!child)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_push_new_child(node, child);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* parser_try_if(struct parser* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_IF))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct token* tok = lexer_try_new_next(&self->lexer);
|
|
||||||
struct node* cond = SK_TRY(parser_try_expr);
|
|
||||||
|
|
||||||
if (!cond)
|
|
||||||
{
|
|
||||||
token_free(tok); free(tok);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* block = SK_TRY(parser_try_inner_block);
|
|
||||||
|
|
||||||
if (0&&lexer_next_is(&self->lexer, TOKEN_END))
|
|
||||||
{
|
|
||||||
lexer_consume_next(&self->lexer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!block)
|
|
||||||
{
|
|
||||||
token_free(tok); free(tok);
|
|
||||||
node_free(cond); free(cond);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* node = malloc(sizeof(struct node));
|
|
||||||
node_init(node, NODE_IF, tok);
|
|
||||||
node_push_new_child(node, cond);
|
|
||||||
node_push_new_child(node, block);
|
|
||||||
|
|
||||||
if (lexer_next_is(&self->lexer, TOKEN_ELSE))
|
|
||||||
{
|
|
||||||
lexer_consume_next(&self->lexer);
|
|
||||||
|
|
||||||
if (lexer_next_is(&self->lexer, TOKEN_IF))
|
|
||||||
{
|
|
||||||
struct node* next = SK_TRY(parser_try_if);
|
|
||||||
|
|
||||||
if (!next)
|
|
||||||
{
|
|
||||||
token_free(tok); free(tok);
|
|
||||||
node_free(node); free(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_push_new_child(node, next);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct node* else_block
|
|
||||||
= SK_TRY(parser_try_inner_block);
|
|
||||||
|
|
||||||
if (!else_block)
|
|
||||||
{
|
|
||||||
token_free(tok); free(tok);
|
|
||||||
node_free(node); free(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_push_new_child(node, else_block);
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_END))
|
|
||||||
{
|
|
||||||
token_free(tok); free(tok);
|
|
||||||
node_free(node); free(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(&self->lexer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_END))
|
|
||||||
{
|
|
||||||
token_free(tok); free(tok);
|
|
||||||
node_free(node); free(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(&self->lexer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* parser_try_assign(struct parser* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_IDENT))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* ident = malloc(sizeof(struct node));
|
|
||||||
node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer));
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_ASSIGN))
|
|
||||||
{
|
|
||||||
node_free(ident); free(ident);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct token* tok = lexer_try_new_next(&self->lexer);
|
|
||||||
|
|
||||||
struct node* expr = SK_TRY(parser_try_expr);
|
|
||||||
|
|
||||||
if (!expr)
|
|
||||||
{
|
|
||||||
node_free(ident); free(ident);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* node = malloc(sizeof(struct node));
|
|
||||||
node_init(node, NODE_ASSIGN, tok);
|
|
||||||
node_push_new_child(node, ident);
|
|
||||||
node_push_new_child(node, expr);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* parser_try_var_decl(struct parser* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_VAR))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(&self->lexer);
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_IDENT))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* ident = malloc(sizeof(struct node));
|
|
||||||
node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer));
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_ASSIGN))
|
|
||||||
{
|
|
||||||
node_free(ident); free(ident);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct token* tok = lexer_try_new_next(&self->lexer);
|
|
||||||
|
|
||||||
struct node* expr = SK_TRY(parser_try_expr);
|
|
||||||
|
|
||||||
if (!expr)
|
|
||||||
{
|
|
||||||
node_free(ident); free(ident);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* node = malloc(sizeof(struct node));
|
|
||||||
node_init(node, NODE_VAR_DECL, tok);
|
|
||||||
node_push_new_child(node, ident);
|
|
||||||
node_push_new_child(node, expr);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* parser_try_const_decl(struct parser* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_CONST))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(&self->lexer);
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_IDENT))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* ident = malloc(sizeof(struct node));
|
|
||||||
node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer));
|
|
||||||
|
|
||||||
if (!lexer_next_is(&self->lexer, TOKEN_ASSIGN))
|
|
||||||
{
|
|
||||||
node_free(ident); free(ident);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct token* tok = lexer_try_new_next(&self->lexer);
|
|
||||||
|
|
||||||
struct node* expr = SK_TRY(parser_try_expr);
|
|
||||||
|
|
||||||
if (!expr)
|
|
||||||
{
|
|
||||||
node_free(ident); free(ident);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* node = malloc(sizeof(struct node));
|
|
||||||
node_init(node, NODE_CONST_DECL, tok);
|
|
||||||
node_push_new_child(node, ident);
|
|
||||||
node_push_new_child(node, expr);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct node* parser_try_assert(struct parser* self)
|
struct node* parser_try_assert(struct parser* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -825,17 +530,6 @@ struct node* parser_try_literal(struct parser* self)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lexer_next_is(&self->lexer, TOKEN_IDENT))
|
|
||||||
{
|
|
||||||
struct node* node = malloc(sizeof(struct node));
|
|
||||||
|
|
||||||
node_init(node,
|
|
||||||
NODE_IDENT,
|
|
||||||
lexer_try_new_next(&self->lexer));
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SK_TRY(parser_try_builtin);
|
return SK_TRY(parser_try_builtin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
|
|
||||||
void stack_value_init(struct stack_value* self,
|
void local_init(struct local* self,
|
||||||
size_t addr,
|
size_t addr,
|
||||||
struct value* new_value)
|
struct value* new_value)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(new_value);
|
assert(new_value);
|
||||||
|
@ -11,7 +11,7 @@ void stack_value_init(struct stack_value* self,
|
||||||
self->value = new_value;
|
self->value = new_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stack_value_free(struct stack_value* self)
|
void local_free(struct local* self)
|
||||||
{
|
{
|
||||||
value_free(self->value);
|
value_free(self->value);
|
||||||
free(self->value);
|
free(self->value);
|
||||||
|
@ -20,16 +20,13 @@ void stack_value_free(struct stack_value* self)
|
||||||
|
|
||||||
void frame_init(struct frame* self)
|
void frame_init(struct frame* self)
|
||||||
{
|
{
|
||||||
vec_init(&self->stack_values);
|
|
||||||
vec_init(&self->locals);
|
vec_init(&self->locals);
|
||||||
vec_init(&self->stack);
|
vec_init(&self->stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void frame_free(struct frame* self)
|
void frame_free(struct frame* self)
|
||||||
{
|
{
|
||||||
vec_free_elements(&self->stack_values, (void*) stack_value_free);
|
vec_free_elements(&self->locals, (void*) local_free);
|
||||||
vec_free(&self->stack_values);
|
|
||||||
vec_free_elements(&self->locals, NULL);
|
|
||||||
vec_free(&self->locals);
|
vec_free(&self->locals);
|
||||||
vec_free(&self->stack);
|
vec_free(&self->stack);
|
||||||
}
|
}
|
||||||
|
@ -86,13 +83,13 @@ struct value* state_try_get_value(struct state* self, SK value)
|
||||||
assert(self);
|
assert(self);
|
||||||
struct frame* frame = state_frame(self);
|
struct frame* frame = state_frame(self);
|
||||||
|
|
||||||
for (size_t i=0; i<frame->stack_values.size; i++)
|
for (size_t i=0; i<frame->locals.size; i++)
|
||||||
{
|
{
|
||||||
struct stack_value* stack_value = frame->stack_values.data[i];
|
struct local* local = frame->locals.data[i];
|
||||||
|
|
||||||
if (stack_value->addr == value)
|
if (local->addr == value)
|
||||||
{
|
{
|
||||||
return stack_value->value;
|
return local->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,10 +118,10 @@ SK state_push(struct state* self,
|
||||||
value_init(value, type, val, line);
|
value_init(value, type, val, line);
|
||||||
|
|
||||||
struct frame* frame = state_frame(self);
|
struct frame* frame = state_frame(self);
|
||||||
struct stack_value* stack_value = malloc(sizeof(struct stack_value));
|
struct local* local = malloc(sizeof(struct local));
|
||||||
stack_value_init(stack_value, self->addr, value);
|
local_init(local, self->addr, value);
|
||||||
|
|
||||||
vec_push(&frame->stack_values, stack_value);
|
vec_push(&frame->locals, local);
|
||||||
vec_push(&frame->stack, (void*) self->addr);
|
vec_push(&frame->stack, (void*) self->addr);
|
||||||
|
|
||||||
self->addr++;
|
self->addr++;
|
||||||
|
@ -165,63 +162,6 @@ SK state_push_string(struct state* self, char const* str, int line)
|
||||||
return state_push(self, TYPE_STRING, val ,line);
|
return state_push(self, TYPE_STRING, val ,line);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct local* state_try_get_local(struct state* self, int id)
|
|
||||||
{
|
|
||||||
struct frame* frame = state_frame(self);
|
|
||||||
|
|
||||||
for (size_t i=0; i<frame->locals.size; i++)
|
|
||||||
{
|
|
||||||
struct local* local = frame->locals.data[i];
|
|
||||||
|
|
||||||
if (local->id == id)
|
|
||||||
{
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SK state_local_store(struct state* self,
|
|
||||||
int id)
|
|
||||||
{
|
|
||||||
struct local* local = state_try_get_local(self, id);
|
|
||||||
|
|
||||||
if (local)
|
|
||||||
{
|
|
||||||
local->addr = state_pop(self);
|
|
||||||
return local->addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
local = malloc(sizeof(struct local));
|
|
||||||
local->id = id;
|
|
||||||
local->addr = state_top(self);
|
|
||||||
|
|
||||||
struct frame* frame = state_frame(self);
|
|
||||||
vec_push(&frame->locals, local);
|
|
||||||
|
|
||||||
return local->addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void state_local_load(struct state* self,
|
|
||||||
int id)
|
|
||||||
{
|
|
||||||
struct frame* frame = state_frame(self);
|
|
||||||
|
|
||||||
for (size_t i=0; i<frame->locals.size; i++)
|
|
||||||
{
|
|
||||||
struct local* local = frame->locals.data[i];
|
|
||||||
|
|
||||||
if (local->id == id)
|
|
||||||
{
|
|
||||||
vec_push(&frame->stack, (void*) local->addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs)
|
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
122
lib/src/sym.c
122
lib/src/sym.c
|
@ -1,122 +0,0 @@
|
||||||
#include "sym.h"
|
|
||||||
|
|
||||||
void env_init(struct env* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
vec_init(&self->symbols);
|
|
||||||
self->parent = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void env_free(struct env* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
vec_free_elements(&self->symbols, (void*) symbol_free);
|
|
||||||
vec_free(&self->symbols);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct symbol* env_try_get(struct env* self, char const* name)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(name);
|
|
||||||
|
|
||||||
for (size_t i=0; i<self->symbols.size; i++)
|
|
||||||
{
|
|
||||||
struct symbol* symbol = self->symbols.data[i];
|
|
||||||
|
|
||||||
if (strcmp(symbol->name, name) == 0)
|
|
||||||
{
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->parent)
|
|
||||||
{
|
|
||||||
return env_try_get(self->parent, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void symbol_init(struct symbol* self,
|
|
||||||
int id,
|
|
||||||
char const* name,
|
|
||||||
struct env* env)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
self->id = id;
|
|
||||||
self->name = strdup(name);
|
|
||||||
self->is_const = false;
|
|
||||||
self->env = env;
|
|
||||||
}
|
|
||||||
|
|
||||||
void symbol_free(struct symbol* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
free(self->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sym_init(struct sym* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
self->id_counter = 1;
|
|
||||||
self->env = malloc(sizeof(struct env));
|
|
||||||
env_init(self->env);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sym_free(struct sym* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
env_free(self->env);
|
|
||||||
free(self->env);
|
|
||||||
self->env = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sym_decl_var(struct sym* self, char const* name)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(name);
|
|
||||||
struct symbol* symbol = malloc(sizeof(struct symbol));
|
|
||||||
symbol_init(symbol, self->id_counter, name, self->env);
|
|
||||||
|
|
||||||
vec_push(&self->env->symbols, symbol);
|
|
||||||
|
|
||||||
self->id_counter++;
|
|
||||||
return self->id_counter - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sym_decl_const(struct sym* self, char const* name)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(name);
|
|
||||||
struct symbol* symbol = malloc(sizeof(struct symbol));
|
|
||||||
symbol_init(symbol, self->id_counter, name, self->env);
|
|
||||||
symbol->is_const = true;
|
|
||||||
vec_push(&self->env->symbols, symbol);
|
|
||||||
|
|
||||||
self->id_counter++;
|
|
||||||
return self->id_counter - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sym_open_scope(struct sym* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
struct env* env = malloc(sizeof(struct env));
|
|
||||||
env_init(env);
|
|
||||||
env->parent = self->env;
|
|
||||||
self->env = env;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sym_close_scope(struct sym* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
struct env* env = self->env;
|
|
||||||
self->env = env->parent;
|
|
||||||
|
|
||||||
env_free(env);
|
|
||||||
free(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct symbol* sym_try_get(struct sym* self, char const* name)
|
|
||||||
{
|
|
||||||
return env_try_get(self->env, name);
|
|
||||||
}
|
|
|
@ -75,16 +75,6 @@ static void test_lexer_bool()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_lexer_decl()
|
|
||||||
{
|
|
||||||
test_lexer(" var const = x ", 4,
|
|
||||||
"VAR",
|
|
||||||
"CONST",
|
|
||||||
"ASSIGN",
|
|
||||||
"IDENT[x]"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_lexer_float()
|
static void test_lexer_float()
|
||||||
{
|
{
|
||||||
test_lexer(".4 7. 2.3 6.12", 4,
|
test_lexer(".4 7. 2.3 6.12", 4,
|
||||||
|
@ -119,21 +109,6 @@ static void test_lexer_cmp()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_lexer_block()
|
|
||||||
{
|
|
||||||
test_lexer("begin end", 2,
|
|
||||||
"BEGIN",
|
|
||||||
"END"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_lexer_cond()
|
|
||||||
{
|
|
||||||
test_lexer("if else", 2,
|
|
||||||
"IF",
|
|
||||||
"ELSE"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
void register_lexer()
|
void register_lexer()
|
||||||
{
|
{
|
||||||
CU_pSuite suite = CU_add_suite("Lexer", 0, 0);
|
CU_pSuite suite = CU_add_suite("Lexer", 0, 0);
|
||||||
|
@ -143,9 +118,6 @@ void register_lexer()
|
||||||
CU_add_test(suite, "Floats", test_lexer_float);
|
CU_add_test(suite, "Floats", test_lexer_float);
|
||||||
CU_add_test(suite, "Strings", test_lexer_string);
|
CU_add_test(suite, "Strings", test_lexer_string);
|
||||||
CU_add_test(suite, "Comparisons", test_lexer_cmp);
|
CU_add_test(suite, "Comparisons", test_lexer_cmp);
|
||||||
CU_add_test(suite, "Var Declarations", test_lexer_decl);
|
|
||||||
CU_add_test(suite, "Blocks", test_lexer_block);
|
|
||||||
CU_add_test(suite, "Conditionnals", test_lexer_cond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -87,46 +87,6 @@ static void test_parser_cmp()
|
||||||
"5<>3");
|
"5<>3");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_parser_decl()
|
|
||||||
{
|
|
||||||
test_parser("ROOT(IDENT[bim!])",
|
|
||||||
"bim!");
|
|
||||||
|
|
||||||
test_parser("ROOT(VAR_DECL(IDENT[x],INT[37]))",
|
|
||||||
"var x = 37");
|
|
||||||
|
|
||||||
test_parser("ROOT(CONST_DECL(IDENT[x],MUL(FLOAT[2.2],INT[3])))",
|
|
||||||
"const x = 2.2 * 3");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_parser_assign()
|
|
||||||
{
|
|
||||||
test_parser("ROOT(ASSIGN(IDENT[hello],BOOL[false]))",
|
|
||||||
"hello = false");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_parser_block()
|
|
||||||
{
|
|
||||||
test_parser("ROOT(BLOCK)",
|
|
||||||
"begin end");
|
|
||||||
|
|
||||||
test_parser("ROOT(BLOCK(INT[1],INT[2]))",
|
|
||||||
"begin 1 2 end");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_parser_if()
|
|
||||||
{
|
|
||||||
test_parser("ROOT(IF(BOOL[true],BLOCK(INT[0])))",
|
|
||||||
"if true 0 end");
|
|
||||||
|
|
||||||
test_parser("ROOT(IF(BOOL[true],BLOCK(INT[0]),BLOCK(INT[1])))",
|
|
||||||
"if true 0 else 1 end");
|
|
||||||
|
|
||||||
test_parser("ROOT(IF(BOOL[true],BLOCK(INT[0]),"
|
|
||||||
"IF(BOOL[false],BLOCK(INT[1]),BLOCK(INT[2]))))",
|
|
||||||
"if true 0 else if false 1 else 2 end");
|
|
||||||
}
|
|
||||||
|
|
||||||
void register_parser()
|
void register_parser()
|
||||||
{
|
{
|
||||||
CU_pSuite suite = CU_add_suite("Parser", 0, 0);
|
CU_pSuite suite = CU_add_suite("Parser", 0, 0);
|
||||||
|
@ -135,10 +95,6 @@ void register_parser()
|
||||||
CU_add_test(suite, "Booleans", test_parser_bool);
|
CU_add_test(suite, "Booleans", test_parser_bool);
|
||||||
CU_add_test(suite, "Strings", test_parser_string);
|
CU_add_test(suite, "Strings", test_parser_string);
|
||||||
CU_add_test(suite, "Comparisons", test_parser_cmp);
|
CU_add_test(suite, "Comparisons", test_parser_cmp);
|
||||||
CU_add_test(suite, "Declarations", test_parser_decl);
|
|
||||||
CU_add_test(suite, "Assignments", test_parser_assign);
|
|
||||||
CU_add_test(suite, "Blocks", test_parser_block);
|
|
||||||
CU_add_test(suite, "IfExpression", test_parser_if);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue