str literal.

main
bog 2023-12-10 04:49:28 +01:00
parent dc4a74ad15
commit f4eb33c76c
13 changed files with 112 additions and 5 deletions

View File

@ -1,3 +1,3 @@
MOD ::= EXPR*
EXPR ::= BUILTIN
BUILTIN ::= num | bool
BUILTIN ::= num | bool | str

View File

@ -49,6 +49,15 @@ void compiler_run(compiler_t* compiler, node_t* node)
mod_push_instr(compiler->mod, op, param);
} break;
case NODE_STR: {
char* value = node->value.data;
value_t* val = tysy_new_str(compiler->tysy, value);
Opcode op = OP_PUSH;
param_t param = (param_t) mod_push_new_value(compiler->mod, val);
mod_push_instr(compiler->mod, op, param);
} break;
default: {
char msg[RZ_STR_LIMIT];
snprintf(msg, RZ_STR_LIMIT, "Unknown node '%s'",

View File

@ -36,6 +36,8 @@ node_t* lexer_try_new_next(lexer_t* lexer)
}
}
// Keywords
// ========
{
node_t* kw = lexer_try_new_keyword(lexer, "true", NODE_BOOL, 1);
if (kw) { return kw; }
@ -45,6 +47,12 @@ node_t* lexer_try_new_next(lexer_t* lexer)
if (kw) { return kw; }
}
// scan str
{
node_t* node = lexer_try_new_str(lexer);
if (node) { return node; }
}
// scan num
{
size_t cursor = lexer->cursor;
@ -171,3 +179,45 @@ node_t* lexer_try_new_keyword(lexer_t* lexer, char* kw,
return NULL;
}
node_t* lexer_try_new_str(lexer_t* lexer)
{
assert(lexer);
size_t cursor = lexer->cursor;
size_t len = strlen(lexer->source);
str_t res_str;
str_init(&res_str);
if (cursor >= len || lexer->source[cursor] != '"')
{
str_free(&res_str);
return NULL;
}
cursor++;
while (cursor < len
&& lexer->source[cursor] != '"')
{
str_push(&res_str, lexer->source[cursor]);
cursor++;
}
if (cursor >= len || lexer->source[cursor] != '"')
{
str_free(&res_str);
return NULL;
}
cursor++;
node_t* tok = malloc(sizeof(node_t));
node_init(tok, NODE_STR, res_str.data, lexer->line);
str_free(&res_str);
lexer->cursor = cursor;
return tok;
}

View File

@ -21,4 +21,6 @@ NodeType lexer_peek(lexer_t* lexer, int lookahead);
node_t* lexer_try_new_keyword(lexer_t* lexer, char* kw,
NodeType type, int has_value);
node_t* lexer_try_new_str(lexer_t* lexer);
#endif

View File

@ -6,7 +6,8 @@
#define NODE_TYPE(G) \
G(NODE_MOD), \
G(NODE_NUM), \
G(NODE_BOOL)
G(NODE_BOOL), \
G(NODE_STR)
RZ_ENUM_H(NodeType, NODE_TYPE);

View File

@ -57,7 +57,7 @@ node_t* parser_try_new_builtin(parser_t* parser)
assert(parser);
NodeType next = lexer_peek(parser->lexer, 1);
if (next == NODE_NUM || next == NODE_BOOL)
if (next == NODE_NUM || next == NODE_BOOL || next == NODE_STR)
{
return parser_try_new_consume(parser, next);
}

View File

@ -4,8 +4,7 @@
#include "commons.h"
#define TYPE_KIND(G) \
G(TYPE_NUM), \
G(TYPE_BOOL)
G(TYPE_NUM), G(TYPE_BOOL), G(TYPE_STR)
RZ_ENUM_H(TypeKind, TYPE_KIND);

View File

@ -18,6 +18,13 @@ void tysy_init(tysy_t* tysy)
type_init(ty, TYPE_BOOL);
tysy_register_new_type(tysy, "bool", ty);
}
// str
{
type_t* ty = malloc(sizeof(type_t));
type_init(ty, TYPE_STR);
tysy_register_new_type(tysy, "str", ty);
}
}
void tysy_free(tysy_t* tysy)
@ -83,3 +90,14 @@ value_t* tysy_new_bool(tysy_t* tysy, int value)
return val;
}
value_t* tysy_new_str(tysy_t* tysy, char* value)
{
assert(tysy);
value_t* val = malloc(sizeof(value_t));
value_init(val, tysy_try_find_type(tysy, "str"));
val->value.str = strdup(value);
return val;
}

View File

@ -18,5 +18,6 @@ type_t* tysy_try_find_type(tysy_t* tysy, char* name);
value_t* tysy_new_num(tysy_t* tysy, double value);
value_t* tysy_new_bool(tysy_t* tysy, int value);
value_t* tysy_new_str(tysy_t* tysy, char* value);
#endif

View File

@ -11,6 +11,11 @@ void value_init(value_t* value, type_t* type)
void value_free(value_t* value)
{
assert(value);
if (value->type->kind == TYPE_STR)
{
free(value->value.str);
}
}
int value_eq(value_t* value, value_t* rhs)
@ -30,6 +35,10 @@ int value_eq(value_t* value, value_t* rhs)
return value->value.bool == rhs->value.bool;
} break;
case TYPE_STR: {
return strcmp(value->value.str, rhs->value.str) == 0;
} break;
default: {
fprintf(stderr, "Cannot compare value of type '%s'.\n",
TypeKindStr[value->type->kind]);
@ -55,6 +64,10 @@ size_t value_str(value_t* value, char* buffer, size_t size)
return snprintf(buffer, size, "%s", value->value.bool ? "true" : "false");
break;
case TYPE_STR:
return snprintf(buffer, size, "\"%s\"", value->value.str);
break;
default: {
fprintf(stderr, "Cannot stringify unknown value of type '%s'.\n",
TypeKindStr[value->type->kind]);

View File

@ -9,6 +9,7 @@ typedef struct {
union {
double num;
int bool;
char* str;
} value;
} value_t;

View File

@ -93,3 +93,12 @@ Test(lexer, bool) {
"NUM[3]",
"BOOL[false]");
}
Test(lexer, str) {
test_lexer_ko("\"hello");
test_lexer_ko("hello\"");
test_lexer(" \"bonjour\" \" monde \"", 2,
"STR[bonjour]",
"STR[ monde ]");
}

View File

@ -62,3 +62,7 @@ Test(parser, num) {
Test(parser, bool) {
test_parser_ok("MOD(BOOL[true],BOOL[false])", "true false");
}
Test(parser, str) {
test_parser_ok("MOD(STR[bim bam bum])", " \"bim bam bum\"");
}