We'll need this when the compiler parses the entire patch, not just
an expression.
---
src/compiler/parser.y | 8 ++-
src/compiler/parser_helper.c | 34 ++++++++--
src/compiler/parser_itf.h | 4 +
src/compiler/scanner.h | 1 +
src/compiler/scanner.re | 21 +++++-
src/compiler/test/comment | 6 +-
src/compiler/test/error | 6 +-
src/compiler/test/location | 158 ++++++++++++++++++++++++++++++++++++++++++
src/compiler/test/number | 3 +-
src/compiler/test/wrap | 4 +-
10 files changed, 226 insertions(+), 19 deletions(-)
create mode 100755 src/compiler/test/location
diff --git a/src/compiler/parser.y b/src/compiler/parser.y
index 53695ed..acc6af7 100644
--- a/src/compiler/parser.y
+++ b/src/compiler/parser.y
@@ -85,7 +85,13 @@
%type node {struct ast_node *}
%destructor node { free($$); }
-%syntax_error { yy_parse_failed(yypParser); }
+%syntax_error {
+ if(!state->error_label) {
+ state->error_label = state->id->label;
+ state->error_lineno = state->id->lineno;
+ }
+ yy_parse_failed(yypParser);
+}
start ::= TOK_START_EXPR node(N). {
state->comm->parseout = N;
diff --git a/src/compiler/parser_helper.c b/src/compiler/parser_helper.c
index c959282..f75a1ec 100644
--- a/src/compiler/parser_helper.c
+++ b/src/compiler/parser_helper.c
@@ -24,12 +24,33 @@
#include "parser_itf.h"
#include "parser_helper.h"
+static char printable_char(unsigned char c)
+{
+ return c < ' ' || c > '~' ? '?' : c;
+}
+
+/*
+ * Since operators don't set "label" properly in unique(), we can't just print
+ * the whole string, but need to cut it at the first non-printable character.
+ */
+
+static int printable_label(const char *s)
+{
+ const char *p;
+
+ for(p = s; *p > ' '; p++);
+ return p-s;
+}
+
+
int fpvm_parse(const char *expr, int start_token, union parser_comm *comm)
{
struct scanner *s;
struct parser_state state = {
.comm = comm,
.success = 0,
+ .error_label = NULL,
+ .id = NULL,
};
int tok;
struct id *identifier;
@@ -42,14 +63,17 @@ int fpvm_parse(const char *expr, int start_token, union
parser_comm *comm)
while(tok != TOK_EOF) {
identifier = malloc(sizeof(struct id));
identifier->token = tok;
+ identifier->lineno = s->lineno;
if(tok == TOK_CONSTANT) {
identifier->constant = get_constant(s);
identifier->label = "";
} else {
identifier->label = get_token(s);
}
+ state.id = identifier;
if(tok == TOK_ERROR) {
- printf("FPVM: scan error\n");
+ printf("FPVM, line %d, near \"%c\": scan error\n",
+ s->lineno, printable_char(s->cursor[-1]));
ParseFree(p, free);
delete_scanner(s);
return 0;
@@ -61,10 +85,10 @@ int fpvm_parse(const char *expr, int start_token, union
parser_comm *comm)
ParseFree(p, free);
delete_scanner(s);
- if(!state.success) {
- printf("FPVM: parse error\n");
- return 0;
- }
+ if(!state.success)
+ printf("FPVM, line %d, near \"%.*s\": parse error\n",
+ state.error_lineno, printable_label(state.error_label),
+ state.error_label);
return state.success;
}
diff --git a/src/compiler/parser_itf.h b/src/compiler/parser_itf.h
index f36aab8..2de69ee 100644
--- a/src/compiler/parser_itf.h
+++ b/src/compiler/parser_itf.h
@@ -29,11 +29,15 @@ struct id {
int token;
const char *label;
float constant;
+ int lineno;
};
struct parser_state {
int success;
union parser_comm *comm;
+ const char *error_label;
+ int error_lineno;
+ const struct id *id; /* for error handling */
};
void *ParseAlloc(void *(*mallocProc)(size_t));
diff --git a/src/compiler/scanner.h b/src/compiler/scanner.h
index 627364a..d41b0c1 100644
--- a/src/compiler/scanner.h
+++ b/src/compiler/scanner.h
@@ -28,6 +28,7 @@ struct scanner {
unsigned char *old_cursor;
unsigned char *cursor;
unsigned char *limit;
+ int lineno;
};
struct scanner *new_scanner(unsigned char *input);
diff --git a/src/compiler/scanner.re b/src/compiler/scanner.re
index df59d3f..5d06096 100644
--- a/src/compiler/scanner.re
+++ b/src/compiler/scanner.re
@@ -41,7 +41,8 @@ struct scanner *new_scanner(unsigned char *input)
s->old_cursor = input;
s->cursor = input;
s->limit = input + strlen((char *)input);
-
+ s->lineno = 1;
+
return s;
}
@@ -50,6 +51,16 @@ void delete_scanner(struct scanner *s)
free(s);
}
+static int nls(const unsigned char *s, const unsigned char *end)
+{
+ int n = 0;
+
+ while(s != end)
+ if(*s++ == '\n')
+ n++;
+ return n;
+}
+
int scan(struct scanner *s)
{
std:
@@ -57,11 +68,15 @@ int scan(struct scanner *s)
s->old_cursor = s->cursor;
/*!re2c
- [\x20\n\r\t] { goto std; }
+ [\x20\r\t] { goto std; }
+ "\n" { s->lineno++;
+ goto std; }
"//"[^\n\x00]* { goto std; }
"/*"("*"*[^/\x00]|[^*\x00])*"*"+"/"
- { goto std; }
+ { s->lineno += nls(s->old_cursor,
+ s->cursor);
+ goto std; }
[0-9]+ { return TOK_CONSTANT; }
[0-9]+ "." [0-9]* { return TOK_CONSTANT; }
diff --git a/src/compiler/test/comment b/src/compiler/test/comment
index 1bec66c..3aeadc0 100755
--- a/src/compiler/test/comment
+++ b/src/compiler/test/comment
@@ -113,7 +113,7 @@ a = 9 /*/
b = a
EOF
expect <<EOF
-FPVM: parse error
+FPVM, line 1, near "*/": parse error
EOF
#------------------------------------------------------------------------------
@@ -123,14 +123,14 @@ a = b + c /* comment
d = e + f
EOF
expect <<EOF
-FPVM: parse error
+FPVM, line 1, near "*": parse error
EOF
#------------------------------------------------------------------------------
ptest_fail "comment: unterminated /* ... without newline" "a = b+c /* comment"
expect <<EOF
-FPVM: parse error
+FPVM, line 1, near "*": parse error
EOF
###############################################################################
diff --git a/src/compiler/test/error b/src/compiler/test/error
index c8d8749..e44af1d 100755
--- a/src/compiler/test/error
+++ b/src/compiler/test/error
@@ -7,7 +7,7 @@ ptest_fail "syntax error: x = backtick" <<EOF
x = \`
EOF
expect <<EOF
-FPVM: scan error
+FPVM, line 1, near "\`": scan error
EOF
#------------------------------------------------------------------------------
@@ -17,7 +17,7 @@ x = a b
EOF
expect <<EOF
x = a
-FPVM: parse error
+FPVM, line 1, near "b": parse error
EOF
#------------------------------------------------------------------------------
@@ -26,7 +26,7 @@ ptest_fail "syntax error: x = a + + b" <<EOF
x = a + + b
EOF
expect <<EOF
-FPVM: parse error
+FPVM, line 1, near "+": parse error
EOF
###############################################################################
diff --git a/src/compiler/test/location b/src/compiler/test/location
new file mode 100755
index 0000000..aabee2d
--- /dev/null
+++ b/src/compiler/test/location
@@ -0,0 +1,158 @@
+#!/bin/sh
+. ./Common
+
+###############################################################################
+
+ptest_fail "location: scanner, inside line" <<EOF
+a = b
+x = \` y
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2, near "\`": scan error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: scanner, beginning of line" <<EOF
+a = b
+\`x = y
+c = d
+EOF
+expect <<EOF
+FPVM, line 2, near "\`": scan error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: scanner, end of line" <<EOF
+a = b
+x = y\`
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2, near "\`": scan error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: parser, inside line" <<EOF
+a = b
+x = * y
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2, near "*": parse error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: parser, beginning of line" <<EOF
+a = b
+)x = y
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2, near ")x": parse error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: parser, end of line (1)" <<EOF
+a = b
+x = y(
+c = d
+EOF
+expect <<EOF
+a = b
+x = y
+FPVM, line 2, near "(": parse error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: parser, end of line (2)" <<EOF
+a = b
+x = )
+c = d
+EOF
+expect <<EOF
+a = b
+FPVM, line 2, near ")": parse error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: error is end of line" <<EOF
+a = b
+x =
+EOF
+expect <<EOF
+a = b
+FPVM, line 2, near "=": parse error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: error is EOF" "x="
+expect <<EOF
+FPVM, line 1, near "=": parse error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: error is identifier" <<EOF
+foo = this is an error
+EOF
+expect <<EOF
+foo = this
+FPVM, line 1, near "an": parse error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: 3rd line" <<EOF
+a = b
+c = d
+)
+EOF
+expect <<EOF
+a = b
+c = d
+FPVM, line 3, near ")": parse error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: 5th line, with // comments" <<EOF
+// assign a
+a = b
+// assign c
+c = d
+)
+EOF
+expect <<EOF
+a = b
+c = d
+FPVM, line 5, near ")": parse error
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "location: 4th line, with /*...*/ comments" <<EOF
+a = b /* some
+comment */
+c = d
+)
+EOF
+expect <<EOF
+a = b
+c = d
+FPVM, line 4, near ")": parse error
+EOF
+
+###############################################################################
diff --git a/src/compiler/test/number b/src/compiler/test/number
index db7fb10..2162eaf 100755
--- a/src/compiler/test/number
+++ b/src/compiler/test/number
@@ -20,7 +20,6 @@ b = 1.2
EOF
#------------------------------------------------------------------------------
-#------------------------------------------------------------------------------
ptest "number: c = .3" <<EOF
c = .3
@@ -53,7 +52,7 @@ ptest_fail "number: f = ." <<EOF
f = .
EOF
expect <<EOF
-FPVM: scan error
+FPVM, line 1, near ".": scan error
EOF
###############################################################################
diff --git a/src/compiler/test/wrap b/src/compiler/test/wrap
index 1e978ee..e3ed6c4 100755
--- a/src/compiler/test/wrap
+++ b/src/compiler/test/wrap
@@ -75,7 +75,7 @@ ptest_fail "wrap: one assignment containing semicolon (1)"
<<EOF
a = b +; c
EOF
expect <<EOF
-FPVM: parse error
+FPVM, line 1, near ";": parse error
EOF
#------------------------------------------------------------------------------
@@ -85,7 +85,7 @@ a = b; + c
EOF
expect <<EOF
a = b
-FPVM: parse error
+FPVM, line 1, near "+": parse error
EOF
###############################################################################
--
1.7.1
_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode