summaryrefslogtreecommitdiff
path: root/parse/tok.c
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2014-10-07 20:17:58 -0400
committerOri Bernstein <ori@eigenstate.org>2014-10-07 20:17:58 -0400
commit7088e222cf1b0ae17607ce0ac232067a172b851e (patch)
tree6617fb95823025f21b60cc0f0270548bad2730fb /parse/tok.c
parent6b45f935bd240eb066fe4edd49b8cd0853bc5dd9 (diff)
downloadmc-7088e222cf1b0ae17607ce0ac232067a172b851e.tar.gz
Keep track of source files as well as line numbers.
This makes our error messages better *AND* makes it easier to provide good debug info later.
Diffstat (limited to 'parse/tok.c')
-rw-r--r--parse/tok.c69
1 files changed, 39 insertions, 30 deletions
diff --git a/parse/tok.c b/parse/tok.c
index e39122e..db9895f 100644
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -17,7 +17,7 @@
#define End (-1)
char *filename;
-int line;
+Srcloc curloc;
Tok *curtok;
/* the file contents are stored globally */
@@ -75,7 +75,7 @@ static Tok *mktok(int tt)
t = zalloc(sizeof(Tok));
t->type = tt;
- t->line = line;
+ t->loc = curloc;
return t;
}
@@ -91,7 +91,7 @@ static void eatcomment(void)
int c;
depth = 0;
- startln = line;
+ startln = curloc.line;
while (1) {
c = next();
switch (c) {
@@ -107,10 +107,10 @@ static void eatcomment(void)
break;
/* have to keep line numbers synced */
case '\n':
- line++;
+ curloc.line++;
break;
case End:
- lfatal(line, 0, "File ended within comment starting at line %d", startln);
+ lfatal(curloc, 0, "File ended within comment starting at line %d", startln);
break;
}
if (depth == 0)
@@ -140,7 +140,7 @@ static void eatspace(void)
next();
} else if (ignorenl && c == '\n') {
next();
- line++;
+ curloc.line++;
ignorenl = 0;
} else if (isspace(c)) {
next();
@@ -287,7 +287,7 @@ static void appendc(char **buf, size_t *len, size_t *sz, uint32_t c)
else if (c < 0x200000)
charlen = 4;
else
- lfatal(line, 0, "invalid utf character '\\u{%x}'", c);
+ lfatal(curloc, 0, "invalid utf character '\\u{%x}'", c);
encode(charbuf, charlen, c);
for (i = 0; i < charlen; i++)
@@ -316,7 +316,7 @@ static int hexval(char c)
return c - 'A' + 10;
else if (c >= '0' && c <= '9')
return c - '0';
- lfatal(line, 0, "passed non-hex value '%c' to where hex was expected", c);
+ lfatal(curloc, 0, "passed non-hex value '%c' to where hex was expected", c);
return -1;
}
@@ -328,16 +328,16 @@ static int32_t unichar(void)
/* we've already seen the \u */
if (next() != '{')
- lfatal(line, 0, "\\u escape sequence without initial '{'");
+ lfatal(curloc, 0, "\\u escape sequence without initial '{'");
v = 0;
while (ishexval(peek())) {
c = next();
v = 16*v + hexval(c);
if (v > 0x10FFFF)
- lfatal(line, 0, "invalid codepoint for \\u escape sequence");
+ lfatal(curloc, 0, "invalid codepoint for \\u escape sequence");
}
if (next() != '}')
- lfatal(line, 0, "\\u escape sequence without ending '}'");
+ lfatal(curloc, 0, "\\u escape sequence without ending '}'");
return v;
}
@@ -361,10 +361,10 @@ static int decode(char **buf, size_t *len, size_t *sz)
case 'x': /* arbitrary hex */
c1 = next();
if (!isxdigit(c1))
- lfatal(line, 0, "expected hex digit, got %c", c1);
+ lfatal(curloc, 0, "expected hex digit, got %c", c1);
c2 = next();
if (!isxdigit(c2))
- lfatal(line, 0, "expected hex digit, got %c", c1);
+ lfatal(curloc, 0, "expected hex digit, got %c", c1);
v = 16*hexval(c1) + hexval(c2);
break;
case 'n': v = '\n'; break;
@@ -376,7 +376,7 @@ static int decode(char **buf, size_t *len, size_t *sz)
case 'v': v = '\v'; break;
case '\\': v = '\\'; break;
case '0': v = '\0'; break;
- default: lfatal(line, 0, "unknown escape code \\%c", c);
+ default: lfatal(curloc, 0, "unknown escape code \\%c", c);
}
append(buf, len, sz, v);
return v;
@@ -400,9 +400,9 @@ static Tok *strlit(void)
if (c == '"')
break;
else if (c == End)
- lfatal(line, 0, "Unexpected EOF within string");
+ lfatal(curloc, 0, "Unexpected EOF within string");
else if (c == '\n')
- lfatal(line, 0, "Newlines not allowed in strings");
+ lfatal(curloc, 0, "Newlines not allowed in strings");
else if (c == '\\')
decode(&buf, &len, &sz);
else
@@ -428,14 +428,14 @@ static uint32_t readutf(char c, char **buf, size_t *buflen, size_t *sz) {
else if ((c & 0xf8) == 0xf0)
len = 4;
else
- lfatal(line, 0, "Invalid utf8 encoded character constant");
+ lfatal(curloc, 0, "Invalid utf8 encoded character constant");
val = c & ((1 << (8 - len)) - 1);
append(buf, buflen, sz, c);
for (i = 1; i < len; i++) {
c = next();
if ((c & 0xc0) != 0x80)
- lfatal(line, 0, "Invalid utf8 codepoint in character literal");
+ lfatal(curloc, 0, "Invalid utf8 codepoint in character literal");
val = (val << 6) | (c & 0x3f);
append(buf, buflen, sz, c);
}
@@ -459,16 +459,16 @@ static Tok *charlit(void)
val = 0;
c = next();
if (c == End)
- lfatal(line, 0, "Unexpected EOF within char lit");
+ lfatal(curloc, 0, "Unexpected EOF within char lit");
else if (c == '\n')
- lfatal(line, 0, "Newlines not allowed in char lit");
+ lfatal(curloc, 0, "Newlines not allowed in char lit");
else if (c == '\\')
val = decode(&buf, &len, &sz);
else
val = readutf(c, &buf, &len, &sz);
append(&buf, &len, &sz, '\0');
if (next() != '\'')
- lfatal(line, 0, "Character constant with multiple characters");
+ lfatal(curloc, 0, "Character constant with multiple characters");
t = mktok(Tchrlit);
t->chrval = val;
@@ -614,7 +614,7 @@ static Tok *oper(void)
break;
default:
tt = Terror;
- lfatal(line, 0, "Junk character %c", c);
+ lfatal(curloc, 0, "Junk character %c", c);
break;
}
return mktok(tt);
@@ -644,10 +644,10 @@ static Tok *number(int base)
if (c == '.')
isfloat = 1;
else if (hexval(c) < 0 || hexval(c) > base)
- lfatal(line, 0, "Integer digit '%c' outside of base %d", c, base);
+ lfatal(curloc, 0, "Integer digit '%c' outside of base %d", c, base);
if (nbuf >= sizeof buf) {
buf[nbuf-1] = '\0';
- lfatal(line, 0, "number %s... too long to represent", buf);
+ lfatal(curloc, 0, "number %s... too long to represent", buf);
}
buf[nbuf++] = c;
}
@@ -674,7 +674,7 @@ nextsuffix:
switch (peek()) {
case 'u':
if (unsignedval == 1)
- lfatal(line, 0, "Duplicate 'u' integer specifier");
+ lfatal(curloc, 0, "Duplicate 'u' integer specifier");
next();
unsignedval = 1;
goto nextsuffix;
@@ -708,7 +708,7 @@ nextsuffix:
break;
default:
if (unsignedval)
- lfatal(line, 0, "Unrecognized character int type specifier after 'u'");
+ lfatal(curloc, 0, "Unrecognized character int type specifier after 'u'");
break;
}
}
@@ -762,7 +762,7 @@ static Tok *toknext()
if (c == End) {
t = mktok(0);
} else if (c == '\n') {
- line++;
+ curloc.line++;
next();
t = mktok(Tendln);
} else if (isalpha(c) || c == '_' || c == '$') {
@@ -780,7 +780,7 @@ static Tok *toknext()
}
if (!t || t->type == Terror)
- lfatal(line, 0, "Unable to parse token starting with %c", c);
+ lfatal(curloc, 0, "Unable to parse token starting with %c", c);
return t;
}
@@ -812,8 +812,8 @@ void tokinit(char *file)
}
fbufsz = nread;
- line = 1;
- fidx = 0;
+ curloc.line = 1;
+ curloc.file = 0;
close(fd);
filename = strdup(file);
}
@@ -825,3 +825,12 @@ int yylex(void)
yylval.tok = curtok;
return curtok->type;
}
+
+void yyerror(const char *s)
+{
+ fprintf(stderr, "%s:%d: %s", filename, curloc.line, s);
+ if (curtok->str)
+ fprintf(stderr, " near \"%s\"", curtok->str);
+ fprintf(stderr, "\n");
+ exit(1);
+}