taitan_orm_parser/template_parser/structs/
sign.rs1use 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#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum Sign {
16 Star,
17 Plus,
18 Minus,
19 Semicolon,
20 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::Semicolon),
34 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::Semicolon => write!(fmt, ";"),
53 Sign::Bracket(c) => write!(fmt, "{}", c),
56 Sign::Unknown(c) => write!(fmt, "{}", c),
57 }
58 }
59}
60
61fn is_alphanumeric_or_underscore(c: char) -> bool {
63 c.is_ascii_alphanumeric() || c == '_'
64}
65
66fn 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}