commit 957cdf0e7229eb3b3e968d9e7260ac85659ed4dd
parent cd711543cce22ff401faed8287b4191cf683f3b1
Author: Drew DeVault <sir@cmpwn.com>
Date: Mon, 22 Feb 2021 13:33:24 -0500
hare::parse: simplify parse::ident
Diffstat:
3 files changed, 71 insertions(+), 39 deletions(-)
diff --git a/hare/parse/parse.ha b/hare/parse/parse.ha
@@ -1,52 +1,24 @@
use hare::ast;
use hare::lex;
-// All possible error types
-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);
-
// Parses a single identifier, i.e. foo::bar::baz
export fn ident(lexer: *lex::lexer) (ast::ident | error) = {
let ident = ast::ident { ... }, cur = &ident;
for (true) {
- let tok = lex::lex(lexer);
- match (tok) {
- io::EOF => abort(), // TODO: Syntax error
- err: lex::error => return err,
- t: (lex::token, lex::location) => match (t.0) {
- n: lex::name => cur.name = n: str,
- * => {
- lex::unlex(lexer, t);
- break;
- },
- },
+ cur.name = match (want_name(lexer)) {
+ err: error => return err,
+ n: lex::name => n: str,
};
- tok = lex::lex(lexer);
- match (tok) {
- io::EOF => break,
- err: lex::error => return err,
- t: (lex::token, lex::location) => match (t.0) {
- b: lex::btoken => switch (b) {
- hare::lex::btoken::DOUBLE_COLON => {
- let new = alloc(*ast::ident,
- ast::ident { ... });
- cur.ns = new;
- cur = new;
- },
- * => {
- lex::unlex(lexer, t);
- break;
- },
- },
- * => {
- lex::unlex(lexer, t);
- break;
- },
- },
+ match (try_btoken(lexer, hare::lex::btoken::DOUBLE_COLON)) {
+ err: error => return err,
+ void => break,
+ * => void, // Grab the next ident
};
+
+ let new = alloc(*ast::ident, ast::ident { ... });
+ cur.ns = new;
+ cur = new;
};
return ident;
};
diff --git a/hare/parse/types.ha b/hare/parse/types.ha
@@ -0,0 +1,16 @@
+use hare::lex;
+
+// All possible error types
+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 mkloc(lex: *lex::lexer) lex::location = lex::location {
+ path = lex.path,
+ line = lex.loc.0,
+ col = lex.loc.1,
+};
diff --git a/hare/parse/util.ha b/hare/parse/util.ha
@@ -0,0 +1,44 @@
+use hare::ast;
+use hare::lex;
+
+// 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"),
+ err: lex::error => return err,
+ 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>"),
+ },
+ };
+};
+
+// Looks for a matching btoken from the lexer, and if not present, unlexes the
+// token and returns void. If found, the token is consumed from the lexer and is
+// returned.
+fn try_btoken(
+ lexer: *lex::lexer,
+ want: lex::btoken...
+) (lex::btoken | error | void) = {
+ let tok = lex::lex(lexer);
+ let tuple = match (tok) {
+ io::EOF => return,
+ err: lex::error => return err,
+ t: (lex::token, lex::location) => {
+ match (t.0) {
+ b: lex::btoken =>
+ for (let i = 0z; i < len(want); i += 1) {
+ if (b == want[i]) {
+ return b;
+ };
+ },
+ * => void,
+ };
+ t;
+ },
+ };
+ lex::unlex(lexer, tuple);
+};