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