commit 80d03addce474489fb3be95293d454a667f4951f
parent 1dba69e7a4c6bfcc2ba87757fb046799d030bf6e
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 16 Apr 2021 09:20:50 -0400
hare::parse: implement struct field access
Diffstat:
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha
@@ -21,6 +21,12 @@
"export fn main() void = void: int as uint: u16 is u8;\n");
};
+@test fn postfix() void = {
+ roundtrip("export fn main() void = x.y;\n"
+ "export fn main() void = x.y.z.q;\n"
+ "export fn main() void = x().y;\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
@@ -1,6 +1,7 @@
use hare::ast;
use hare::lex::{ltok};
use hare::lex;
+use fmt;
// Parses an expression.
export fn expression(lexer: *lex::lexer) (ast::expr | error) = {
@@ -207,11 +208,11 @@ fn postfix(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) =
ex: ast::expr => ex,
};
- lvalue = match (try(lexer, ltok::LPAREN, ltok::DOT, ltok::LBRACKET,
- ltok::QUESTION)) {
+ lvalue = match (try(lexer, ltok::LPAREN,
+ ltok::DOT, ltok::LBRACKET, ltok::QUESTION)) {
tok: lex::token => switch (tok.0) {
ltok::LPAREN => call(lexer, lvalue)?,
- ltok::DOT => abort(), // TODO: Field access
+ ltok::DOT => postfix_dot(lexer, lvalue)?,
ltok::LBRACKET => abort(), // TODO: Indexing
ltok::QUESTION => abort(), // TODO: Propagation
* => abort(),
@@ -222,6 +223,18 @@ fn postfix(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) =
return postfix(lexer, lvalue);
};
+fn postfix_dot(lexer: *lex::lexer, lvalue: ast::expr) (ast::expr | error) = {
+ let tok = want(lexer, ltok::NAME, ltok::LIT_INT)?;
+ return switch (tok.0) {
+ ltok::NAME => ast::access_field {
+ object = alloc(lvalue),
+ field = tok.1 as str,
+ },
+ ltok::LIT_INT => abort(), // TODO: Tuple access
+ * => abort(),
+ };
+};
+
fn unarithm(lexer: *lex::lexer) (ast::expr | error) = {
const tok = match (try(lexer,
ltok::PLUS, ltok::MINUS, ltok::BNOT,
diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha
@@ -12,7 +12,10 @@ export fn expr(
e: ast::access_expr => match (e) {
id: ast::access_identifier => ident(out, id),
ix: ast::access_index => abort(),
- fl: ast::access_field => abort(),
+ fi: ast::access_field => {
+ let z = expr(out, indent, *fi.object)?;
+ z + fmt::fprintf(out, ".{}", fi.field)?;
+ },
tp: ast::access_tuple => abort(),
},
e: ast::alloc_expr => abort(),