tmc_langs_util/
parse_util.rs1use nom::{IResult, Parser, branch, bytes, character, combinator, multi, sequence};
4use nom_language::error::VerboseError;
5
6pub fn string(i: &str) -> IResult<&str, &str, VerboseError<&str>> {
8 combinator::map(
9 sequence::delimited(
10 character::complete::char('"'),
11 bytes::complete::is_not("\""),
12 character::complete::char('"'),
13 ),
14 str::trim,
15 )
16 .parse(i)
17}
18
19pub fn string_single(i: &str) -> IResult<&str, &str, VerboseError<&str>> {
21 combinator::map(
22 sequence::delimited(
23 character::complete::char('\''),
24 bytes::complete::is_not("'"),
25 character::complete::char('\''),
26 ),
27 str::trim,
28 )
29 .parse(i)
30}
31
32pub fn comma_separated_strings(i: &str) -> IResult<&str, Vec<&str>, VerboseError<&str>> {
34 comma_separated_things(string, i)
35}
36
37pub fn comma_separated_strings_single(i: &str) -> IResult<&str, Vec<&str>, VerboseError<&str>> {
39 comma_separated_things(string_single, i)
40}
41
42pub fn comma_separated_strings_either(i: &str) -> IResult<&str, Vec<&str>, VerboseError<&str>> {
44 comma_separated_things(branch::alt((string, string_single)), i)
45}
46
47fn comma_separated_things<'a>(
49 thing_parser: impl Parser<&'a str, Output = &'a str, Error = VerboseError<&'a str>>,
50 i: &'a str,
51) -> IResult<&'a str, Vec<&'a str>, VerboseError<&'a str>> {
52 multi::separated_list1(
53 sequence::delimited(
54 character::complete::multispace0,
55 character::complete::char(','),
56 character::complete::multispace0,
57 ),
58 thing_parser,
59 )
60 .parse(i)
61}
62
63#[cfg(test)]
64#[allow(clippy::unwrap_used)]
65mod test {
66 use super::*;
67
68 #[test]
69 fn parses_string() {
70 let (left, res) = string("\"abcd\"").unwrap();
71 assert!(left.is_empty());
72 assert_eq!(res, "abcd");
73 }
74
75 #[test]
76 fn parses_string_single() {
77 let (left, res) = string_single("'abcd'").unwrap();
78 assert!(left.is_empty());
79 assert_eq!(res, "abcd");
80 }
81
82 #[test]
83 fn parses_comma_separated_strings() {
84 let (left, res) = comma_separated_strings("\"abcd\", \"efgh\", \"hijk\"").unwrap();
85 assert!(left.is_empty());
86 assert_eq!(res, &["abcd", "efgh", "hijk"]);
87 }
88
89 #[test]
90 fn parses_comma_separated_strings_single() {
91 let (left, res) = comma_separated_strings_single("'abcd', 'efgh', 'hijk'").unwrap();
92 assert!(left.is_empty());
93 assert_eq!(res, &["abcd", "efgh", "hijk"]);
94 }
95
96 #[test]
97 fn parses_comma_separated_strings_either() {
98 let (left, res) = comma_separated_strings_either("'abcd', \"efgh\", 'hijk'").unwrap();
99 assert!(left.is_empty());
100 assert_eq!(res, &["abcd", "efgh", "hijk"]);
101 }
102}