hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mhare/parse/parse.ha | 50+++++++++++---------------------------------------
Ahare/parse/types.ha | 16++++++++++++++++
Ahare/parse/util.ha | 44++++++++++++++++++++++++++++++++++++++++++++
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); +};