File: util.ha

package info (click to toggle)
hare-update 0.26.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,044 kB
  • sloc: makefile: 37; sh: 14
file content (79 lines) | stat: -rw-r--r-- 2,008 bytes parent folder | download
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);
	};
};