ident.ha (1683B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use bufio; 5 use hare::ast; 6 use hare::lex; 7 use hare::lex::{ltok}; 8 use memio; 9 use strings; 10 11 // Parses a single identifier, possibly with a trailing ::, i.e. 'foo::bar::'. 12 // Returns the identifier and whether there's a trailing ::. 13 export fn ident_trailing(lexer: *lex::lexer) ((ast::ident, bool) | error) = { 14 let ident: []str = []; 15 let trailing = false; 16 const tok = want(lexer, ltok::NAME)?; 17 append(ident, tok.1 as str); 18 const loc = tok.2; 19 let z = len(ident[0]); 20 for (true) { 21 match (try(lexer, ltok::DOUBLE_COLON)?) { 22 case void => break; 23 case => void; // Grab the next ident 24 }; 25 z += 1; 26 let name = match (try(lexer, ltok::NAME)?) { 27 case let t: lex::token => 28 yield t.1 as str; 29 case void => 30 trailing = true; 31 break; 32 }; 33 append(ident, name); 34 z += len(name); 35 }; 36 if (z > ast::IDENT_MAX) { 37 ast::ident_free(ident: ast::ident); 38 return syntaxerr(loc, "Identifier exceeds maximum length"); 39 }; 40 return (ident: ast::ident, trailing); 41 }; 42 43 // Parses a single identifier, i.e. 'foo::bar::baz'. 44 export fn ident(lexer: *lex::lexer) (ast::ident | error) = { 45 let ident = ident_trailing(lexer)?; 46 synassert(lex::mkloc(lexer), !ident.1, "Unexpected trailing :: in ident")?; 47 return ident.0; 48 }; 49 50 // A convenience function which parses an identifier from a string, so the 51 // caller needn't provide a lexer instance. 52 export fn identstr(in: str) (ast::ident | error) = { 53 let in = memio::fixed(strings::toutf8(in)); 54 let sc = bufio::newscanner(&in); 55 defer bufio::finish(&sc); 56 let lexer = lex::init(&sc, "<string>"); 57 let ret = ident(&lexer); 58 want(&lexer, ltok::EOF)?; 59 return ret; 60 };