1 use nom::{
2 branch::alt,
3 bytes::complete::{tag, take_until, take_while},
4 character::complete::{alpha1, alphanumeric1, digit1, multispace1},
5 combinator::{map, map_res, opt, recognize, value},
6 error::{context, VerboseError},
7 multi::{many0, many0_count, many1},
8 sequence::{delimited, pair, tuple},
9 IResult, Parser,
10 };
11 use crate::string::parse_string;
12
13 /// Result type with verbose error
14 pub(crate) type VerboseResult<'a, T> = IResult<&'a str, T, VerboseError<&'a str>>;
15
comment(input: &str) -> VerboseResult<()>16 pub(crate) fn comment(input: &str) -> VerboseResult<()> {
17 context(
18 "comment",
19 value(
20 (),
21 tuple((tag("//"), take_while(|c|c!='\n'))),
22 ),
23 )(input)
24 }
25
multiline_comment(input: &str) -> VerboseResult<()>26 pub(crate) fn multiline_comment(input: &str) -> VerboseResult<()> {
27 context(
28 "multiline comment",
29 value((), delimited(tag("/*"), take_until("*/"), tag("*/"))),
30 )(input)
31 }
32
space_or_comments(input: &str) -> VerboseResult<()>33 pub(crate) fn space_or_comments(input: &str) -> VerboseResult<()> {
34 value(
35 (),
36 many0(alt((value((), multispace1), comment, multiline_comment))),
37 )(input)
38 }
space_or_comments1(input: &str) -> VerboseResult<()>39 pub(crate) fn space_or_comments1(input: &str) -> VerboseResult<()> {
40 value(
41 (),
42 many1(alt((value((), multispace1), comment, multiline_comment))),
43 )(input)
44 }
45
ws<'a, F, O>(inner: F) -> impl Parser<&'a str, O, VerboseError<&'a str>> where F: Parser<&'a str, O, VerboseError<&'a str>>,46 pub(crate)fn ws<'a, F, O>(inner: F) -> impl Parser<&'a str, O, VerboseError<&'a str>>
47 where
48 F: Parser<&'a str, O, VerboseError<&'a str>>,
49 {
50 delimited(
51 space_or_comments,
52 inner,
53 space_or_comments
54 )
55 }
identifier(input: &str) -> VerboseResult<&str>56 pub(crate) fn identifier(input: &str) -> VerboseResult<&str> {
57 recognize(pair(
58 alt((alpha1, tag("_"))),
59 many0_count(alt((alphanumeric1, tag("_")))),
60 ))(input)
61 }
62
string_literal(input: &str) -> VerboseResult<String>63 pub(crate) fn string_literal(input: &str) -> VerboseResult<String> {
64 context(
65 "string",
66 parse_string
67 )(input)
68 }
69
comma(input: &str) -> VerboseResult<&str>70 pub(crate) fn comma(input: &str) -> VerboseResult<&str> {
71 ws(tag(",")).parse(input)
72 }
73
parse_bool(input: &str) -> VerboseResult<bool>74 pub(crate) fn parse_bool(input: &str) -> VerboseResult<bool> {
75 alt((map(tag("true"), |_| true), map(tag("false"), |_| false)))(input)
76 }
77
parse_int(input: &str) -> VerboseResult<i64>78 pub(crate) fn parse_int(input: &str) -> VerboseResult<i64> {
79 map_res(
80 recognize(pair(opt(tag("-")), digit1)),
81 |x| i64::from_str_radix(x, 10),
82 )(input)
83 }
84 #[cfg(test)]
85 mod tests {
86 use super::*;
87
88 #[test]
test_parse_bool()89 fn test_parse_bool() {
90 let input = "true";
91 let expected_output = Ok(("", true));
92 assert_eq!(parse_bool(input), expected_output);
93 }
94 #[test]
test_parse_int()95 fn test_parse_int() {
96 let input = "123";
97 let expected_output = Ok(("", 123));
98 assert_eq!(parse_int(input), expected_output);
99 }
100 #[test]
test_parse_nint()101 fn test_parse_nint() {
102 let input: &str = "-123";
103 let expected_output = Ok(("", -123));
104 assert_eq!(parse_int(input), expected_output);
105 }
106 }
107
108