@@ -117,6 +117,16 @@ enum l2_opcode { | |||
*/ | |||
L2_OP_ALLOC_NAMESPACE, | |||
/* | |||
* Set a namespace's name to a value. | |||
* Pop <key> | |||
* Pop <val> | |||
* Read <ns> | |||
* Assign <val> to <ns[<key>]> | |||
* Push <val> | |||
*/ | |||
L2_OP_NAMESPACE_SET, | |||
/* | |||
* Halt execution. | |||
*/ |
@@ -2,7 +2,17 @@ | |||
#define L2_GEN_H | |||
#include "../io.h" | |||
#include "../strset.h" | |||
void l2_gen_stack_frame(struct l2_bufio_writer *writer); | |||
struct l2_generator { | |||
struct l2_strset atoms; | |||
struct l2_strset strings; | |||
struct l2_bufio_writer writer; | |||
}; | |||
void l2_gen_init(struct l2_generator *gen); | |||
void l2_gen_free(struct l2_generator *gen); | |||
void l2_gen_stack_frame(struct l2_generator *gen); | |||
void l2_gen_assignment(struct l2_generator *gen, char **ident); | |||
#endif |
@@ -12,9 +12,11 @@ enum l2_token_kind { | |||
L2_TOK_CLOSE_BRACKET, | |||
L2_TOK_COMMA, | |||
L2_TOK_PERIOD, | |||
L2_TOK_COLON_EQ, | |||
L2_TOK_EOF, | |||
L2_TOK_NUMBER, | |||
L2_TOK_STRING, | |||
L2_TOK_IDENT, | |||
L2_TOK_ERROR, | |||
}; | |||
@@ -2,20 +2,8 @@ | |||
#define L2_PARSE_H | |||
#include "lex.h" | |||
#include "../io.h" | |||
#include "../strset.h" | |||
#include "gen/gen.h" | |||
struct l2_parse_state { | |||
struct l2_lexer *lexer; | |||
struct l2_bufio_writer writer; | |||
struct l2_strset atoms; | |||
struct l2_strset strings; | |||
}; | |||
void l2_parse_init( | |||
struct l2_parse_state *state, | |||
struct l2_lexer *lexer, struct l2_io_writer *w); | |||
void l2_parse_free(struct l2_parse_state *state); | |||
void l2_parse_program(struct l2_parse_state *state); | |||
void l2_parse_program(struct l2_lexer *lexer, struct l2_generator *gen); | |||
#endif |
@@ -14,7 +14,7 @@ struct l2_strset { | |||
void l2_strset_init(struct l2_strset *set); | |||
void l2_strset_free(struct l2_strset *set); | |||
size_t l2_strset_put_move(struct l2_strset *set, char **str); | |||
size_t l2_strset_put(struct l2_strset *set, char **str); | |||
size_t l2_strset_put_copy(struct l2_strset *set, const char *str); | |||
size_t l2_strset_get(struct l2_strset *set, const char *str); | |||
@@ -2,10 +2,27 @@ | |||
#include "bytecode.h" | |||
static void put(struct l2_bufio_writer *writer, l2_word word) { | |||
l2_bufio_put_n(writer, &word, sizeof(word)); | |||
static void put(struct l2_generator *gen, l2_word word) { | |||
l2_bufio_put_n(&gen->writer, &word, sizeof(word)); | |||
} | |||
void l2_gen_stack_frame(struct l2_bufio_writer *writer) { | |||
put(writer, L2_OP_ALLOC_NAMESPACE); | |||
void l2_gen_init(struct l2_generator *gen) { | |||
l2_strset_init(&gen->atoms); | |||
l2_strset_init(&gen->strings); | |||
} | |||
void l2_gen_free(struct l2_generator *gen) { | |||
l2_strset_free(&gen->atoms); | |||
l2_strset_free(&gen->strings); | |||
} | |||
void l2_gen_stack_frame(struct l2_generator *gen) { | |||
put(gen, L2_OP_ALLOC_NAMESPACE); | |||
} | |||
void l2_gen_assignment(struct l2_generator *gen, char **ident) { | |||
size_t atom_id = l2_strset_put(&gen->atoms, ident); | |||
put(gen, L2_OP_PUSH); | |||
put(gen, atom_id); | |||
put(gen, L2_OP_NAMESPACE_SET); | |||
} |
@@ -20,12 +20,16 @@ const char *l2_token_kind_name(enum l2_token_kind kind) { | |||
return "comma"; | |||
case L2_TOK_PERIOD: | |||
return "period"; | |||
case L2_TOK_COLON_EQ: | |||
return "period"; | |||
case L2_TOK_EOF: | |||
return "end-of-file"; | |||
case L2_TOK_NUMBER: | |||
return "number"; | |||
case L2_TOK_STRING: | |||
return "string"; | |||
case L2_TOK_IDENT: | |||
return "ident"; | |||
case L2_TOK_ERROR: | |||
return "error"; | |||
} | |||
@@ -54,6 +58,11 @@ void l2_lexer_init(struct l2_lexer *lexer, struct l2_io_reader *r) { | |||
l2_bufio_reader_init(&lexer->reader, r); | |||
} | |||
static int peek_ch(struct l2_lexer *lexer) { | |||
int ch = l2_bufio_peek(&lexer->reader, 1); | |||
return ch; | |||
} | |||
static int read_ch(struct l2_lexer *lexer) { | |||
int ch = l2_bufio_get(&lexer->reader); | |||
lexer->ch += 1; | |||
@@ -137,6 +146,55 @@ static void read_string(struct l2_lexer *lexer, struct l2_token *tok) { | |||
} | |||
} | |||
static void read_ident(struct l2_lexer *lexer, struct l2_token *tok) { | |||
tok->kind = L2_TOK_IDENT; | |||
tok->v.str = malloc(16); | |||
if (tok->v.str == NULL) { | |||
tok->kind = L2_TOK_ERROR; | |||
tok->v.str = "Allocaton failure"; | |||
return; | |||
} | |||
size_t size = 16; | |||
size_t idx = 0; | |||
while (1) { | |||
int ch = peek_ch(lexer); | |||
if (is_whitespace(ch)) { | |||
return; | |||
} | |||
switch (ch) { | |||
case '(': | |||
case ')': | |||
case '{': | |||
case '}': | |||
case '[': | |||
case ']': | |||
case ',': | |||
case '.': | |||
case ':': | |||
case EOF: | |||
return; | |||
} | |||
tok->v.str[idx++] = (char)read_ch(lexer); | |||
if (idx >= size) { | |||
size *= 2; | |||
char *newbuf = realloc(tok->v.str, size); | |||
if (newbuf == NULL) { | |||
free(tok->v.str); | |||
tok->kind = L2_TOK_ERROR; | |||
tok->v.str = "Allocation failure"; | |||
return; | |||
} | |||
tok->v.str = newbuf; | |||
} | |||
} | |||
} | |||
static void read_tok(struct l2_lexer *lexer, struct l2_token *tok) { | |||
skip_whitespace(lexer); | |||
@@ -177,6 +235,22 @@ static void read_tok(struct l2_lexer *lexer, struct l2_token *tok) { | |||
tok->kind = L2_TOK_PERIOD; | |||
break; | |||
case ':': | |||
{ | |||
ch = read_ch(lexer); | |||
switch (ch) { | |||
case '=': | |||
tok->kind = L2_TOK_COLON_EQ; | |||
break; | |||
default: | |||
tok->kind = L2_TOK_ERROR; | |||
tok->v.str = "Unexpected character"; | |||
break; | |||
} | |||
} | |||
break; | |||
case EOF: | |||
tok->kind = L2_TOK_EOF; | |||
break; | |||
@@ -184,6 +258,10 @@ static void read_tok(struct l2_lexer *lexer, struct l2_token *tok) { | |||
case '"': | |||
read_string(lexer, tok); | |||
break; | |||
default: | |||
read_ident(lexer, tok); | |||
break; | |||
} | |||
} | |||
@@ -2,20 +2,25 @@ | |||
#include "gen/gen.h" | |||
void l2_parse_init( | |||
struct l2_parse_state *state, | |||
struct l2_lexer *lexer, struct l2_io_writer *w) { | |||
state->lexer = lexer; | |||
l2_bufio_writer_init(&state->writer, w); | |||
l2_strset_init(&state->atoms); | |||
l2_strset_init(&state->strings); | |||
} | |||
static void parse_expression(struct l2_lexer *lexer, struct l2_generator *gen) { | |||
struct l2_token *tok = l2_lexer_peek(lexer, 1); | |||
struct l2_token *tok2 = l2_lexer_peek(lexer, 2); | |||
void l2_parse_free(struct l2_parse_state *state) { | |||
l2_strset_free(&state->atoms); | |||
l2_strset_free(&state->strings); | |||
if (tok->kind == L2_TOK_IDENT && tok2->kind == L2_TOK_COLON_EQ) { | |||
parse_expression(lexer, gen); | |||
l2_gen_assignment(gen, &tok->v.str); | |||
} | |||
} | |||
void l2_parse_program(struct l2_parse_state *state) { | |||
l2_gen_stack_frame(&state->writer); | |||
void l2_parse_program(struct l2_lexer *lexer, struct l2_generator *gen) { | |||
l2_gen_stack_frame(gen); | |||
while (1) { | |||
struct l2_token *tok = l2_lexer_peek(lexer, 1); | |||
if (tok->kind == L2_TOK_EOF) { | |||
break; | |||
} | |||
parse_expression(lexer, gen); | |||
} | |||
} |
@@ -67,7 +67,7 @@ void l2_strset_free(struct l2_strset *set) { | |||
free(set->vals); | |||
} | |||
size_t l2_strset_put_move(struct l2_strset *set, char **str) { | |||
size_t l2_strset_put(struct l2_strset *set, char **str) { | |||
if (set->len >= set->size / 2) { | |||
grow(set); | |||
} |