add support for statement lists (so that e.g. conditionals and function bodies can be defined)
This commit is contained in:
parent
f5db5076db
commit
f6fb1a3cb5
1 changed files with 80 additions and 3 deletions
83
lapis.c
83
lapis.c
|
@ -5,6 +5,13 @@
|
|||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
struct lapis_node_s;
|
||||
|
||||
typedef struct {
|
||||
size_t nnodes;
|
||||
struct lapis_node_s *nodes;
|
||||
} lapis_stmt_t;
|
||||
|
||||
typedef struct {
|
||||
enum lapis_ttype {
|
||||
LAPIS_TTYPE_NONE,
|
||||
|
@ -14,9 +21,14 @@ typedef struct {
|
|||
LAPIS_TTYPE_INT,
|
||||
LAPIS_TTYPE_BOOL,
|
||||
LAPIS_TTYPE_OPER,
|
||||
LAPIS_TTYPE_STMT_LIST,
|
||||
} type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
size_t nstmts;
|
||||
lapis_stmt_t *stmts;
|
||||
};
|
||||
struct {
|
||||
size_t len;
|
||||
char * str;
|
||||
|
@ -54,6 +66,13 @@ void lapis_node_print(const lapis_node_t *nodes, size_t idx) {
|
|||
case LAPIS_TTYPE_INT:
|
||||
printf("%ld", nodes[idx].value.i64);
|
||||
break;
|
||||
case LAPIS_TTYPE_STMT_LIST:
|
||||
for (size_t n=0; n < nodes[idx].value.nstmts; n++) {
|
||||
lapis_node_print(nodes[idx].value.stmts[n].nodes, nodes[idx].value.stmts[n].nnodes-1);
|
||||
fputs("; ", stdout);
|
||||
}
|
||||
fputs("} ", stdout);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( nodes[idx].rhs_idx != SIZE_MAX ) {
|
||||
|
@ -82,6 +101,8 @@ void lapis_token_free(lapis_token_t *token) {
|
|||
}
|
||||
}
|
||||
|
||||
lapis_node_t *lapis_parse_expr(size_t *nnodes, FILE *f);
|
||||
|
||||
lapis_token_t *lapis_parse_tokens(size_t *ntokens, FILE *f) {
|
||||
|
||||
size_t num_tokens = 0;
|
||||
|
@ -91,7 +112,62 @@ lapis_token_t *lapis_parse_tokens(size_t *ntokens, FILE *f) {
|
|||
_Bool end_of_expression = false;
|
||||
|
||||
int c;
|
||||
while ( (c = fgetc(f)) != EOF && !end_of_expression ) {
|
||||
while ( !end_of_expression && ((c = fgetc(f)) != EOF) ) {
|
||||
|
||||
if ( c == '{' ) {
|
||||
|
||||
size_t nstmts = 0;
|
||||
lapis_stmt_t *stmts = NULL;
|
||||
|
||||
while (1) {
|
||||
|
||||
//puts("++++++++++");
|
||||
size_t nnodes;
|
||||
lapis_node_t *nodes = lapis_parse_expr(&nnodes, f);
|
||||
//puts("----------");
|
||||
|
||||
if ( nodes == 0 ) break;
|
||||
|
||||
//printf("%lu: ", nstmts);
|
||||
//lapis_node_print(nodes, nnodes-1);
|
||||
//putchar('\n');
|
||||
|
||||
nstmts++;
|
||||
stmts = realloc(stmts, nstmts * sizeof(lapis_stmt_t));
|
||||
|
||||
if ( stmts == NULL ) {
|
||||
fprintf(stderr, "ERROR[%d]: realloc failed!\n", __LINE__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
stmts[nstmts-1] = (lapis_stmt_t) { .nnodes = nnodes, .nodes = nodes };
|
||||
}
|
||||
|
||||
if ( nstmts > 0 ) {
|
||||
|
||||
tokens = realloc(tokens, (num_tokens + 2) * sizeof(lapis_token_t));
|
||||
if ( tokens == NULL ) {
|
||||
fprintf(stderr, "ERROR [%s:%d]: realloc failed!\n", __func__, __LINE__);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
// need an operator to connect the statement list to the outer statement
|
||||
tokens[num_tokens].type = LAPIS_TTYPE_OPER;
|
||||
tokens[num_tokens].str = strdup("{");
|
||||
tokens[num_tokens].len = 1;
|
||||
|
||||
num_tokens++;
|
||||
|
||||
// need an operator to connect the statement list to the outer statement
|
||||
tokens[num_tokens].type = LAPIS_TTYPE_STMT_LIST;
|
||||
tokens[num_tokens].stmts = stmts;
|
||||
tokens[num_tokens].nstmts = nstmts;
|
||||
|
||||
num_tokens++;
|
||||
}
|
||||
|
||||
c = ' ';
|
||||
}
|
||||
|
||||
_Bool in_escape = false;
|
||||
|
||||
|
@ -108,9 +184,9 @@ lapis_token_t *lapis_parse_tokens(size_t *ntokens, FILE *f) {
|
|||
if ( c == EOF ) break;
|
||||
}
|
||||
|
||||
if ( c == ';' || (!in_escape && c == '\n') ) {
|
||||
if ( c == ';' || c == '}' || (!in_escape && c == '\n') ) {
|
||||
if ( num_tokens || c == '}' ) end_of_expression = true;
|
||||
c = ' ';
|
||||
if ( num_tokens ) end_of_expression = true;
|
||||
}
|
||||
|
||||
enum lapis_ttype cur_ttype;
|
||||
|
@ -290,6 +366,7 @@ lapis_node_t *lapis_parse_expr(size_t *nnodes, FILE *f) {
|
|||
fputs("'\n", stderr);
|
||||
goto ERROR;
|
||||
case 1ul*',':
|
||||
case 1ul*'{':
|
||||
oper_priorities[n] = 1;
|
||||
oper_arg_form[n] = 3;
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue