taitan_orm_parser/template_parser/structs/
variable.rs

1use nom::branch::alt;
2use nom::bytes::complete::tag;
3use nom::character::complete::{alpha1, alphanumeric1, multispace0};
4use nom::combinator::{map, recognize};
5use nom::error::context;
6use nom::multi::many0;
7use nom::sequence::{delimited, pair, preceded, tuple};
8use nom::IResult;
9use std::fmt::{Display, Formatter};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum Variable {
13    Simple(String),
14    Backquote(String),
15    Brackets(String),
16    DoubleQuote(String),
17}
18
19impl Variable {
20    pub fn parse(input: &str) -> IResult<&str, Variable> {
21        alt((
22            parse_quoted_variable,                        // 尝试解析带引号的变量名
23            map(parse_simple_variable, Variable::Simple), // 如果失败,则尝试解析不带引号的变量名
24        ))(input)
25    }
26    pub fn get_ident(&self) -> &str {
27        match self {
28            Variable::Simple(ident)
29            | Variable::Backquote(ident)
30            | Variable::Brackets(ident)
31            | Variable::DoubleQuote(ident) => ident,
32        }
33    }
34}
35
36impl Display for Variable {
37    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
38        match self {
39            Variable::Simple(ident) => write!(f, "{}", ident),
40            Variable::Backquote(ident) => write!(f, "`{}`", ident),
41            Variable::Brackets(ident) => write!(f, "[{}]", ident),
42            Variable::DoubleQuote(ident) => write!(f, "\"{}\"", ident),
43        }
44    }
45}
46
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct VariableChain {
49    pub variables: Vec<Variable>,
50}
51impl VariableChain {
52    pub fn new(variables: Vec<Variable>) -> VariableChain {
53        VariableChain { variables }
54    }
55    pub fn parse(input: &str) -> IResult<&str, VariableChain> {
56        // 解析完整的变量名链条 a.b.c
57        context(
58            "VariableChain",
59            map(
60                tuple((
61                    Variable::parse, // 解析第一个变量名部分
62                    many0(preceded(
63                        multispace0,
64                        preceded(tag("."), preceded(multispace0, Variable::parse)),
65                    )), // 解析后续的部分,每个部分前有 '.'
66                )),
67                |(first, rest)| VariableChain {
68                    variables: std::iter::once(first).chain(rest.into_iter()).collect(),
69                },
70            ),
71        )(input)
72    }
73}
74
75impl Display for VariableChain {
76    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
77        let mut result = String::new();
78        for (index, variable) in self.variables.iter().enumerate() {
79            if index > 0 {
80                result.push('.');
81            }
82            result.push_str(&variable.to_string());
83        }
84        write!(f, "{}", result)
85    }
86}
87
88fn parse_simple_variable(input: &str) -> IResult<&str, String> {
89    // 解析变量名,允许字母数字字符和下划线
90    map(
91        recognize(pair(
92            alpha1,                                // 变量名以字母开头
93            many0(alt((alphanumeric1, tag("_")))), // 后面可以跟字母、数字或下划线
94        )),
95        |s: &str| s.to_string(),
96    )(input)
97}
98
99fn parse_quoted_variable(input: &str) -> IResult<&str, Variable> {
100    // 解析带引号的变量名,例如 `var`
101    alt((
102        map(
103            delimited(
104                tag("`"),
105                preceded(multispace0, parse_simple_variable),
106                preceded(multispace0, tag("`")),
107            ),
108            |var| Variable::Backquote(var.to_string()),
109        ),
110        map(
111            delimited(
112                tag("["),
113                preceded(multispace0, parse_simple_variable),
114                preceded(multispace0, tag("]")),
115            ),
116            |var| Variable::Brackets(var.to_string()),
117        ),
118        map(
119            delimited(
120                tag("\""),
121                preceded(multispace0, parse_simple_variable),
122                preceded(multispace0, tag("\"")),
123            ),
124            |var| Variable::DoubleQuote(var.to_string()),
125        ),
126    ))(input)
127}
128
129#[cfg(test)]
130mod tests {
131    use super::*;
132    #[test]
133    fn test_parse_variable_chain_spec_001() {
134        let template = "sdfs.[ sdf ].` uire123`.\"gsdg \".  dfdsl";
135        let (_, variable_chain) = VariableChain::parse(template).unwrap();
136        assert_eq!(
137            variable_chain.variables,
138            vec![
139                Variable::Simple("sdfs".to_string()),
140                Variable::Brackets("sdf".to_string()),
141                Variable::Backquote("uire123".to_string()),
142                Variable::DoubleQuote("gsdg".to_string()),
143                Variable::Simple("dfdsl".to_string()),
144            ]
145        );
146    }
147
148    #[test]
149    fn test_parse_variable_chain_spec_002() {
150        let template = "123";
151        let parse_result = VariableChain::parse(template);
152        assert!(parse_result.is_err());
153
154        let template = "'asdfv'";
155        let parse_result = VariableChain::parse(template);
156        assert!(parse_result.is_err());
157    }
158}