harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit b12b2d604300464d407df43b8df2391de51886c6
parent 84825112a9ad95f67ea2a2076cce86574fccf90d
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Tue, 17 Nov 2020 10:58:24 -0500

lex: parse floating-point literals

Diffstat:
Minclude/lex.h | 7++++++-
Msrc/lex.c | 44+++++++++++++++++++++++++++++++++++---------
Msrc/parse.c | 5+++++
3 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/include/lex.h b/include/lex.h @@ -114,12 +114,17 @@ enum lexical_token { T_ERROR, }; +#ifndef __STDC_IEC_559__ +#error "harec requires IEC 60559 (IEEE 754) floating-point arithmetic" +#endif + struct token { enum lexical_token token; union { struct { uintmax_t u; intmax_t s; + double f; enum type_storage storage; } literal; char *name; @@ -135,7 +140,7 @@ struct lexer { FILE *in; char *buf; size_t bufsz, buflen; - uint32_t c; + uint32_t c[2]; }; void lex_init(struct lexer *lexer, FILE *f); diff --git a/src/lex.c b/src/lex.c @@ -129,9 +129,10 @@ static uint32_t next(struct lexer *lexer, bool buffer) { uint32_t c; - if (lexer->c != 0) { - c = lexer->c; - lexer->c = 0; + if (lexer->c[0] != 0) { + c = lexer->c[0]; + lexer->c[0] = lexer->c[1]; + lexer->c[1] = 0; } else { c = utf8_fgetch(lexer->in); } @@ -176,7 +177,8 @@ consume(struct lexer *lexer, ssize_t n) static void push(struct lexer *lexer, uint32_t c, bool buffer) { - lexer->c = c; + lexer->c[1] = lexer->c[0]; + lexer->c[0] = c; if (buffer) { consume(lexer, 1); } @@ -249,6 +251,12 @@ lex_literal(struct lexer *lexer, struct token *out) goto finalize; } isfloat = true; + if (!strchr(base, c = next(lexer, false))) { + push(lexer, c, false); + push(lexer, '.', true); + goto finalize; + } + push(lexer, c, false); break; case 'e': if (exp || suff) { @@ -276,9 +284,13 @@ lex_literal(struct lexer *lexer, struct token *out) finalize: out->token = T_LITERAL; - out->literal.storage = TYPE_STORAGE_INT; + if (isfloat) { + out->literal.storage = TYPE_STORAGE_F64; + } else { + out->literal.storage = TYPE_STORAGE_INT; + } if (suff) { - const char *suffs[] = { + const char *isuffs[] = { [TYPE_STORAGE_U8] = "u8", [TYPE_STORAGE_U16] = "u16", [TYPE_STORAGE_U32] = "u32", @@ -294,10 +306,23 @@ finalize: [TYPE_STORAGE_F32] = "f32", [TYPE_STORAGE_F64] = "f64", }; + + const char *fsuffs[] = { + [TYPE_STORAGE_F32] = "f32", + [TYPE_STORAGE_F64] = "f64", + }; bool isvalid = false; for (enum type_storage i = 0; - i < sizeof(suffs) / sizeof(suffs[0]); ++i) { - if (suffs[i] && strcmp(suff, suffs[i]) == 0) { + i < sizeof(isuffs) / sizeof(isuffs[0]); ++i) { + if (isuffs[i] && strcmp(suff, isuffs[i]) == 0) { + isvalid = true; + out->literal.storage = i; + break; + } + } + for (enum type_storage i = 0; + i < sizeof(fsuffs) / sizeof(fsuffs[0]); ++i) { + if (fsuffs[i] && strcmp(suff, fsuffs[i]) == 0) { isvalid = true; out->literal.storage = i; isfloat = true; @@ -347,7 +372,8 @@ finalize: break; case TYPE_STORAGE_F32: case TYPE_STORAGE_F64: - assert(0); // TODO + out->literal.f = strtod(lexer->buf, NULL); + break; default: assert(0); } diff --git a/src/parse.c b/src/parse.c @@ -38,6 +38,11 @@ parse(struct lexer *lexer, struct identifier *ns, struct ast_unit *unit) fprintf(stderr, "(%jd: %s)\n", tok.literal.s, type_storage_unparse(tok.literal.storage)); break; + case TYPE_STORAGE_F32: + case TYPE_STORAGE_F64: + fprintf(stderr, "(%lf: %s)\n", tok.literal.f, + type_storage_unparse(tok.literal.storage)); + break; default: assert(0); }