commit 2ab02483e5356939d332ee44933787f6bc3e7cc2
parent 0a91e248b228a07bb36a7b14840ead5f64bcd45c
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 24 Mar 2021 10:14:18 -0400
hare::parse: improve error messages
Diffstat:
6 files changed, 50 insertions(+), 29 deletions(-)
diff --git a/hare/parse/decl.ha b/hare/parse/decl.ha
@@ -1,7 +1,8 @@
use ascii;
-use hare::lex;
-use hare::lex::{btoken};
use hare::ast;
+use hare::lex::{btoken};
+use hare::lex;
+use hare::unparse;
use strings;
fn attr_symbol(lexer: *lex::lexer) (str | error) = {
@@ -13,10 +14,12 @@ fn attr_symbol(lexer: *lex::lexer) (str | error) = {
l: lex::literal => match (l) {
s: str => (s, t.1),
* => return syntaxerr(t.1,
- "Expected string, got <something else>"),
+ "Unexpected {}, was expecting string",
+ lex::tokstr(t.0)),
},
* => return syntaxerr(t.1,
- "Expected string, got <something else>"),
+ "Unexpected {}, was expecting string",
+ lex::tokstr(t.0)),
},
};
let d = strings::iter(s.0);
@@ -122,7 +125,7 @@ fn decl_func(lexer: *lex::lexer) (ast::decl_func | error) = {
let body = switch (tok) {
btoken::EQUAL => {
synassert(ident_loc, len(ident) == 1,
- "Expected name, found identifier")?;
+ "Unexpected identifier, was expecting name")?;
const params = prototype.params;
for (let i = 0z; i < len(params); i += 1) {
synassert(params[i].loc,
@@ -158,14 +161,14 @@ export fn decls(lexer: *lex::lexer) ([]ast::decl | error) = {
};
let tok = match(lex::lex(lexer)?) {
io::EOF => return syntaxerr(mkloc(lexer),
- "Expected declaration, found EOF"),
+ "Unexpected EOF, was expecting declaration"),
t: (lex::token, lex::location) => t,
};
let btok = match (tok.0) {
b: lex::btoken => b,
- // TODO: Use fmt+lex::tokstr here:
* => return syntaxerr(mkloc(lexer),
- "Expected declaration, found <something else>"),
+ "Unexpected {}, was expecting declaration",
+ lex::tokstr(tok.0)),
};
let decl = switch (btok) {
btoken::CONST, btoken::LET, btoken::DEF =>
diff --git a/hare/parse/type.ha b/hare/parse/type.ha
@@ -86,7 +86,8 @@ fn primitive_type(lexer: *lex::lexer) (ast::_type | error) = {
let b = match (t.0) {
b: lex::btoken => b,
* => return syntaxerr(mkloc(lexer),
- "Expected primitive type, got <something else>"),
+ "Unexpected {}, was expecting primitive type",
+ lex::tokstr(t.0)),
};
let builtin = switch (b) {
btoken::CHAR, btoken::I16, btoken::I32, btoken::I64,
@@ -211,7 +212,7 @@ export fn _type(lexer: *lex::lexer) (ast::_type | error) = {
};
let t = match (lex::lex(lexer)?) {
io::EOF => return syntaxerr(mkloc(lexer),
- "Expected type, found EOF"),
+ "Unexpected EOF, was expecting type"),
t: (lex::token, lex::location) => t,
};
lex::unlex(lexer, t);
@@ -243,7 +244,8 @@ export fn _type(lexer: *lex::lexer) (ast::_type | error) = {
},
lex::name => alias_type(lexer)?,
* => return syntaxerr(mkloc(lexer),
- "Expected type, found <something>"),
+ "Unexpected {}, was expecting type",
+ lex::tokstr(t.0)),
};
match (try_btoken(lexer, btoken::LNOT)?) {
diff --git a/hare/parse/types.ha b/hare/parse/types.ha
@@ -1,3 +1,4 @@
+use fmt;
use hare::lex;
// All possible error types
@@ -6,8 +7,14 @@ export type error = lex::error!;
// Convert an error into a human-friendly string
export fn errstr(err: error) const str = lex::errstr(err: lex::error);
-fn syntaxerr(loc: lex::location, why: str) lex::error =
- (loc, why): lex::syntax: lex::error;
+fn syntaxerr(
+ loc: lex::location,
+ fmt: str,
+ args: fmt::formattable...
+) lex::error = {
+ let why = fmt::asprintf(fmt, args...);
+ return (loc, why): lex::syntax: lex::error;
+};
fn mkloc(lex: *lex::lexer) lex::location = lex::location {
path = lex.path,
diff --git a/hare/parse/util.ha b/hare/parse/util.ha
@@ -1,16 +1,19 @@
+use fmt;
use hare::ast;
use hare::lex;
+use io;
+use strio;
// Requires the next token to be a name. Returns that name, or an error.
fn want_name(lexer: *lex::lexer) (lex::name | error) = {
match (lex::lex(lexer)?) {
io::EOF => return syntaxerr(mkloc(lexer),
- "Expected name, found EOF"),
+ "Unexpected EOF, was expecting name"),
t: (lex::token, lex::location) => match (t.0) {
n: lex::name => return n,
- // TODO: Use fmt+lex::tokstr here:
* => return syntaxerr(mkloc(lexer),
- "Expected name, got <something else>"),
+ "Unexpected {}, was expecting name",
+ lex::tokstr(t.0)),
},
};
};
@@ -34,9 +37,8 @@ fn want_btoken(
lexer: *lex::lexer,
want: lex::btoken...
) (lex::btoken | error) = {
- match (lex::lex(lexer)?) {
- io::EOF => return syntaxerr(mkloc(lexer),
- "Expected name, found EOF"),
+ let tok: lex::token = match (lex::lex(lexer)?) {
+ io::EOF => return syntaxerr(mkloc(lexer), "Unexpected EOF"),
t: (lex::token, lex::location) => match (t.0) {
b: lex::btoken => {
if (len(want) == 0) {
@@ -47,15 +49,22 @@ fn want_btoken(
return b;
};
};
- // TODO: Use fmt+lex::tokstr here:
- return syntaxerr(mkloc(lexer),
- "Expected <something>, got <something else>");
+ t.0;
},
- // TODO: Use fmt+lex::tokstr here:
- * => return syntaxerr(mkloc(lexer),
- "Expected <something>, got <something else>"),
+ * => t.0,
},
};
+
+ let buf = strio::dynamic();
+ defer io::close(buf);
+ for (let i = 0z; i < len(want); i += 1) {
+ fmt::fprintf(buf, lex::tokstr(want[i]));
+ if (i + 1 < len(want)) {
+ fmt::fprint(buf, ", ");
+ };
+ };
+ return syntaxerr(mkloc(lexer), "Unexpected {}, was expecting {}",
+ lex::tokstr(tok), strio::string(buf));
};
// Looks for a matching btoken from the lexer, and if not present, unlexes the
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -315,12 +315,12 @@ hare_parse() {
if [ $testing -eq 0 ]
then
gensrcs_hare_parse
- gen_ssa hare::parse hare::ast hare::lex
+ gen_ssa hare::parse hare::ast hare::lex hare::unparse fmt
else
gensrcs_hare_parse \
+test.ha
gen_ssa hare::parse bufio fmt hare::ast hare::lex hare::unparse io \
- strings strio
+ strings strio fmt
fi
}
diff --git a/stdlib.mk b/stdlib.mk
@@ -400,7 +400,7 @@ stdlib_hare_parse_srcs= \
$(STDLIB)/hare/parse/unit.ha \
$(STDLIB)/hare/parse/util.ha
-$(HARECACHE)/hare/parse/hare_parse.ssa: $(stdlib_hare_parse_srcs) $(stdlib_rt) $(stdlib_hare_ast) $(stdlib_hare_lex)
+$(HARECACHE)/hare/parse/hare_parse.ssa: $(stdlib_hare_parse_srcs) $(stdlib_rt) $(stdlib_hare_ast) $(stdlib_hare_lex) $(stdlib_hare_unparse) $(stdlib_fmt)
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/hare/parse
@HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::parse \
@@ -1053,7 +1053,7 @@ testlib_hare_parse_srcs= \
$(STDLIB)/hare/parse/util.ha \
$(STDLIB)/hare/parse/+test.ha
-$(TESTCACHE)/hare/parse/hare_parse.ssa: $(testlib_hare_parse_srcs) $(testlib_rt) $(testlib_bufio) $(testlib_fmt) $(testlib_hare_ast) $(testlib_hare_lex) $(testlib_hare_unparse) $(testlib_io) $(testlib_strings) $(testlib_strio)
+$(TESTCACHE)/hare/parse/hare_parse.ssa: $(testlib_hare_parse_srcs) $(testlib_rt) $(testlib_bufio) $(testlib_fmt) $(testlib_hare_ast) $(testlib_hare_lex) $(testlib_hare_unparse) $(testlib_io) $(testlib_strings) $(testlib_strio) $(testlib_fmt)
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/parse
@HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::parse \