summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Phillips <david@sighup.nz>2018-08-01 20:21:37 +1200
committerDavid Phillips <david@sighup.nz>2018-08-01 20:29:38 +1200
commit328e34077a2017d4017f907ac69c7ed5d6c160d4 (patch)
tree1795fd0d10293320dae0854b5b1d34a59e8fdbec
parent70c76b708308c72956e83163b2819be69f725a7e (diff)
downloadhence-328e34077a2017d4017f907ac69c7ed5d6c160d4.tar.xz
Trim leading whitespace from contextual error, detect EOF
Side-note that the token location tuple maintains the correct column number to include the whitespace in the source file. Side-side note: tabs are counted as one column but many editors will count them as whatever the tabstop/tabwidth is.
-rw-r--r--common.c8
-rw-r--r--lexer.c7
-rw-r--r--lexer.h1
-rw-r--r--parser.c30
4 files changed, 39 insertions, 7 deletions
diff --git a/common.c b/common.c
index 96c9b72..c0e0af4 100644
--- a/common.c
+++ b/common.c
@@ -7,13 +7,19 @@ indicate_file_area(FILE* fd, size_t line, size_t column, size_t span) {
char margin[] = " ";
/* FIXME use proper line counting, not this hack */
char buf[1024];
+ char *line_start = &buf;
+
rewind(fd);
for (; line; line--) {
fgets(buf, sizeof(buf), fd);
}
+ while (*line_start == '\t' || *line_start == ' ') {
+ line_start++;
+ }
+
fputs(margin, stderr);
- fputs(buf, stderr);
+ fputs(line_start, stderr);
/* corner case (still needed?) - buf was just return */
if (strlen(buf) == 1 && buf[0] == '\n') {
diff --git a/lexer.c b/lexer.c
index a8b7716..d9810a5 100644
--- a/lexer.c
+++ b/lexer.c
@@ -53,6 +53,7 @@ static char buf[BUFFER_SIZE];
static FILE* fd;
static size_t line_number = 0;
static size_t column_number = 0;
+static size_t leading_whitespace_len = 0;
static struct token *tok_start = NULL;
static struct token *tok_cursor = NULL;
@@ -64,6 +65,7 @@ get_current_loc(void) {
struct location l;
l.line = line_number;
l.column = column_number + 1;
+ l.leading_whitespace_len = leading_whitespace_len;
return l;
}
@@ -187,6 +189,8 @@ lex_colon(void) {
static int
lex_line(void) {
size_t length = strlen(buf);
+ leading_whitespace_len = 0;
+
while (column_number < length && column_number < strlen(buf)) {
switch (buf[column_number]) {
case ':':
@@ -195,6 +199,9 @@ lex_line(void) {
case ' ':
case '\t':
eat_whitespace();
+ if (leading_whitespace_len == 0) {
+ leading_whitespace_len = column_number;
+ }
break;
case '\r':
case '\n':
diff --git a/lexer.h b/lexer.h
index 2e27ffa..3ce15f4 100644
--- a/lexer.h
+++ b/lexer.h
@@ -19,6 +19,7 @@ enum TOKEN_TYPE {
struct location {
size_t line;
size_t column;
+ size_t leading_whitespace_len;
};
struct token {
diff --git a/parser.c b/parser.c
index 618df1a..f16af6c 100644
--- a/parser.c
+++ b/parser.c
@@ -14,9 +14,16 @@ static FILE* fd;
static struct token *cursor;
static const char *filename;
-#define emit(...) fprintf(stderr, "%s at (%zd,%zd): ", filename, cursor->loc.line, cursor->loc.column);\
- fprintf(stderr, __VA_ARGS__);\
- indicate_file_area(fd, cursor->loc.line, cursor->loc.column, cursor->span)
+/* FIXME change to varadic fuction */
+#define emit(...) \
+ if (cursor) { \
+ fprintf(stderr, "%s at (%zd,%zd): ", filename, cursor->loc.line, cursor->loc.column); \
+ fprintf(stderr, __VA_ARGS__); \
+ indicate_file_area(fd, cursor->loc.line, cursor->loc.column - cursor->loc.leading_whitespace_len, cursor->span); \
+ } else { \
+ fprintf(stderr, "%s: ", filename); \
+ fprintf(stderr, __VA_ARGS__); \
+ }
//static struct op_lookup uop_handlers[] = {
@@ -42,9 +49,13 @@ expect(enum TOKEN_TYPE e) {
char *expected_desc = "(internal error)";
char *observed_desc = "(internal error)";
- if (cursor->type != e) {
+ if (!cursor || cursor->type != e) {
expected_desc = get_token_description(e);
- observed_desc = get_token_description(cursor->type);
+ if (cursor) {
+ observed_desc = get_token_description(cursor->type);
+ } else {
+ observed_desc = "end of file";
+ }
emit("Error: Expected %s, got %s\n", expected_desc, observed_desc);
return 1;
}
@@ -54,7 +65,9 @@ expect(enum TOKEN_TYPE e) {
static void
kerchunk() {
- cursor = cursor->next;
+ if (cursor) {
+ cursor = cursor->next;
+ }
}
int
@@ -64,6 +77,11 @@ parse(const char *fname, FILE *f, struct token *t) {
filename = fname;
cursor = t;
+ /* Eat leading EOL tokens */
+ while (cursor && cursor->type == TOK_EOL) {
+ kerchunk();
+ }
+
if (expect(TOK_MODULE)) {
return 1;
}