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 71 72 73 74 75 76 77 78 79
|
// SPDX-License-Identifier: MPL-2.0
// (c) Hare authors <https://harelang.org>
use common;
use common::{ltok};
use fmt;
use io;
use memio;
use vNEXT::lex;
// Requires the next token to have a matching ltok. Returns that token, or an
// error.
export fn want(lexer: *lex::lexer, want: common::ltok...) (common::token | error) = {
let tok = lex::lex(lexer)?;
if (len(want) == 0) {
return tok;
};
for (let i = 0z; i < len(want); i += 1) {
if (tok.0 == want[i]) {
return tok;
};
};
let buf = memio::dynamic();
defer io::close(&buf)!;
for (let i = 0z; i < len(want); i += 1) {
const tstr = if (want[i] == common::ltok::NAME) "name"
else common::tokstr((want[i], void, lex::mkloc(lexer)));
fmt::fprintf(&buf, "'{}'", tstr)!;
if (i + 1 < len(want)) {
fmt::fprint(&buf, ", ")!;
};
};
lex::unlex(lexer, tok);
return syntaxerr(lex::mkloc(lexer), "Unexpected '{}', was expecting {}",
common::tokstr(tok), memio::string(&buf)!);
};
// Looks for a matching ltok 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.
export fn try(
lexer: *lex::lexer,
want: common::ltok...
) (common::token | error | void) = {
let tok = lex::lex(lexer)?;
assert(len(want) > 0);
for (let i = 0z; i < len(want); i += 1) {
if (tok.0 == want[i]) {
return tok;
};
};
lex::unlex(lexer, tok);
};
// Looks for a matching ltok from the lexer, unlexes the token, and returns
// it; or void if it was not an ltok.
export fn peek(
lexer: *lex::lexer,
want: common::ltok...
) (common::token | error | void) = {
let tok = lex::lex(lexer)?;
lex::unlex(lexer, tok);
if (len(want) == 0) {
return tok;
};
for (let i = 0z; i < len(want); i += 1) {
if (tok.0 == want[i]) {
return tok;
};
};
};
// Returns a syntax error if cond is false and void otherwise
export fn synassert(loc: common::location, cond: bool, msg: str) (void | error) = {
if (!cond) {
return syntaxerr(loc, "{}", msg);
};
};
|