hare

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

commit 36690cd889efe83159a2bf37b8ca1a3f77d37ee9
parent f7e05b481992ab16992fc6eb99f7afcb0bc01ae0
Author: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Date:   Tue,  8 Mar 2022 19:43:32 +0100

haredoc: error out on invalid trailing chars in parseident

`haredoc hare::parse+*&}{` was previously interpreted as `haredoc
hare::parse` and wasn't throwing an error.

Signed-off-by: Bor Grošelj Simić <bor.groseljsimic@telemach.net>

Diffstat:
Mcmd/haredoc/main.ha | 24++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/cmd/haredoc/main.ha b/cmd/haredoc/main.ha @@ -207,8 +207,9 @@ export fn main() void = { }; // Nearly identical to parse::identstr, except alphanumeric lexical tokens are -// converted to strings. For example, this function will parse `rt::abort` as a -// valid identifier. +// converted to strings and there must be no trailing tokens that don't belong +// to the ident in the string. For example, this function will parse `rt::abort` +// as a valid identifier. fn parseident(in: str) (ast::ident | parse::error) = { const buf = bufio::fixed(strings::toutf8(in), io::mode::READ); const lexer = lex::init(&buf, "<string>"); @@ -228,10 +229,19 @@ fn parseident(in: str) (ast::ident | parse::error) = { }; append(ident, name); z += len(name); - if (lex::lex(&lexer)?.0 != lex::ltok::DOUBLE_COLON) { + const tok = lex::lex(&lexer)?; + switch (tok.0) { + case lex::ltok::EOF => break; + case lex::ltok::DOUBLE_COLON => + z += 1; + case => + lex::unlex(&lexer, tok); + const loc = lex::mkloc(&lexer); + const why = fmt::asprintf("Unexpected '{}' in ident\n", + lex::tokstr(tok)); + return (loc, why): lex::syntax: parse::error; }; - z += 1; }; if (z > ast::IDENT_MAX) { const loc = lex::mkloc(&lexer); @@ -329,3 +339,9 @@ fn emit(ctx: *context) (void | error) = { case format::GEMTEXT => abort(); // TODO }; }; + +@test fn parseident() void = { + assert(parseident("hare::lex") is ast::ident); + assert(parseident("strings::dup*{}&@") is parse::error); + assert(parseident("foo::bar::") is parse::error); +};