hare

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

commit a7ec0904d08b31115d40bd6960ff7905ac01a55b
parent 093f10edccd19044a215746f4df1b947cd6f647a
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 16 Apr 2021 14:42:14 -0400

hare::parse: implement (or finish) expression-list

Diffstat:
Mhare/parse/+test/expr.ha | 8++++++++
Mhare/parse/expr.ha | 43++++++++++++++++++++++++++++++++++---------
Mhare/unparse/expr.ha | 12+++++++++++-
3 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha @@ -21,6 +21,14 @@ "export fn main() void = void: int as uint: u16 is u8;\n"); }; +@test fn list() void = { + roundtrip("export fn main() void = { + 2 + 2; + call(); +}; +"); +}; + @test fn postfix() void = { roundtrip("export fn main() void = x.y;\n" "export fn main() void = x.y.z.q;\n" diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha @@ -3,10 +3,25 @@ use hare::lex::{ltok}; use hare::lex; use fmt; -// Parses an expression. +// Parses a expression. export fn expression(lexer: *lex::lexer) (ast::expr | error) = { - // TODO: if, for, switch, match, etc - return binarithm(lexer, void, 0); + let tok = match (peek(lexer, ltok::LBRACE, ltok::MATCH, ltok::SWITCH, + ltok::IF, ltok::FOR, ltok::BREAK, ltok::CONTINUE, + ltok::RETURN, ltok::LET, ltok::CONST)?) { + void => return binarithm(lexer, void, 0), + tok: lex::token => tok, + }; + return switch (tok.0) { + ltok::LBRACE => expression_list(lexer)?, + ltok::MATCH => abort(), // TODO + ltok::SWITCH => abort(), // TODO + ltok::IF => abort(), // TODO + ltok::FOR => abort(), // TODO + ltok::BREAK, ltok::CONTINUE, ltok::RETURN => + control_statement(lexer)?, + ltok::LET, ltok::CONST => abort(), // TODO + * => abort(), // Invariant + }; }; fn binarithm( @@ -16,6 +31,7 @@ fn binarithm( ) (ast::expr | error) = { // Precedence climbing parser // https://en.wikipedia.org/wiki/Operator-precedence_parser + // TODO: Incorporate assignment into this? let lvalue = match (lvalue) { void => cast(lexer, void)?, expr: ast::expr => expr, @@ -49,15 +65,23 @@ fn binarithm( }; fn builtin(lexer: *lex::lexer) (ast::expr | error) = { - match (peek(lexer, ltok::ALLOC, ltok::APPEND, ltok::FREE, + let tok = match (peek(lexer, ltok::ALLOC, ltok::APPEND, ltok::FREE, ltok::DELETE, ltok::ABORT, ltok::ASSERT, ltok::STATIC, ltok::SIZE, ltok::LEN, ltok::OFFSET)?) { - tok: lex::token => { - abort(); // TODO: Delegate as appropriate - }, - void => void, + tok: lex::token => tok, + void => return postfix(lexer, void), + }; + + return switch (tok.0) { + ltok::ALLOC => abort(), + ltok::APPEND => abort(), + ltok::DELETE => abort(), + ltok::FREE => abort(), + ltok::ASSERT => abort(), + ltok::STATIC => abort(), + ltok::SIZE, ltok::LEN, ltok::OFFSET => abort(), + * => abort(), // Invariant }; - return postfix(lexer, void); }; fn call(lexer: *lex::lexer, lvalue: ast::expr) (ast::expr | error) = { @@ -144,6 +168,7 @@ fn control_statement(lexer: *lex::lexer) (ast::expr | error) = { fn expression_list(lexer: *lex::lexer) (ast::expr | error) = { let items: ast::list_expr = []; + want(lexer, ltok::LBRACE)?; for (let more = true; more) { let tok = peek(lexer)? as lex::token; let item = switch (tok.0) { diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -93,7 +93,17 @@ export fn expr( e: ast::for_expr => abort(), e: ast::free_expr => abort(), e: ast::if_expr => abort(), - e: ast::list_expr => abort(), + e: ast::list_expr => { + let z = fmt::fprintf(out, "{{")?; + for (let i = 0z; i < len(e); i += 1) { + z += newline(out, indent + 1)?; + z += expr(out, indent + 1, *e[i])?; + z += fmt::fprintf(out, ";")?; + }; + z += newline(out, indent)?; + z += fmt::fprintf(out, "}}")?; + z; + }, e: ast::match_expr => abort(), e: ast::len_expr => abort(), e: ast::size_expr => abort(),