taitan_orm_parser/template_parser/structs/
sign.rs

1use nom::branch::alt;
2use nom::bytes::complete::tag;
3use nom::character::complete::satisfy;
4use nom::combinator::map;
5use nom::IResult;
6use std::fmt::Display;
7
8// not alpha,  it is variable
9// not number, it is number
10// not begin with "/[/`, if begin with "/[/`, it is variable
11// not begin with ', if begin with ', it is text
12// not begin with @/#/$, it is placeholder
13// not begin with {, it is rinja template
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum Sign {
16    Star,
17    Plus,
18    Minus,
19    Semicolon,
20    // Comma,
21    // LeftParen,
22    // RightParen,
23    Bracket(char),
24    Unknown(char),
25}
26impl Sign {
27    pub fn parse(input: &str) -> IResult<&str, Sign> {
28        alt((
29            map(tag("*"), |_| Sign::Star),
30            map(tag("+"), |_| Sign::Plus),
31            map(tag("-"), |_| Sign::Minus),
32            // map(tag(","), |_| Sign::Comma),
33            map(tag(";"), |_| Sign::Semicolon),
34            // map(tag("("), |_| Sign::LeftParen),
35            // map(tag(")"), |_| Sign::RightParen),
36            map(tag("["), |_| Sign::Bracket('[')),
37            map(tag("]"), |_| Sign::Bracket(']')),
38            map(tag("{"), |_| Sign::Bracket('{')),
39            map(tag("{"), |_| Sign::Bracket('}')),
40            parse_unknown,
41        ))(input)
42    }
43}
44
45impl Display for Sign {
46    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        match self {
48            Sign::Star => write!(fmt, "*"),
49            Sign::Plus => write!(fmt, "+"),
50            Sign::Minus => write!(fmt, "-"),
51            // Sign::Comma => write!(fmt, ","),
52            Sign::Semicolon => write!(fmt, ";"),
53            // Sign::LeftParen => write!(fmt, "("),
54            // Sign::RightParen => write!(fmt, ")"),
55            Sign::Bracket(c) => write!(fmt, "{}", c),
56            Sign::Unknown(c) => write!(fmt, "{}", c),
57        }
58    }
59}
60
61// 判断字符是否为字母、数字或下划线
62fn is_alphanumeric_or_underscore(c: char) -> bool {
63    c.is_ascii_alphanumeric() || c == '_'
64}
65
66// 判断字符是否不是字母、数字、下划线或空格
67fn sign_condition(c: char) -> bool {
68    !is_alphanumeric_or_underscore(c)
69        && !c.is_whitespace()
70        && c != '('
71        && c != ')'
72        && c != '['
73        && c != ']'
74        && c != '{'
75        && c != '}'
76        && c != '@'
77        && c != '#'
78        && c != '$'
79        && c != '?'
80        && c != '*'
81        && c != '='
82        && c != '+'
83        && c != '-'
84        && c != '>'
85        && c != '<'
86        && c != '!'
87        && c != '`'
88        && c != '"'
89        && c != '\''
90        && c != ','
91        && c != ';'
92}
93
94fn parse_unknown(input: &str) -> IResult<&str, Sign> {
95    let parser = satisfy(sign_condition);
96    map(parser, |c: char| Sign::Unknown(c))(input)
97}
98
99#[cfg(test)]
100mod tests {
101    use crate::template_parser::structs::sign::Sign;
102
103    #[test]
104    fn sign_parser_spec_001() {
105        let template = "*";
106        let (_, parsed) = Sign::parse(template).unwrap();
107        assert_eq!(parsed, Sign::Star);
108
109        let template = ";";
110        let (_, parsed) = Sign::parse(template).unwrap();
111        assert_eq!(parsed, Sign::Semicolon);
112    }
113    #[test]
114    fn sign_parser_spec_002() {
115        let template = "s1$@#\"'`";
116        for c in template.chars() {
117            let content = c.to_string();
118            let parse_result = Sign::parse(content.as_str());
119            assert!(parse_result.is_err());
120        }
121    }
122}