diff --git a/src/ast/build.rs b/src/ast/build.rs index 164cabd..c3847a3 100644 --- a/src/ast/build.rs +++ b/src/ast/build.rs @@ -1173,26 +1173,45 @@ fn build_primary_expression(file_id: usize, primary_expression_pair: Pair) fn build_object_access( file_id: usize, receiver: Expression, - navigations_pair: Pair, + object_access_pair: Pair, ) -> ObjectAccess { ObjectAccess { receiver: Box::new(receiver), navigations: ObjectNavigations( - navigations_pair + object_access_pair .into_inner() - .map(|identifier_pair| { - ObjectNavigation::Identifier(Box::new(expect_and_use( - file_id, - identifier_pair, - Rule::Identifier, - build_identifier, - ))) - }) + .map( + |property_or_index_pair| match property_or_index_pair.as_rule() { + Rule::ObjectProperty => { + build_object_property(file_id, property_or_index_pair) + } + Rule::ObjectIndex => build_object_index(file_id, property_or_index_pair), + _ => unreachable!(), + }, + ) .collect(), ), } } +fn build_object_property(file_id: usize, inner_pair: Pair) -> ObjectNavigation { + ObjectNavigation::Identifier(Box::new(expect_and_use( + file_id, + inner_pair.into_inner().next().unwrap(), + Rule::Identifier, + build_identifier, + ))) +} + +fn build_object_index(file_id: usize, inner_pair: Pair) -> ObjectNavigation { + ObjectNavigation::Index(Box::new(expect_and_use( + file_id, + inner_pair.into_inner().next().unwrap(), + Rule::Expression, + build_expression, + ))) +} + fn build_closure(file_id: usize, closure_pair: Pair) -> Closure { todo!() } @@ -1242,3 +1261,37 @@ fn build_double_quote_string(file_id: usize, pair: Pair) -> Literal { fn build_backtick_string(file_id: usize, pair: Pair) -> Literal { todo!() } + +#[cfg(test)] +mod tests { + use super::*; + use crate::parser::DeimosParser; + use indoc::indoc; + + fn assert_builds(src: &str) { + let parse_result = DeimosParser::parse(Rule::CompilationUnit, src); + if let Err(e) = parse_result { + panic!("Parsing failed.\n{}", e) + } else { + build_ast(0, parse_result.unwrap().next().unwrap()); + } + } + + #[test] + fn index_object() { + assert_builds(indoc! {" + fn main() { + let x = foo[a]; + } + "}) + } + + #[test] + fn object_index_and_call() { + assert_builds(indoc! {"\ + fn main() { + a[b]().c() + } + "}) + } +}