commit 1e3eccc3ec9aabd16f29bdb148bef3b6eae4c559
parent 93b292a28e6e17912eadc093661e0692fbfab704
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 16 Apr 2021 10:27:52 -0400
hare::parse: implement slicing expressions
Diffstat:
3 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha
@@ -33,6 +33,13 @@
"export fn main() void = x[10 + 10][20];\n");
};
+@test fn slice() void = {
+ roundtrip("export fn main() void = x[..];\n"
+ "export fn main() void = x[123..];\n"
+ "export fn main() void = x[123..321];\n"
+ "export fn main() void = x[..321];\n");
+};
+
@test fn unarithm() void = {
// TODO: object selectors/addr operator
roundtrip("export fn main() void = +void;\n"
diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha
@@ -164,6 +164,37 @@ fn expression_list(lexer: *lex::lexer) (ast::expr | error) = {
return items;
};
+fn indexing(lexer: *lex::lexer, lvalue: ast::expr) (ast::expr | error) = {
+ let is_slice = false;
+ let start: nullable *ast::expr = null, end: nullable *ast::expr = null;
+
+ match (try(lexer, ltok::SLICE)?) {
+ void => start = alloc(expression(lexer)?),
+ lex::token => is_slice = true,
+ };
+ if (!is_slice) match (try(lexer, ltok::SLICE)?) {
+ void => void,
+ lex::token => is_slice = true,
+ };
+ if (is_slice) match (peek(lexer, ltok::RBRACKET)?) {
+ lex::token => void,
+ void => end = alloc(expression(lexer)?),
+ };
+
+ want(lexer, ltok::RBRACKET)?;
+ return if (is_slice) ast::slice_expr {
+ object = alloc(lvalue),
+ start = start,
+ end = end,
+ } else ast::access_index {
+ object = alloc(lvalue),
+ index = {
+ assert(start != null && end == null);
+ start: *ast::expr;
+ },
+ };
+};
+
fn objsel(lexer: *lex::lexer) (ast::expr | error) = {
abort(); // TODO
};
@@ -213,15 +244,7 @@ fn postfix(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) =
tok: lex::token => switch (tok.0) {
ltok::LPAREN => call(lexer, lvalue)?,
ltok::DOT => postfix_dot(lexer, lvalue)?,
- ltok::LBRACKET => {
- // TODO: Slicing expressions
- let expr = ast::access_index {
- object = alloc(lvalue),
- index = alloc(expression(lexer)?),
- };
- want(lexer, ltok::RBRACKET)?;
- expr;
- },
+ ltok::LBRACKET => indexing(lexer, lvalue)?,
ltok::QUESTION => alloc(lvalue): ast::propagate_expr,
* => abort(),
},
diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha
@@ -103,7 +103,21 @@ export fn expr(
z + fmt::fprintf(out, "?")?;
},
e: ast::return_expr => abort(),
- e: ast::slice_expr => abort(),
+ e: ast::slice_expr => {
+ let z = expr(out, indent, *e.object)?;
+ z += fmt::fprint(out, "[")?;
+ z += match (e.start) {
+ null => 0z,
+ e: *ast::expr => expr(out, indent, *e)?,
+ };
+ z += fmt::fprint(out, "..")?;
+ z += match (e.end) {
+ null => 0z,
+ e: *ast::expr => expr(out, indent, *e)?,
+ };
+ z += fmt::fprint(out, "]")?;
+ z;
+ },
e: ast::switch_expr => abort(),
e: ast::unarithm_expr => {
let z = fmt::fprintf(out, "{}", switch (e.op) {