add char literals

This commit is contained in:
r4 2021-12-23 21:26:53 +01:00
parent a0842424ec
commit d67008cfbf
5 changed files with 58 additions and 5 deletions

3
ir.c
View File

@ -84,6 +84,9 @@ static void print_val(const Value *v) {
case TypeBool: case TypeBool:
printf("%s", v->Bool ? "true" : "false"); printf("%s", v->Bool ? "true" : "false");
break; break;
case TypeChar:
printf("'%c'", v->Char);
break;
default: default:
printf("(unknown type)"); printf("(unknown type)");
break; break;

37
lex.c
View File

@ -11,6 +11,7 @@ static void consume(Pos *p, char c);
static void emit(TokList *toks, const Pos *p, Tok t); static void emit(TokList *toks, const Pos *p, Tok t);
static void mark(Pos *p); static void mark(Pos *p);
static void mark_err(const Pos *p); static void mark_err(const Pos *p);
static char get_esc_char(char c);
static void consume(Pos *p, char c) { static void consume(Pos *p, char c) {
if (c == '\n') { if (c == '\n') {
@ -36,6 +37,23 @@ static void mark_err(const Pos *p) {
err_col = p->m_col; err_col = p->m_col;
} }
static char get_esc_char(char c) {
switch(c) {
case 'a': return '\a';
case 'b': return '\b';
case 'e': return '\033';
case 'f': return '\f';
case 'n': return '\n';
case 'r': return '\r';
case 't': return '\t';
case 'v': return '\v';
case '\\': return '\\';
case '\'': return '\'';
case '"': return '\"';
default: return 0;
}
}
TokList lex(const char *s) { TokList lex(const char *s) {
TokList toks; TokList toks;
toklist_init(&toks); toklist_init(&toks);
@ -248,6 +266,25 @@ TokList lex(const char *s) {
}); });
} }
continue; continue;
case '\'': {
consume(&pos, *(s++));
char c = s[0];
if (c == '\\') {
consume(&pos, *(s++));
c = get_esc_char(s[0]);
if (!c) {
set_err("Unrecognized escape sequence: '\\%c'", c);
return toks;
}
}
consume(&pos, *(s++));
if (s[0] != '\'') {
set_err("Unclosed char literal");
return toks;
}
emit(&toks, &pos, (Tok){ .kind = TokVal, .Val = { .type = { .kind = TypeChar, }, .Char = c, }, });
break;
}
default: default:
set_err("Unrecognized character: '%c'", s[0]); set_err("Unrecognized character: '%c'", s[0]);
return toks; return toks;

18
main.c
View File

@ -33,18 +33,25 @@ static void die(const char *fmt, ...) {
exit(1); exit(1);
} }
static Value fn_print(Value *args) { static Value fn_put(Value *args) {
switch (args[0].type.kind) { switch (args[0].type.kind) {
case TypeVoid: printf("(void)\n"); break; case TypeVoid: printf("(void)"); break;
case TypeFloat: printf("%f\n", args[0].Float); break; case TypeFloat: printf("%f", args[0].Float); break;
case TypeInt: printf("%zd\n", args[0].Int); break; case TypeInt: printf("%zd", args[0].Int); break;
case TypeBool: printf("%s\n", args[0].Bool ? "true" : "false"); break; case TypeBool: printf("%s", args[0].Bool ? "true" : "false"); break;
case TypeChar: printf("%c", args[0].Char); break;
default: default:
ASSERT_UNREACHED(); ASSERT_UNREACHED();
} }
return (Value){0}; return (Value){0};
} }
static Value fn_print(Value *args) {
fn_put(args);
printf("\n");
return (Value){0};
}
static Value fn_int(Value *args) { static Value fn_int(Value *args) {
Value ret = { Value ret = {
.type.kind = TypeInt, .type.kind = TypeInt,
@ -141,6 +148,7 @@ int main(int argc, const char **argv) {
print_toks(&tokens); print_toks(&tokens);
/* parse tokens into IR code */ /* parse tokens into IR code */
BuiltinFunc funcs[] = { BuiltinFunc funcs[] = {
{ .name = "put", .side_effects = true, .n_args = 1, .func = fn_put, },
{ .name = "print", .side_effects = true, .n_args = 1, .func = fn_print, }, { .name = "print", .side_effects = true, .n_args = 1, .func = fn_print, },
{ .name = "int", .side_effects = false, .n_args = 1, .func = fn_int, }, { .name = "int", .side_effects = false, .n_args = 1, .func = fn_int, },
{ .name = "float", .side_effects = false, .n_args = 1, .func = fn_float, }, { .name = "float", .side_effects = false, .n_args = 1, .func = fn_float, },

3
tok.c
View File

@ -115,6 +115,9 @@ void print_toks(TokList *l) {
case TypeBool: case TypeBool:
printf(": " C_ICYAN "%s" C_RESET, i->tok.Val.Bool ? "true" : "false"); printf(": " C_ICYAN "%s" C_RESET, i->tok.Val.Bool ? "true" : "false");
break; break;
case TypeChar:
printf(": " C_ICYAN "'%c'" C_RESET, i->tok.Val.Char);
break;
default: default:
printf(" " C_ICYAN "(unknown type)" C_RESET); printf(" " C_ICYAN "(unknown type)" C_RESET);
break; break;

2
tok.h
View File

@ -12,6 +12,7 @@ typedef struct Type {
TypeFloat, TypeFloat,
TypeInt, TypeInt,
TypeBool, TypeBool,
TypeChar,
} kind; } kind;
/*union { /*union {
@ -25,6 +26,7 @@ typedef struct Value {
double Float; double Float;
ssize_t Int; ssize_t Int;
bool Bool; bool Bool;
char Char;
}; };
} Value; } Value;