add support for statement lists (so that e.g. conditionals and function bodies can be defined)

This commit is contained in:
icst 2024-06-18 00:00:26 -04:00
parent f5db5076db
commit f6fb1a3cb5

83
lapis.c
View file

@ -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;