shadowplay/puppet_parser/
regex.rs1use crate::puppet_parser::{range::Range, IResult, Span};
2use nom::branch::alt;
3use nom::bytes::complete::{is_not, tag};
4use nom::character::complete::anychar;
5use nom::combinator::{map, recognize, verify};
6use nom::multi::fold_many0;
7use nom::sequence::{pair, tuple};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10enum StringFragment<'a> {
11 Literal(Span<'a>),
12 EscapedChar(Span<'a>),
13}
14
15fn parse_literal(input: Span) -> IResult<Span> {
16 let not_quote_slash = is_not("/\\");
17 verify(not_quote_slash, |s: &Span| !s.is_empty())(input)
18}
19
20fn parse_escaped_char(input: Span) -> IResult<Span> {
21 recognize(pair(tag("\\"), anychar))(input)
22}
23
24fn parse_fragment(input: Span) -> IResult<StringFragment> {
25 alt((
26 map(parse_literal, StringFragment::Literal),
27 map(parse_escaped_char, StringFragment::EscapedChar),
28 ))(input)
29}
30
31pub fn parse(input: Span) -> IResult<crate::puppet_lang::expression::Regexp<Range>> {
32 let build_regex = fold_many0(parse_fragment, String::new, |mut string, fragment| {
33 match fragment {
34 StringFragment::Literal(s) => string.push_str(&s),
35 StringFragment::EscapedChar(s) => string.push_str(&s),
36 }
37 string
38 });
39
40 map(
41 tuple((tag("/"), build_regex, tag("/"))),
42 |(left_tag, data, right_tag)| crate::puppet_lang::expression::Regexp {
43 data,
44 extra: Range::from((left_tag, right_tag)),
45 },
46 )(input)
47}
48
49#[test]
50fn test() {
51 assert_eq!(
52 parse(Span::new("//")).unwrap().1,
53 crate::puppet_lang::expression::Regexp {
54 data: "".to_owned(),
55 extra: Range::new(0, 1, 1, 1, 1, 2)
56 }
57 );
58 assert_eq!(
59 parse(Span::new("/aaa/")).unwrap().1,
60 crate::puppet_lang::expression::Regexp {
61 data: "aaa".to_owned(),
62 extra: Range::new(0, 1, 1, 4, 1, 5)
63 }
64 );
65 assert_eq!(
66 parse(Span::new("/\\//")).unwrap().1,
67 crate::puppet_lang::expression::Regexp {
68 data: "\\/".to_owned(),
69 extra: Range::new(0, 1, 1, 3, 1, 4)
70 }
71 );
72 assert_eq!(
73 parse(Span::new("/\\d/")).unwrap().1,
74 crate::puppet_lang::expression::Regexp {
75 data: "\\d".to_owned(),
76 extra: Range::new(0, 1, 1, 3, 1, 4)
77 }
78 );
79}