Precompute line number for each token

No functionality change
This commit is contained in:
Rui Ueyama 2020-04-20 22:23:11 +09:00
parent cd832a311e
commit 6647ad9b84
2 changed files with 26 additions and 9 deletions

View File

@ -41,6 +41,8 @@ struct Token {
int len; // Token length
Type *ty; // Used if TK_STR
char *str; // String literal contents including terminating '\0'
int line_no; // Line number
};
void error(char *fmt, ...);

View File

@ -19,7 +19,7 @@ void error(char *fmt, ...) {
//
// foo.c:10: x = y + 1;
// ^ <error message here>
static void verror_at(char *loc, char *fmt, va_list ap) {
static void verror_at(int line_no, char *loc, char *fmt, va_list ap) {
// Find a line containing `loc`.
char *line = loc;
while (current_input < line && line[-1] != '\n')
@ -29,12 +29,6 @@ static void verror_at(char *loc, char *fmt, va_list ap) {
while (*end != '\n')
end++;
// Get a line number.
int line_no = 1;
for (char *p = current_input; p < line; p++)
if (*p == '\n')
line_no++;
// Print out the line.
int indent = fprintf(stderr, "%s:%d: ", current_filename, line_no);
fprintf(stderr, "%.*s\n", (int)(end - line), line);
@ -50,15 +44,20 @@ static void verror_at(char *loc, char *fmt, va_list ap) {
}
void error_at(char *loc, char *fmt, ...) {
int line_no = 1;
for (char *p = current_input; p < loc; p++)
if (*p == '\n')
line_no++;
va_list ap;
va_start(ap, fmt);
verror_at(loc, fmt, ap);
verror_at(line_no, loc, fmt, ap);
}
void error_tok(Token *tok, char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
verror_at(tok->loc, fmt, ap);
verror_at(tok->line_no, tok->loc, fmt, ap);
}
// Consumes the current token if it matches `op`.
@ -222,6 +221,21 @@ static void convert_keywords(Token *tok) {
t->kind = TK_KEYWORD;
}
// Initialize line info for all tokens.
static void add_line_numbers(Token *tok) {
char *p = current_input;
int n = 1;
do {
if (p == tok->loc) {
tok->line_no = n;
tok = tok->next;
}
if (*p == '\n')
n++;
} while (*p++);
}
// Tokenize a given string and returns new tokens.
static Token *tokenize(char *filename, char *p) {
current_filename = filename;
@ -291,6 +305,7 @@ static Token *tokenize(char *filename, char *p) {
}
cur = cur->next = new_token(TK_EOF, p, p);
add_line_numbers(head.next);
convert_keywords(head.next);
return head.next;
}