parse.ha (1919B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use fmt; 5 use lexical::lex; 6 use io; 7 use memio; 8 9 // All possible error types. 10 export type error = !lex::error; 11 12 // Requires the next token to have a matching ltok. Returns that token, or an 13 // error. 14 export fn want( 15 lexer: *lex::lexer, 16 want: str... 17 ) (*lex::token | error) = { 18 let tok = lex::next(lexer)?; 19 if (len(want) == 0) return tok; 20 for (let want .. want) if (tok.name == want) return tok; 21 22 let buf = memio::dynamic(); 23 defer io::close(&buf)!; 24 lex::unlex(lexer, tok); 25 for (let i = 0z; i < len(want); i += 1) { 26 fmt::fprintf(&buf, "'{}'", want[i])!; 27 if (i + 1 < len(want)) fmt::fprint(&buf, ", ")!; 28 }; 29 return lex::syntaxf(tok.start, 30 "Unexpected '{}', was expecting {}", 31 tok.name, memio::string(&buf)!); 32 }; 33 34 // Looks for a matching ltok from the lexer, and if not present, unlexes the 35 // token and returns void. If found, the token is consumed from the lexer and is 36 // returned. 37 export fn try( 38 lexer: *lex::lexer, 39 want: str... 40 ) (*lex::token | error | void) = { 41 let tok = lex::next(lexer)?; 42 assert(len(want) > 0); 43 for (let want .. want) if (tok.name == want) return tok; 44 lex::unlex(lexer, tok); 45 }; 46 47 // Looks for a matching ltok from the lexer, unlexes the token, and returns 48 // it; or void if it was not an ltok. 49 export fn peek( 50 lexer: *lex::lexer, 51 want: str... 52 ) (*lex::token | error | void) = { 53 let tok = lex::next(lexer)?; 54 lex::unlex(lexer, tok); 55 if (len(want) == 0) return tok; 56 for (let want .. want) if (tok.name == want) return tok; 57 }; 58 59 // Returns a syntax error if cond is false and void otherwise 60 export fn synassert( 61 loc: lex::location, 62 cond: bool, 63 msg: const str, 64 ) (void | error) = { 65 if (!cond) return lex::syntaxf(loc, msg); 66 }; 67 68 export fn loc_from(lexer: *lex::lexer, start: lex::location) lex::ast_location = { 69 return lex::ast_location { 70 start = start, 71 end = lex::prevloc(lexer), 72 }; 73 };