diff options
Diffstat (limited to 'src/parser.rs')
-rw-r--r-- | src/parser.rs | 40 |
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 | ||
177 | fn parse_field_access<'a>(i: &'a str) -> IResult<&'a str, Vec<Identifier>> { | 177 | fn 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 | ||
184 | fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> { | 188 | fn 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 | ||
220 | fn parse_if<'a>(i: &'a str) -> IResult<&'a str, If> { | 223 | fn 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_())] |