hare

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

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 };