static_graph/parser/
literal.rs

1use std::ops::Deref;
2
3use nom::{
4    branch::alt,
5    bytes::complete::{escaped, tag},
6    character::complete::{none_of, one_of},
7    combinator::map,
8    sequence::delimited,
9    IResult,
10};
11
12use super::Parser;
13
14#[derive(Debug, Clone)]
15pub struct Literal(pub String);
16
17impl Deref for Literal {
18    type Target = str;
19    fn deref(&self) -> &str {
20        &self.0
21    }
22}
23
24impl<'a> Parser<'a> for Literal {
25    fn parse(input: &'a str) -> IResult<&'a str, Literal> {
26        alt((
27            map(single_quote, |x| Literal(x.into())),
28            map(double_quote, |x| Literal(x.into())),
29        ))(input)
30    }
31}
32
33fn single_quote(input: &str) -> IResult<&str, &str> {
34    let esc = escaped(none_of(r#"\'"#), '\\', one_of(r#"'"n\"#));
35    let esc_or_empty = alt((esc, tag("")));
36    let res = delimited(tag("\'"), esc_or_empty, tag("\'"))(input)?;
37
38    Ok(res)
39}
40
41fn double_quote(input: &str) -> IResult<&str, &str> {
42    let esc = escaped(none_of(r#"\""#), '\\', one_of(r#"'"n\"#));
43    let esc_or_empty = alt((esc, tag("")));
44    let res = delimited(tag("\""), esc_or_empty, tag("\""))(input)?;
45
46    Ok(res)
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn test_literal() {
55        let input = r#""foo""#;
56        match super::Literal::parse(input) {
57            Ok((remain, lit)) => {
58                assert_eq!(remain, "");
59                assert_eq!(lit.0, "foo");
60            }
61            Err(e) => panic!("Error: {e:?}"),
62        }
63    }
64}