1use winnow::ascii::multispace0;
2use winnow::combinator::alt;
3use winnow::error::{StrContext, StrContextValue};
4use winnow::token::literal;
5use winnow::{ModalResult as WResult, Parser};
6
7#[derive(Debug, PartialEq, Clone)]
8pub enum LogicSymbol {
9 And,
10 Or,
11 Not,
12}
13
14#[derive(Debug, PartialEq, Clone, Copy)]
15pub enum CmpSymbol {
16 We,
18 Eq,
19 Ne,
20 Gt,
21 Ge,
22 Lt,
23 Le,
24}
25
26macro_rules! define_unit_symbol {
32 ($name:ident, $lit:expr, $desc:expr) => {
33 #[doc = concat!("Parses the `", $lit, "` symbol.")]
34 pub fn $name(data: &mut &str) -> WResult<()> {
35 multispace0.parse_next(data)?;
36 literal($lit)
37 .context(StrContext::Label("symbol"))
38 .context(StrContext::Expected(StrContextValue::Description($desc)))
39 .parse_next(data)?;
40 Ok(())
41 }
42 };
43}
44
45macro_rules! define_logic_symbol {
47 ($name:ident, $lit:expr, $desc:expr, $variant:expr) => {
48 #[doc = concat!("Parses the `", $lit, "` logic operator.")]
49 pub fn $name(data: &mut &str) -> WResult<LogicSymbol> {
50 multispace0.parse_next(data)?;
51 literal($lit)
52 .context(StrContext::Label("symbol"))
53 .context(StrContext::Expected(StrContextValue::Description($desc)))
54 .parse_next(data)?;
55 Ok($variant)
56 }
57 };
58}
59
60macro_rules! define_cmp_symbol {
62 ($name:ident, $lit:expr, $label:expr, $desc:expr, $variant:expr) => {
63 #[doc = concat!("Parses the `", $lit, "` comparison operator.")]
64 pub fn $name(data: &mut &str) -> WResult<CmpSymbol> {
65 multispace0.parse_next(data)?;
66 literal($lit)
67 .context(StrContext::Label($label))
68 .context(StrContext::Expected(StrContextValue::Description($desc)))
69 .parse_next(data)?;
70 Ok($variant)
71 }
72 };
73}
74
75define_logic_symbol!(symbol_logic_and, "&&", "need '&&'", LogicSymbol::And);
80define_logic_symbol!(symbol_logic_or, "||", "need '||'", LogicSymbol::Or);
81define_logic_symbol!(symbol_logic_not, "!", "need '!'", LogicSymbol::Not);
82
83define_unit_symbol!(symbol_match_to, "=>", "need '=>'");
88define_unit_symbol!(symbol_var, "var", "need 'var'");
89define_unit_symbol!(symbol_comma, ",", "need ','");
90define_unit_symbol!(symbol_bracket_beg, "(", "need '('");
91define_unit_symbol!(symbol_bracket_end, ")", "need ')'");
92define_unit_symbol!(symbol_brace_beg, "{", "need '{'");
93define_unit_symbol!(symbol_brace_end, "}", "need '}'");
94define_unit_symbol!(symbol_under_line, "_", "need '_'");
95define_unit_symbol!(symbol_marvel, "!", "need '!'");
96define_unit_symbol!(symbol_brackets_beg, "[", "need '['");
97define_unit_symbol!(symbol_brackets_end, "]", "need ']'");
98define_unit_symbol!(symbol_colon, ":", "need ':'");
99define_unit_symbol!(symbol_semicolon, ";", "need ';'");
100define_unit_symbol!(symbol_pipe, "|", "need '|' pipe symbol");
101define_unit_symbol!(symbol_assign, "=", "need '='");
102define_unit_symbol!(symbol_dollar, "$", "need '$'");
103
104define_cmp_symbol!(symbol_cmp_eq, "==", "symbol", "need '=='", CmpSymbol::Eq);
109define_cmp_symbol!(symbol_cmp_we, "=*", "symbol", "need '=*'", CmpSymbol::We);
110define_cmp_symbol!(symbol_cmp_ne, "!=", "symbol", "need '!='", CmpSymbol::Ne);
111define_cmp_symbol!(symbol_cmp_ge, ">=", "symbol ge", "need '>='", CmpSymbol::Ge);
112define_cmp_symbol!(symbol_cmp_gt, ">", "symbol gt", "need '>'", CmpSymbol::Gt);
113define_cmp_symbol!(symbol_cmp_le, "<=", "symbol ge", "need '<='", CmpSymbol::Le);
114define_cmp_symbol!(symbol_cmp_lt, "<", "symbol gt", "need '<'", CmpSymbol::Lt);
115
116pub fn symbol_cmp(data: &mut &str) -> WResult<CmpSymbol> {
125 alt((
126 symbol_cmp_eq,
127 symbol_cmp_ne,
128 symbol_cmp_we,
129 symbol_cmp_le,
130 symbol_cmp_ge,
131 symbol_cmp_lt,
132 symbol_cmp_gt,
133 ))
134 .parse_next(data)
135}
136
137pub fn symbol_logic(data: &mut &str) -> WResult<LogicSymbol> {
139 alt((symbol_logic_and, symbol_logic_or, symbol_logic_not)).parse_next(data)
140}
141
142#[inline(always)]
148pub fn ctx_label(label: &'static str) -> StrContext {
149 StrContext::Label(label)
150}
151
152#[inline(always)]
154pub fn ctx_literal(lit: &'static str) -> StrContext {
155 StrContext::Expected(StrContextValue::StringLiteral(lit))
156}
157
158#[inline(always)]
160pub fn ctx_desc(desc: &'static str) -> StrContext {
161 StrContext::Expected(StrContextValue::Description(desc))
162}