aboutsummaryrefslogtreecommitdiff
path: root/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.rs')
-rw-r--r--src/parser.rs40
1 files changed, 23 insertions, 17 deletions
diff --git a/src/parser.rs b/src/parser.rs
index d705a11..4ec8e57 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -4,7 +4,7 @@ use nom::{
4 character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, one_of}, 4 character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, one_of},
5 combinator::{map, opt, recognize, value}, 5 combinator::{map, opt, recognize, value},
6 error::ParseError, 6 error::ParseError,
7 multi::{many0, many0_count, many1, separated_list0, separated_list1}, 7 multi::{fold_many0, many0, many0_count, many1, separated_list0},
8 sequence::{delimited, pair, preceded, terminated, tuple}, 8 sequence::{delimited, pair, preceded, terminated, tuple},
9 IResult, Parser, 9 IResult, Parser,
10}; 10};
@@ -169,24 +169,27 @@ 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_atom, op, parse_mul); 172 let recursive = parse_binary(parse_field_access, op, parse_mul);
173 let base = parse_atom; 173 let base = parse_field_access;
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, Vec<Identifier>> { 177fn parse_field_access<'a>(i: &'a str) -> IResult<&'a str, Expr> {
178 let node = tag("node"); 178 let trailing = map(tuple((ws(char('.')), ws(parse_ident))), |(_, i)| i);
179 let dot = ws(char('.')); 179 let (i, base) = parse_atom(i)?;
180 let fields = separated_list1(ws(char('.')), map(parse_name, str::to_owned)); 180
181 map(tuple((node, dot, fields)), |(_, _, fields)| fields)(i) 181 fold_many0(
182 trailing,
183 move || base.clone(),
184 move |acc, new| Expr::FieldAccess(acc.boxed(), new),
185 )(i)
182} 186}
183 187
184fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> { 188fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> {
185 let inner = alt(( 189 let inner = alt((
186 map(parse_field_access, Expr::FieldAccess),
187 map(tag("node"), |_| Expr::Node), 190 map(tag("node"), |_| Expr::Node),
188 map(parse_block, Expr::Block), 191 map(parse_block, Expr::Block),
189 map(parse_if, Expr::IfExpr), 192 map(parse_if, Expr::If),
190 map(parse_call, Expr::Call), 193 map(parse_call, Expr::Call),
191 map(parse_lit, Expr::Lit), 194 map(parse_lit, Expr::Lit),
192 map(parse_ident, Expr::Ident), 195 map(parse_ident, Expr::Ident),
@@ -217,7 +220,7 @@ fn parse_block<'a>(i: &'a str) -> IResult<&'a str, Block> {
217 delimited(open, statements, close).parse(i) 220 delimited(open, statements, close).parse(i)
218} 221}
219 222
220fn parse_if<'a>(i: &'a str) -> IResult<&'a str, If> { 223fn parse_if<'a>(i: &'a str) -> IResult<&'a str, IfExpr> {
221 let if_ = delimited(multispace0, tag("if"), multispace1); 224 let if_ = delimited(multispace0, tag("if"), multispace1);
222 225
223 let open = char('('); 226 let open = char('(');
@@ -231,7 +234,7 @@ fn parse_if<'a>(i: &'a str) -> IResult<&'a str, If> {
231 234
232 map( 235 map(
233 tuple((if_, open, condition, close, then, else_)), 236 tuple((if_, open, condition, close, then, else_)),
234 |(_, _, condition, _, then, else_)| If { 237 |(_, _, condition, _, then, else_)| IfExpr {
235 condition: condition.boxed(), 238 condition: condition.boxed(),
236 then, 239 then,
237 else_: else_.unwrap_or_default(), 240 else_: else_.unwrap_or_default(),
@@ -571,7 +574,7 @@ mod test {
571 assert_eq!(parse_expr(r#" node "#), Ok(("", Expr::Node))); 574 assert_eq!(parse_expr(r#" node "#), Ok(("", Expr::Node)));
572 assert_eq!( 575 assert_eq!(
573 parse_expr(r#" node.foo "#), 576 parse_expr(r#" node.foo "#),
574 Ok(("", Expr::FieldAccess(vec!["foo".to_owned()]))) 577 Ok(("", Expr::FieldAccess(Expr::Node.boxed(), "foo".to_owned())))
575 ); 578 );
576 assert_eq!( 579 assert_eq!(
577 parse_expr( 580 parse_expr(
@@ -581,7 +584,10 @@ mod test {
581 ), 584 ),
582 Ok(( 585 Ok((
583 "", 586 "",
584 Expr::FieldAccess(vec!["foo".to_owned(), "bar".to_owned()]) 587 Expr::FieldAccess(
588 Expr::FieldAccess(Expr::Node.boxed(), "foo".to_owned()).boxed(),
589 "bar".to_owned()
590 )
585 )) 591 ))
586 ); 592 );
587 } 593 }
@@ -600,7 +606,7 @@ mod test {
600 ), 606 ),
601 Ok(( 607 Ok((
602 "", 608 "",
603 Expr::IfExpr(If { 609 Expr::If(IfExpr {
604 condition: Expr::Bin( 610 condition: Expr::Bin(
605 Expr::int(1).boxed(), 611 Expr::int(1).boxed(),
606 BinOp::Cmp(CmpOp::Eq), 612 BinOp::Cmp(CmpOp::Eq),
@@ -713,7 +719,7 @@ mod test {
713 parse_statement("if (true) { true; };"), 719 parse_statement("if (true) { true; };"),
714 Ok(( 720 Ok((
715 "", 721 "",
716 Statement::Bare(Expr::IfExpr(If { 722 Statement::Bare(Expr::If(IfExpr {
717 condition: Expr::true_().boxed(), 723 condition: Expr::true_().boxed(),
718 then: Block { 724 then: Block {
719 body: vec![Statement::Bare(Expr::true_())] 725 body: vec![Statement::Bare(Expr::true_())]
@@ -726,7 +732,7 @@ mod test {
726 parse_expr("if (true) { true; } else { true; }"), 732 parse_expr("if (true) { true; } else { true; }"),
727 Ok(( 733 Ok((
728 "", 734 "",
729 Expr::IfExpr(If { 735 Expr::If(IfExpr {
730 condition: Expr::true_().boxed(), 736 condition: Expr::true_().boxed(),
731 then: Block { 737 then: Block {
732 body: vec![Statement::Bare(Expr::true_())] 738 body: vec![Statement::Bare(Expr::true_())]