diff --git a/frontend/lexer.c b/frontend/lexer.c index d432b05..df5673c 100644 --- a/frontend/lexer.c +++ b/frontend/lexer.c @@ -10,12 +10,14 @@ #include #include +#include #include #include #include #include #include "frontend/token.h" #include "frontend/lexer.h" +#include "common/ptrbox.h" /* * Test if a given character counts as a whitespace character @@ -142,6 +144,61 @@ lexer_consume(struct quip_state *state, bool skip_ws) return '\0'; } +/* + * Scan a name and create a token if valid + * + * @state: Quip state + * @lc: Last character + * @tokres: Token result written here + * + * Returns zero on success + */ +static int +lexer_scan_name(struct quip_state *state, int lc, struct token *tokres) +{ + char c, *buf; + size_t bufsz, bufcap; + + if (state == NULL || tokres == NULL) { + return -1; + } + + if (!isalpha(lc) && lc != '_') { + return -1; + } + + bufsz = 0; + bufcap = 8; + if ((buf = malloc(bufcap)) == NULL) { + return -1; + } + + buf[bufsz++] = lc; + for (;;) { + c = lexer_consume(state, false); + if (!isalnum(c) && c != '_') { + buf[bufsz] = '\0'; + lexer_putback(state, c); + break; + } + + buf[bufsz++] = c; + if (bufsz >= bufcap - 1) { + bufcap += 8; + buf = realloc(buf, bufcap); + } + + if (buf == NULL) { + return -1; + } + } + + tokres->type = TT_NAME; + tokres->s = ptrbox_strdup(&state->ptrbox, buf); + free(buf); + return 0; +} + int lexer_scan(struct quip_state *state, struct token *tokres) { @@ -170,6 +227,12 @@ lexer_scan(struct quip_state *state, struct token *tokres) lexer_putback(state, c); tokres->type = TT_COLON; return 0; + default: + if (lexer_scan_name(state, c, tokres) == 0) { + return 0; + } + + break; } return -1; diff --git a/include/frontend/token.h b/include/frontend/token.h index 5189b65..bc298f6 100644 --- a/include/frontend/token.h +++ b/include/frontend/token.h @@ -31,6 +31,7 @@ struct token { tt_t type; union { char c; + char *s; }; };