aboutsummaryrefslogtreecommitdiff
path: root/src/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.rs')
-rw-r--r--src/parser.rs58
1 files changed, 55 insertions, 3 deletions
diff --git a/src/parser.rs b/src/parser.rs
index 3a020dc..d705a11 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -1,10 +1,10 @@
1use nom::{ 1use nom::{
2 branch::alt, 2 branch::alt,
3 bytes::complete::tag, 3 bytes::complete::{is_not, tag},
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}, 7 multi::{many0, many0_count, many1, separated_list0, separated_list1},
8 sequence::{delimited, pair, preceded, terminated, tuple}, 8 sequence::{delimited, pair, preceded, terminated, tuple},
9 IResult, Parser, 9 IResult, Parser,
10}; 10};
@@ -21,6 +21,11 @@ where
21 delimited(multispace0, inner, multispace0) 21 delimited(multispace0, inner, multispace0)
22} 22}
23 23
24// TODO use this
25fn _parse_comment<'a>(i: &'a str) -> IResult<&'a str, ()> {
26 value((), pair(tag("//"), is_not("\n\r")))(i)
27}
28
24fn parse_unit<'a>(i: &'a str) -> IResult<&'a str, ()> { 29fn parse_unit<'a>(i: &'a str) -> IResult<&'a str, ()> {
25 let open = char('('); 30 let open = char('(');
26 let close = char(')'); 31 let close = char(')');
@@ -169,8 +174,16 @@ fn parse_mul<'a>(i: &'a str) -> IResult<&'a str, Expr> {
169 alt((recursive, base)).parse(i) 174 alt((recursive, base)).parse(i)
170} 175}
171 176
177fn parse_field_access<'a>(i: &'a str) -> IResult<&'a str, Vec<Identifier>> {
178 let node = tag("node");
179 let dot = ws(char('.'));
180 let fields = separated_list1(ws(char('.')), map(parse_name, str::to_owned));
181 map(tuple((node, dot, fields)), |(_, _, fields)| fields)(i)
182}
183
172fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> { 184fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> {
173 let inner = alt(( 185 let inner = alt((
186 map(parse_field_access, Expr::FieldAccess),
174 map(tag("node"), |_| Expr::Node), 187 map(tag("node"), |_| Expr::Node),
175 map(parse_block, Expr::Block), 188 map(parse_block, Expr::Block),
176 map(parse_if, Expr::IfExpr), 189 map(parse_if, Expr::IfExpr),
@@ -337,7 +350,7 @@ fn parse_pattern<'a>(i: &str) -> IResult<&str, Pattern> {
337 tuple((parse_modifier, multispace0, parse_ident)), 350 tuple((parse_modifier, multispace0, parse_ident)),
338 |(modifier, _, kind)| Pattern::Node(NodePattern { modifier, kind }), 351 |(modifier, _, kind)| Pattern::Node(NodePattern { modifier, kind }),
339 ); 352 );
340 alt((begin, end, node)).parse(i) 353 ws(alt((begin, end, node))).parse(i)
341} 354}
342 355
343pub fn parse_stanza<'a>(i: &str) -> IResult<&str, Stanza> { 356pub fn parse_stanza<'a>(i: &str) -> IResult<&str, Stanza> {
@@ -358,6 +371,25 @@ pub fn parse_file(i: &str) -> IResult<&str, Vec<Stanza>> {
358mod test { 371mod test {
359 use super::*; 372 use super::*;
360 373
374 // test helpers
375 impl Expr {
376 pub fn int(int: i128) -> Expr {
377 Self::Lit(Literal::Int(int))
378 }
379
380 pub fn str(s: &str) -> Expr {
381 Self::Lit(Literal::Str(s.to_owned()))
382 }
383
384 pub const fn false_() -> Expr {
385 Self::Lit(Literal::Bool(false))
386 }
387
388 pub const fn true_() -> Expr {
389 Self::Lit(Literal::Bool(true))
390 }
391 }
392
361 #[test] 393 #[test]
362 fn test_parse_unit() { 394 fn test_parse_unit() {
363 assert_eq!(parse_unit("()"), Ok(("", ()))) 395 assert_eq!(parse_unit("()"), Ok(("", ())))
@@ -535,6 +567,26 @@ mod test {
535 } 567 }
536 568
537 #[test] 569 #[test]
570 fn test_parse_node() {
571 assert_eq!(parse_expr(r#" node "#), Ok(("", Expr::Node)));
572 assert_eq!(
573 parse_expr(r#" node.foo "#),
574 Ok(("", Expr::FieldAccess(vec!["foo".to_owned()])))
575 );
576 assert_eq!(
577 parse_expr(
578 r#" node
579 .foo
580 .bar"#
581 ),
582 Ok((
583 "",
584 Expr::FieldAccess(vec!["foo".to_owned(), "bar".to_owned()])
585 ))
586 );
587 }
588
589 #[test]
538 fn test_parse_if() { 590 fn test_parse_if() {
539 assert_eq!( 591 assert_eq!(
540 parse_expr( 592 parse_expr(