✨ int arithmetic.
parent
1f71fce283
commit
77fda3a432
|
@ -1,4 +1,11 @@
|
||||||
ROOT ::= EXPR*
|
ROOT ::= EXPR*
|
||||||
EXPR ::= BUILTIN
|
EXPR ::= TERM
|
||||||
|
TERM ::= FACTOR ((add|sub) FACTOR)*
|
||||||
|
FACTOR ::= USUB ((mul|div|mod) USUB)*
|
||||||
|
USUB ::= sub* POW
|
||||||
|
POW ::= LITERAL (pow LITERAL)?
|
||||||
|
LITERAL ::=
|
||||||
|
| BUILTIN
|
||||||
|
| opar EXPR cpar
|
||||||
BUILTIN ::=
|
BUILTIN ::=
|
||||||
| int
|
| int
|
||||||
|
|
|
@ -42,6 +42,10 @@ target_include_directories(skopy-lib
|
||||||
PUBLIC ${CMAKE_SOURCE_DIR}/lib/include
|
PUBLIC ${CMAKE_SOURCE_DIR}/lib/include
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_link_options(skopy-lib
|
||||||
|
PUBLIC -lm
|
||||||
|
)
|
||||||
|
|
||||||
target_compile_options(skopy-lib
|
target_compile_options(skopy-lib
|
||||||
PUBLIC -Wall -Wextra -g
|
PUBLIC -Wall -Wextra -g
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
|
|
|
@ -15,5 +15,8 @@ void compiler_compile(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct prog* prog);
|
struct prog* prog);
|
||||||
|
|
||||||
|
void compiler_compile_children(struct compiler* self,
|
||||||
|
struct node* node,
|
||||||
|
struct prog* prog);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,11 @@ void lexer_skip_spaces(struct lexer* self);
|
||||||
|
|
||||||
bool lexer_next_is(struct lexer* self, TokenKind kind);
|
bool lexer_next_is(struct lexer* self, TokenKind kind);
|
||||||
|
|
||||||
|
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_text(struct lexer* self,
|
||||||
|
char const* text,
|
||||||
|
TokenKind kind);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
|
|
||||||
#define NODE_KIND(G) \
|
#define NODE_KIND(G) \
|
||||||
G(NODE_ROOT), \
|
G(NODE_ROOT), \
|
||||||
G(NODE_INT)
|
G(NODE_INT), \
|
||||||
|
G(NODE_ADD), G(NODE_SUB), G(NODE_MUL),\
|
||||||
|
G(NODE_DIV), G(NODE_POW), G(NODE_MOD),\
|
||||||
|
G(NODE_USUB)
|
||||||
|
|
||||||
SK_ENUM_H(NodeKind, NODE_KIND);
|
SK_ENUM_H(NodeKind, NODE_KIND);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,11 @@ 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_term(struct parser* self);
|
||||||
|
struct node* parser_try_factor(struct parser* self);
|
||||||
|
struct node* parser_try_usub(struct parser* self);
|
||||||
|
struct node* parser_try_pow(struct parser* self);
|
||||||
|
struct node* parser_try_literal(struct parser* self);
|
||||||
struct node* parser_try_builtin(struct parser* self);
|
struct node* parser_try_builtin(struct parser* self);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
|
|
||||||
#define SK_NO_PARAM (-1)
|
#define SK_NO_PARAM (-1)
|
||||||
#define OPCODE(G) \
|
#define OPCODE(G) \
|
||||||
G(OP_PUSH)
|
G(OP_PUSH), \
|
||||||
|
G(OP_ADD), G(OP_SUB), G(OP_MUL), \
|
||||||
|
G(OP_DIV), G(OP_MOD), G(OP_POW), \
|
||||||
|
G(OP_USUB)
|
||||||
|
|
||||||
SK_ENUM_H(Opcode, OPCODE);
|
SK_ENUM_H(Opcode, OPCODE);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,16 @@ bool state_has_top(struct state* self);
|
||||||
SK state_top(struct state* self);
|
SK state_top(struct state* self);
|
||||||
struct value* state_try_get_value(struct state* self, SK value);
|
struct value* state_try_get_value(struct state* self, SK value);
|
||||||
|
|
||||||
|
SK state_pop(struct state* self);
|
||||||
|
|
||||||
SK state_push_int(struct state* self, int integer);
|
SK state_push_int(struct state* self, int integer);
|
||||||
|
|
||||||
|
SK state_add(struct state* self);
|
||||||
|
SK state_sub(struct state* self);
|
||||||
|
SK state_usub(struct state* self);
|
||||||
|
SK state_mul(struct state* self);
|
||||||
|
SK state_div(struct state* self);
|
||||||
|
SK state_mod(struct state* self);
|
||||||
|
SK state_pow(struct state* self);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
|
|
||||||
#define TOKEN_KIND(G) \
|
#define TOKEN_KIND(G) \
|
||||||
G(TOKEN_ROOT), \
|
G(TOKEN_ROOT), \
|
||||||
G(TOKEN_INT)
|
G(TOKEN_INT), \
|
||||||
|
G(TOKEN_ADD), G(TOKEN_SUB), \
|
||||||
|
G(TOKEN_MUL), G(TOKEN_DIV), G(TOKEN_MOD), \
|
||||||
|
G(TOKEN_POW), G(TOKEN_OPAR), G(TOKEN_CPAR)
|
||||||
|
|
||||||
SK_ENUM_H(TokenKind, TOKEN_KIND);
|
SK_ENUM_H(TokenKind, TOKEN_KIND);
|
||||||
|
|
||||||
|
@ -20,6 +23,7 @@ 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);
|
||||||
|
|
||||||
void token_str(struct token* self, struct str* dest);
|
void token_str(struct token* self, struct str* dest);
|
||||||
|
|
|
@ -17,6 +17,7 @@ void vec_free_elements(struct vec* self,
|
||||||
void vec_free(struct vec* self);
|
void vec_free(struct vec* self);
|
||||||
|
|
||||||
void vec_push(struct vec* self, void* element);
|
void vec_push(struct vec* self, void* element);
|
||||||
|
void* vec_pop(struct vec* self);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,41 @@ void compiler_compile(struct compiler* self,
|
||||||
prog_add_instr(prog, OP_PUSH, idx);
|
prog_add_instr(prog, OP_PUSH, idx);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case NODE_ADD: {
|
||||||
|
compiler_compile_children(self, node, prog);
|
||||||
|
prog_add_instr(prog, OP_ADD, SK_NO_PARAM);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_SUB: {
|
||||||
|
compiler_compile_children(self, node, prog);
|
||||||
|
prog_add_instr(prog, OP_SUB, SK_NO_PARAM);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_MUL: {
|
||||||
|
compiler_compile_children(self, node, prog);
|
||||||
|
prog_add_instr(prog, OP_MUL, SK_NO_PARAM);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_DIV: {
|
||||||
|
compiler_compile_children(self, node, prog);
|
||||||
|
prog_add_instr(prog, OP_DIV, SK_NO_PARAM);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_MOD: {
|
||||||
|
compiler_compile_children(self, node, prog);
|
||||||
|
prog_add_instr(prog, OP_MOD, SK_NO_PARAM);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_POW: {
|
||||||
|
compiler_compile_children(self, node, prog);
|
||||||
|
prog_add_instr(prog, OP_POW, SK_NO_PARAM);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case NODE_USUB: {
|
||||||
|
compiler_compile_children(self, node, prog);
|
||||||
|
prog_add_instr(prog, OP_USUB, SK_NO_PARAM);
|
||||||
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "cannot compile node '%s'\n",
|
fprintf(stderr, "cannot compile node '%s'\n",
|
||||||
NodeKindStr[node->kind]);
|
NodeKindStr[node->kind]);
|
||||||
|
@ -46,3 +81,18 @@ void compiler_compile(struct compiler* self,
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void compiler_compile_children(struct compiler* self,
|
||||||
|
struct node* node,
|
||||||
|
struct prog* prog)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(node);
|
||||||
|
assert(prog);
|
||||||
|
|
||||||
|
for (size_t i=0; i<node->children.size; i++)
|
||||||
|
{
|
||||||
|
struct node* child = node->children.data[i];
|
||||||
|
compiler_compile(self, child, prog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,41 @@ void exec_execute(struct exec* self,
|
||||||
self->pc++;
|
self->pc++;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case OP_ADD: {
|
||||||
|
state_add(state);
|
||||||
|
self->pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case OP_SUB: {
|
||||||
|
state_sub(state);
|
||||||
|
self->pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case OP_MUL: {
|
||||||
|
state_mul(state);
|
||||||
|
self->pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case OP_DIV: {
|
||||||
|
state_div(state);
|
||||||
|
self->pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case OP_MOD: {
|
||||||
|
state_mod(state);
|
||||||
|
self->pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case OP_POW: {
|
||||||
|
state_pow(state);
|
||||||
|
self->pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case OP_USUB: {
|
||||||
|
state_usub(state);
|
||||||
|
self->pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "cannot execute opcode '%s'\n",
|
fprintf(stderr, "cannot execute opcode '%s'\n",
|
||||||
OpcodeStr[opcode]);
|
OpcodeStr[opcode]);
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
|
|
||||||
|
#define SK_SCAN_TEXT(TXT, TOK) \
|
||||||
|
if ( (tok=lexer_try_scan_text(self, TXT, TOK)) )\
|
||||||
|
{\
|
||||||
|
return tok;\
|
||||||
|
}
|
||||||
|
|
||||||
void lexer_init(struct lexer* self, char const* source)
|
void lexer_init(struct lexer* self, char const* source)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
self->source = strdup(source);
|
self->len = source ? strlen(source) : 0;
|
||||||
self->len = strlen(self->source);
|
self->source = (self->len > 0) ? strdup(source) : strdup("");
|
||||||
self->context.line = 1;
|
self->context.line = 1;
|
||||||
self->context.cursor = 0;
|
self->context.cursor = 0;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +18,12 @@ void lexer_init(struct lexer* self, char const* source)
|
||||||
void lexer_free(struct lexer* self)
|
void lexer_free(struct lexer* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
|
if (self->source)
|
||||||
|
{
|
||||||
free(self->source);
|
free(self->source);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void lexer_skip_spaces(struct lexer* self)
|
void lexer_skip_spaces(struct lexer* self)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +41,22 @@ void lexer_skip_spaces(struct lexer* self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lexer_is_sep(struct lexer* self, size_t index)
|
||||||
|
{
|
||||||
|
if (index >= self->len) { return true; }
|
||||||
|
char c = self->source[index];
|
||||||
|
|
||||||
|
return isspace(c)
|
||||||
|
|| c == '('
|
||||||
|
|| c == ')'
|
||||||
|
|| c == '+'
|
||||||
|
|| c == '-'
|
||||||
|
|| c == '*'
|
||||||
|
|| c == '/'
|
||||||
|
|| c == '%'
|
||||||
|
|| c == '^';
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -51,6 +77,17 @@ bool lexer_next_is(struct lexer* self, TokenKind kind)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lexer_consume_next(struct lexer* self)
|
||||||
|
{
|
||||||
|
struct token* tok = lexer_try_new_next(self);
|
||||||
|
|
||||||
|
if (tok)
|
||||||
|
{
|
||||||
|
token_free(tok);
|
||||||
|
free(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct token* lexer_try_new_next(struct lexer* self)
|
struct token* lexer_try_new_next(struct lexer* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -69,13 +106,22 @@ struct token* lexer_try_new_next(struct lexer* self)
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SK_SCAN_TEXT("+", TOKEN_ADD);
|
||||||
|
SK_SCAN_TEXT("-", TOKEN_SUB);
|
||||||
|
SK_SCAN_TEXT("*", TOKEN_MUL);
|
||||||
|
SK_SCAN_TEXT("/", TOKEN_DIV);
|
||||||
|
SK_SCAN_TEXT("^", TOKEN_POW);
|
||||||
|
SK_SCAN_TEXT("%", TOKEN_MOD);
|
||||||
|
SK_SCAN_TEXT("(", TOKEN_OPAR);
|
||||||
|
SK_SCAN_TEXT(")", TOKEN_CPAR);
|
||||||
|
|
||||||
if (self->context.cursor < self->len)
|
if (self->context.cursor < self->len)
|
||||||
{
|
{
|
||||||
struct str str;
|
struct str str;
|
||||||
str_init(&str);
|
str_init(&str);
|
||||||
|
|
||||||
while (self->context.cursor < self->len
|
while (self->context.cursor < self->len
|
||||||
&& !isspace(self->source[self->context.cursor]))
|
&& !lexer_is_sep(self, self->context.cursor))
|
||||||
{
|
{
|
||||||
str_push(&str, self->source[self->context.cursor]);
|
str_push(&str, self->source[self->context.cursor]);
|
||||||
self->context.cursor++;
|
self->context.cursor++;
|
||||||
|
@ -112,7 +158,8 @@ struct token* lexer_try_scan_int(struct lexer* self)
|
||||||
|
|
||||||
struct token* tok = NULL;
|
struct token* tok = NULL;
|
||||||
|
|
||||||
if (value.size > 0)
|
if (value.size > 0
|
||||||
|
&& (value.value[0] != '-' || value.size > 1))
|
||||||
{
|
{
|
||||||
tok = malloc(sizeof(struct token));
|
tok = malloc(sizeof(struct token));
|
||||||
token_init(tok, TOKEN_INT,
|
token_init(tok, TOKEN_INT,
|
||||||
|
@ -125,3 +172,30 @@ struct token* lexer_try_scan_int(struct lexer* self)
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct token* lexer_try_scan_text(struct lexer* self,
|
||||||
|
char const* text,
|
||||||
|
TokenKind kind)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(text);
|
||||||
|
size_t txt_sz = strlen(text);
|
||||||
|
|
||||||
|
if (self->context.cursor + txt_sz > self->len)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<txt_sz; i++)
|
||||||
|
{
|
||||||
|
if (self->source[self->context.cursor + i]
|
||||||
|
!= text[i])
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct token* tok = malloc(sizeof(struct token));
|
||||||
|
token_init(tok, kind, "", self->context.line);
|
||||||
|
self->context.cursor += txt_sz;
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
180
lib/src/parser.c
180
lib/src/parser.c
|
@ -58,11 +58,191 @@ struct node* parser_try_root(struct parser* self)
|
||||||
node_push_new_child(node, expr);
|
node_push_new_child(node, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->lexer.context.cursor < self->lexer.len)
|
||||||
|
{
|
||||||
|
errors_push(self->lexer.context.line, "unexpected end");
|
||||||
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node* parser_try_expr(struct parser* self)
|
struct node* parser_try_expr(struct parser* self)
|
||||||
{
|
{
|
||||||
|
return SK_TRY(parser_try_term);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node* parser_try_term(struct parser* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
struct node* lhs = SK_TRY(parser_try_factor);
|
||||||
|
if (!lhs) { return NULL; }
|
||||||
|
|
||||||
|
while (lexer_next_is(&self->lexer, TOKEN_ADD)
|
||||||
|
|| lexer_next_is(&self->lexer, TOKEN_SUB))
|
||||||
|
{
|
||||||
|
struct node* node = malloc(sizeof(struct node));
|
||||||
|
|
||||||
|
if (lexer_next_is(&self->lexer, TOKEN_ADD))
|
||||||
|
{
|
||||||
|
node_init(node, NODE_ADD, lexer_try_new_next(
|
||||||
|
&self->lexer
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node_init(node, NODE_SUB, lexer_try_new_next(
|
||||||
|
&self->lexer
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
node_push_new_child(node, lhs);
|
||||||
|
struct node* rhs = SK_TRY(parser_try_factor);
|
||||||
|
|
||||||
|
if (!rhs)
|
||||||
|
{
|
||||||
|
node_free(node);
|
||||||
|
free(node);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_push_new_child(node, rhs);
|
||||||
|
lhs = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node* parser_try_factor(struct parser* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
struct node* lhs = SK_TRY(parser_try_usub);
|
||||||
|
if (!lhs) { return NULL; }
|
||||||
|
|
||||||
|
while (lexer_next_is(&self->lexer, TOKEN_MUL)
|
||||||
|
|| lexer_next_is(&self->lexer, TOKEN_DIV)
|
||||||
|
|| lexer_next_is(&self->lexer, TOKEN_MOD))
|
||||||
|
{
|
||||||
|
struct node* node = malloc(sizeof(struct node));
|
||||||
|
|
||||||
|
if (lexer_next_is(&self->lexer, TOKEN_MUL))
|
||||||
|
{
|
||||||
|
node_init(node, NODE_MUL, lexer_try_new_next(
|
||||||
|
&self->lexer
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else if (lexer_next_is(&self->lexer, TOKEN_DIV))
|
||||||
|
{
|
||||||
|
node_init(node, NODE_DIV, lexer_try_new_next(
|
||||||
|
&self->lexer
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node_init(node, NODE_MOD, lexer_try_new_next(
|
||||||
|
&self->lexer
|
||||||
|
));
|
||||||
|
}
|
||||||
|
node_push_new_child(node, lhs);
|
||||||
|
struct node* rhs = SK_TRY(parser_try_usub);
|
||||||
|
|
||||||
|
if (!rhs)
|
||||||
|
{
|
||||||
|
node_free(node);
|
||||||
|
free(node);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_push_new_child(node, rhs);
|
||||||
|
lhs = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node* parser_try_usub(struct parser* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if (lexer_next_is(&self->lexer, TOKEN_SUB))
|
||||||
|
{
|
||||||
|
struct node* node = malloc(sizeof(struct node));
|
||||||
|
node_init(node, NODE_USUB, lexer_try_new_next(
|
||||||
|
&self->lexer
|
||||||
|
));
|
||||||
|
|
||||||
|
struct node* child = SK_TRY(parser_try_usub);
|
||||||
|
|
||||||
|
if (!child)
|
||||||
|
{
|
||||||
|
node_free(node);
|
||||||
|
free(node);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_push_new_child(node, child);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SK_TRY(parser_try_pow);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node* parser_try_pow(struct parser* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
struct node* lhs = SK_TRY(parser_try_literal);
|
||||||
|
if (!lhs) { return NULL; }
|
||||||
|
|
||||||
|
if (lexer_next_is(&self->lexer, TOKEN_POW))
|
||||||
|
{
|
||||||
|
struct node* node = malloc(sizeof(struct node));
|
||||||
|
node_init(node, NODE_POW, lexer_try_new_next(
|
||||||
|
&self->lexer
|
||||||
|
));
|
||||||
|
|
||||||
|
struct node* rhs = SK_TRY(parser_try_literal);
|
||||||
|
|
||||||
|
if (!rhs)
|
||||||
|
{
|
||||||
|
node_free(node);
|
||||||
|
free(node);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_push_new_child(node, lhs);
|
||||||
|
node_push_new_child(node, rhs);
|
||||||
|
lhs = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node* parser_try_literal(struct parser* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if (lexer_next_is(&self->lexer, TOKEN_OPAR))
|
||||||
|
{
|
||||||
|
lexer_consume_next(&self->lexer);
|
||||||
|
struct node* node = SK_TRY(parser_try_expr);
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lexer_next_is(&self->lexer, TOKEN_CPAR))
|
||||||
|
{
|
||||||
|
node_free(node);
|
||||||
|
free(node);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lexer_consume_next(&self->lexer);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
return SK_TRY(parser_try_builtin);
|
return SK_TRY(parser_try_builtin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
107
lib/src/state.c
107
lib/src/state.c
|
@ -96,6 +96,17 @@ struct value* state_try_get_value(struct state* self, SK value)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SK state_pop(struct state* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
struct frame* frame = state_frame(self);
|
||||||
|
assert(frame->stack.size > 0);
|
||||||
|
SK value = (SK) vec_pop(&frame->stack);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
SK state_push_int(struct state* self, int integer)
|
SK state_push_int(struct state* self, int integer)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -115,3 +126,99 @@ SK state_push_int(struct state* self, int integer)
|
||||||
self->addr++;
|
self->addr++;
|
||||||
return self->addr - 1;
|
return self->addr - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SK state_add(struct state* self)
|
||||||
|
{
|
||||||
|
SK rhs = state_pop(self);
|
||||||
|
SK lhs = state_pop(self);
|
||||||
|
|
||||||
|
struct value* left = state_try_get_value(self, lhs);
|
||||||
|
struct value* right = state_try_get_value(self, rhs);
|
||||||
|
|
||||||
|
return state_push_int(
|
||||||
|
self,
|
||||||
|
left->val.integer + right->val.integer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SK state_sub(struct state* self)
|
||||||
|
{
|
||||||
|
SK rhs = state_pop(self);
|
||||||
|
SK lhs = state_pop(self);
|
||||||
|
|
||||||
|
struct value* left = state_try_get_value(self, lhs);
|
||||||
|
struct value* right = state_try_get_value(self, rhs);
|
||||||
|
|
||||||
|
return state_push_int(
|
||||||
|
self,
|
||||||
|
left->val.integer - right->val.integer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SK state_usub(struct state* self)
|
||||||
|
{
|
||||||
|
SK lhs = state_pop(self);
|
||||||
|
|
||||||
|
struct value* left = state_try_get_value(self, lhs);
|
||||||
|
|
||||||
|
return state_push_int(
|
||||||
|
self,
|
||||||
|
-left->val.integer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SK state_mul(struct state* self)
|
||||||
|
{
|
||||||
|
SK rhs = state_pop(self);
|
||||||
|
SK lhs = state_pop(self);
|
||||||
|
|
||||||
|
struct value* left = state_try_get_value(self, lhs);
|
||||||
|
struct value* right = state_try_get_value(self, rhs);
|
||||||
|
|
||||||
|
return state_push_int(
|
||||||
|
self,
|
||||||
|
left->val.integer * right->val.integer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SK state_div(struct state* self)
|
||||||
|
{
|
||||||
|
SK rhs = state_pop(self);
|
||||||
|
SK lhs = state_pop(self);
|
||||||
|
|
||||||
|
struct value* left = state_try_get_value(self, lhs);
|
||||||
|
struct value* right = state_try_get_value(self, rhs);
|
||||||
|
|
||||||
|
return state_push_int(
|
||||||
|
self,
|
||||||
|
left->val.integer / right->val.integer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SK state_mod(struct state* self)
|
||||||
|
{
|
||||||
|
SK rhs = state_pop(self);
|
||||||
|
SK lhs = state_pop(self);
|
||||||
|
|
||||||
|
struct value* left = state_try_get_value(self, lhs);
|
||||||
|
struct value* right = state_try_get_value(self, rhs);
|
||||||
|
|
||||||
|
return state_push_int(
|
||||||
|
self,
|
||||||
|
fmod(left->val.integer, right->val.integer)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SK state_pow(struct state* self)
|
||||||
|
{
|
||||||
|
SK rhs = state_pop(self);
|
||||||
|
SK lhs = state_pop(self);
|
||||||
|
|
||||||
|
struct value* left = state_try_get_value(self, lhs);
|
||||||
|
struct value* right = state_try_get_value(self, rhs);
|
||||||
|
|
||||||
|
return state_push_int(
|
||||||
|
self,
|
||||||
|
powf(left->val.integer, right->val.integer)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -57,3 +57,13 @@ void vec_push(struct vec* self, void* element)
|
||||||
self->data[self->size] = element;
|
self->data[self->size] = element;
|
||||||
self->size++;
|
self->size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* vec_pop(struct vec* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(self->size > 0);
|
||||||
|
|
||||||
|
void* element = self->data[self->size - 1];
|
||||||
|
self->size--;
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
|
@ -43,6 +43,11 @@ static void test_lexer_int()
|
||||||
"INT[-23]",
|
"INT[-23]",
|
||||||
"INT[720]"
|
"INT[720]"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test_lexer("+-*/^%()", 8,
|
||||||
|
"ADD", "SUB", "MUL", "DIV",
|
||||||
|
"POW", "MOD", "OPAR", "CPAR"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_lexer()
|
void register_lexer()
|
||||||
|
|
|
@ -26,7 +26,16 @@ static void test_parser(char const* oracle, char const* source)
|
||||||
static void test_parser_int()
|
static void test_parser_int()
|
||||||
{
|
{
|
||||||
test_parser("ROOT(INT[32])", " 32 ");
|
test_parser("ROOT(INT[32])", " 32 ");
|
||||||
|
|
||||||
test_parser("ROOT(INT[32],INT[-2],INT[24])", " 32 -2 24");
|
test_parser("ROOT(INT[32],INT[-2],INT[24])", " 32 -2 24");
|
||||||
|
|
||||||
|
test_parser("ROOT(ADD(INT[1],MUL(INT[2],INT[3])))",
|
||||||
|
" 1 + 2 * 3 ");
|
||||||
|
|
||||||
|
test_parser("ROOT(DIV(SUB(INT[1],INT[2]),INT[3]))",
|
||||||
|
" (1 - 2) / 3 ");
|
||||||
|
|
||||||
|
test_parser("ROOT(USUB(INT[32]))", " -(32) ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_parser()
|
void register_parser()
|
||||||
|
|
Loading…
Reference in New Issue