aboutsummaryrefslogtreecommitdiff
path: root/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.rs')
-rw-r--r--src/parser.rs118
1 files changed, 111 insertions, 7 deletions
diff --git a/src/parser.rs b/src/parser.rs
index 4ec8e57..15d03fe 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -169,28 +169,51 @@ fn parse_mul<'a>(i: &'a str) -> IResult<&'a str, Expr> {
169 let div = parse_op("/", BinOp::Arith(ArithOp::Div)); 169 let div = parse_op("/", BinOp::Arith(ArithOp::Div));
170 let mod_ = parse_op("%", BinOp::Arith(ArithOp::Mod)); 170 let mod_ = parse_op("%", BinOp::Arith(ArithOp::Mod));
171 let op = alt((mul, div, mod_)); 171 let op = alt((mul, div, mod_));
172 let recursive = parse_binary(parse_field_access, op, parse_mul); 172 let recursive = parse_binary(parse_field_or_index, op, parse_mul);
173 let base = parse_field_access; 173 let base = parse_field_or_index;
174 alt((recursive, base)).parse(i) 174 alt((recursive, base)).parse(i)
175} 175}
176 176
177fn parse_field_access<'a>(i: &'a str) -> IResult<&'a str, Expr> { 177fn parse_field_or_index<'a>(i: &'a str) -> IResult<&'a str, Expr> {
178 let trailing = map(tuple((ws(char('.')), ws(parse_ident))), |(_, i)| i); 178 enum FieldOrIndex {
179 Field(String),
180 Index(Expr),
181 }
182
179 let (i, base) = parse_atom(i)?; 183 let (i, base) = parse_atom(i)?;
180 184
185 let field = map(tuple((ws(char('.')), ws(parse_ident))), |(_, i)| {
186 FieldOrIndex::Field(i)
187 });
188 let index = map(
189 tuple((ws(char('[')), parse_expr, ws(char(']')))),
190 |(_, idx, _)| FieldOrIndex::Index(idx),
191 );
192
181 fold_many0( 193 fold_many0(
182 trailing, 194 alt((field, index)),
183 move || base.clone(), 195 move || base.clone(),
184 move |acc, new| Expr::FieldAccess(acc.boxed(), new), 196 move |acc, new| match new {
197 FieldOrIndex::Field(f) => Expr::FieldAccess(acc.boxed(), f),
198 FieldOrIndex::Index(idx) => Expr::Index(acc.boxed(), idx.boxed()),
199 },
185 )(i) 200 )(i)
186} 201}
187 202
203fn parse_list<'a>(i: &'a str) -> IResult<&'a str, List> {
204 let open = ws(char('['));
205 let items = separated_list0(char(','), parse_expr);
206 let close = ws(char(']'));
207 map(tuple((open, items, close)), |(_, items, _)| List { items }).parse(i)
208}
209
188fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> { 210fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> {
189 let inner = alt(( 211 let inner = alt((
190 map(tag("node"), |_| Expr::Node), 212 map(tag("node"), |_| Expr::Node),
191 map(parse_block, Expr::Block), 213 map(parse_block, Expr::Block),
192 map(parse_if, Expr::If), 214 map(parse_if, Expr::If),
193 map(parse_call, Expr::Call), 215 map(parse_call, Expr::Call),
216 map(parse_list, Expr::List),
194 map(parse_lit, Expr::Lit), 217 map(parse_lit, Expr::Lit),
195 map(parse_ident, Expr::Ident), 218 map(parse_ident, Expr::Ident),
196 map(parse_unit, |_| Expr::Unit), 219 map(parse_unit, |_| Expr::Unit),
@@ -254,7 +277,8 @@ fn parse_type<'a>(i: &'a str) -> IResult<&'a str, Type> {
254 let int = value(Type::Integer, tag("int")); 277 let int = value(Type::Integer, tag("int"));
255 let string = value(Type::String, tag("string")); 278 let string = value(Type::String, tag("string"));
256 let bool_ = value(Type::Boolean, tag("bool")); 279 let bool_ = value(Type::Boolean, tag("bool"));
257 alt((int, string, bool_)).parse(i) 280 let list = value(Type::List, tag("list"));
281 alt((int, string, bool_, list)).parse(i)
258} 282}
259 283
260fn parse_declaration<'a>(i: &'a str) -> IResult<&'a str, Declaration> { 284fn parse_declaration<'a>(i: &'a str) -> IResult<&'a str, Declaration> {
@@ -510,6 +534,27 @@ mod test {
510 ) 534 )
511 )) 535 ))
512 ); 536 );
537 assert_eq!(
538 parse_expr("a[0]"),
539 Ok((
540 "",
541 Expr::Index(Expr::Ident("a".to_owned()).boxed(), Expr::int(0).boxed())
542 ))
543 );
544 assert_eq!(
545 parse_expr("children(node)[0]"),
546 Ok((
547 "",
548 Expr::Index(
549 Expr::Call(Call {
550 function: "children".to_owned(),
551 parameters: vec![Expr::Node]
552 })
553 .boxed(),
554 Expr::int(0).boxed()
555 )
556 ))
557 );
513 } 558 }
514 559
515 #[test] 560 #[test]
@@ -544,6 +589,22 @@ mod test {
544 }) 589 })
545 )) 590 ))
546 ); 591 );
592 assert_eq!(
593 parse_statement(r#"list a =["a", "b", "c"]; "#),
594 Ok((
595 "",
596 Statement::Declaration(Declaration {
597 ty: Type::List,
598 name: "a".to_owned(),
599 init: Some(
600 Expr::List(List {
601 items: vec![Expr::str("a"), Expr::str("b"), Expr::str("c"),]
602 })
603 .boxed()
604 )
605 })
606 ))
607 );
547 } 608 }
548 609
549 #[test] 610 #[test]
@@ -624,6 +685,49 @@ mod test {
624 ); 685 );
625 } 686 }
626 687
688 #[test]
689 fn test_parse_index() {
690 assert_eq!(
691 parse_expr(
692 r#"
693 a[0]
694 "#
695 ),
696 Ok((
697 "",
698 Expr::Index(Expr::Ident("a".to_owned()).boxed(), Expr::int(0).boxed()),
699 ))
700 );
701 assert_eq!(
702 parse_expr(r#"node.children[idx]"#),
703 Ok((
704 "",
705 Expr::Index(
706 Expr::FieldAccess(Expr::Node.boxed(), Identifier::from("children")).boxed(),
707 Expr::Ident("idx".to_owned()).boxed()
708 )
709 ))
710 );
711 assert_eq!(
712 parse_expr(r#"foo[i].bar[j]"#),
713 Ok((
714 "",
715 Expr::Index(
716 Expr::FieldAccess(
717 Expr::Index(
718 Expr::Ident("foo".to_owned()).boxed(),
719 Expr::Ident("i".to_owned()).boxed()
720 )
721 .boxed(),
722 "bar".to_owned()
723 )
724 .boxed(),
725 Expr::Ident("j".to_owned()).boxed()
726 ),
727 ))
728 );
729 }
730
627 // #[test] 731 // #[test]
628 // fn test_skip_query() { 732 // fn test_skip_query() {
629 // assert_eq!( 733 // assert_eq!(