diff options
author | Alex Elder <elder@linaro.org> | 2021-10-01 18:23:35 -0500 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2021-10-04 14:18:03 -0500 |
commit | fae755df216617dd132bb72645e1287167726c72 (patch) | |
tree | c9c6768b6f17a2bb773c248fedaa1696c5c0d2f0 | |
parent | b793b576ffe27001ec2087dcffa0510da9d7734e (diff) |
parser: introduce qmi_identifier_parse()
Pull the code that extracts an identifier from the input stream out
of yylex() and into a new helper function. Create qmi_number_parse()
to do a similar thing for numbers.
Signed-off-by: Alex Elder <elder@linaro.org>
Message-Id: <20211001232338.769309-32-elder@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
-rw-r--r-- | parser.c | 103 |
1 files changed, 62 insertions, 41 deletions
@@ -205,20 +205,78 @@ static bool skip(char ch) return in_comment; } +/* Extract an identifier from input into the given buffer */ +static struct symbol *qmi_identifier_parse(char *buf, size_t size, char ch) +{ + char *p = buf; + + /* First character is known to be alphabetic */ + *p++ = ch; + while ((ch = input()) && (isalnum(ch) || ch == '_')) { + if (p - buf == size) { + buf[TOKEN_BUF_MIN] = '\0'; + yyerror("token too long: \"%s...\"", buf); + } + *p++ = ch; + } + unput(ch); + *p = '\0'; + + return symbol_find(buf); +} + /* Used for parsing octal numbers */ static int isodigit(int c) { return isdigit(c) && c < '9'; } +/* Extract a number from input into the given buffer; return base */ +static unsigned qmi_number_parse(char *buf, size_t size, char ch) +{ + int (*isvalid)(int); + char *p = buf; + unsigned base; + + /* First character is a digit; determine base and valid character set */ + if (ch == '0') { + *p++ = ch; + ch = input(); + if (ch == 'x' || ch == 'X') { + *p++ = ch; + ch = input(); + isvalid = isxdigit; + base = 16; + } else { + isvalid = isodigit; + base = 8; + } + } else { + isvalid = isdigit; + base = 10; + } + + /* First character is known to be a digit 0-9 */ + *p++ = ch; + while ((ch = input()) && isvalid(ch)) { + if (p - buf == size) { + buf[TOKEN_BUF_MIN] = '\0'; + yyerror("number too long: \"%s...\"", buf); + } + *p++ = ch; + } + unput(ch); + *p = '\0'; + + return base; +} + static struct token yylex() { struct symbol *sym; struct token token = {}; unsigned long long num; - int (*isvalid)(int); char buf[TOKEN_BUF_SIZE]; - char *p = buf; int base; char ch; @@ -226,22 +284,12 @@ static struct token yylex() ; if (isalpha(ch)) { - *p++ = ch; - while ((ch = input()) && (isalnum(ch) || ch == '_')) { - if (p - buf == sizeof(buf)) { - buf[TOKEN_BUF_MIN] = '\0'; - yyerror("token too long: \"%s...\"", buf); - } - *p++ = ch; - } - unput(ch); - *p = '\0'; + sym = qmi_identifier_parse(buf, sizeof(buf), ch); token.str = strdup(buf); if (!token.str) yyerror("strdup() failed in %s(), line %d\n", __func__, __LINE__); - sym = symbol_find(token.str); if (sym) { token.id = sym->token_id; switch (token.id) { @@ -261,34 +309,7 @@ static struct token yylex() return token; } else if (isdigit(ch)) { - /* Determine base and valid character set */ - if (ch == '0') { - *p++ = ch; - ch = input(); - if (ch == 'x' || ch == 'X') { - *p++ = ch; - ch = input(); - isvalid = isxdigit; - base = 16; - } else { - isvalid = isodigit; - base = 8; - } - } else { - isvalid = isdigit; - base = 10; - } - - *p++ = ch; - while ((ch = input()) && isvalid(ch)) { - if (p - buf == sizeof(buf)) { - buf[TOKEN_BUF_MIN] = '\0'; - yyerror("number too long: \"%s...\"", buf); - } - *p++ = ch; - } - unput(ch); - *p = '\0'; + base = qmi_number_parse(buf, sizeof(buf), ch); errno = 0; num = strtoull(buf, NULL, base); |