lib_ruby_parser/
lex_state.rs

1use crate::maybe_byte::MaybeByte;
2
3/// State of the lexer
4#[derive(Clone, Copy, PartialEq, Eq)]
5#[repr(C)]
6pub struct LexState {
7    pub(crate) value: i32,
8}
9
10impl LexState {
11    pub(crate) fn is(&self, value: i32) -> bool {
12        self.value == value
13    }
14
15    pub(crate) fn is_some(&self, states: i32) -> bool {
16        (self.value & states) != 0
17    }
18
19    pub(crate) fn is_all(&self, states: i32) -> bool {
20        (self.value & states) == states
21    }
22
23    /// Sets state to given `value`
24    pub fn set(&mut self, value: i32) {
25        self.value = value
26    }
27
28    pub(crate) fn get(&self) -> i32 {
29        self.value
30    }
31
32    pub(crate) fn is_after_operator(&self) -> bool {
33        self.is_some(EXPR_FNAME | EXPR_DOT)
34    }
35    pub(crate) fn is_end(&self) -> bool {
36        self.is_some(EXPR_END_ANY)
37    }
38    pub(crate) fn is_arg(&self) -> bool {
39        self.is_some(EXPR_ARG_ANY)
40    }
41    pub(crate) fn is_label_possible(&self, cmd_state: bool) -> bool {
42        (self.is_some(EXPR_LABEL | EXPR_ENDFN) && !cmd_state) || self.is_arg()
43    }
44    pub(crate) fn is_spacearg(&self, c: MaybeByte, space_seen: bool) -> bool {
45        self.is_arg() && space_seen && !c.is_space()
46    }
47    pub(crate) fn is_beg(&self) -> bool {
48        self.is_some(EXPR_BEG_ANY) || self.is_all(EXPR_ARG | EXPR_LABELED)
49    }
50}
51
52impl Default for LexState {
53    fn default() -> Self {
54        Self { value: EXPR_BEG }
55    }
56}
57
58/// Mod with all known lex states
59pub mod lex_states {
60    /// EXPR_BEG state in MRI
61    pub const EXPR_BEG: i32 = 1 << 0;
62
63    /// EXPR_END state in MRI
64    pub const EXPR_END: i32 = 1 << 1;
65
66    /// EXPR_ENDARG state in MRI
67    pub const EXPR_ENDARG: i32 = 1 << 2;
68
69    /// EXPR_ENDFN state in MRI
70    pub const EXPR_ENDFN: i32 = 1 << 3;
71
72    /// EXPR_ARG state in MRI
73    pub const EXPR_ARG: i32 = 1 << 4;
74
75    /// EXPR_CMDARG state in MRI
76    pub const EXPR_CMDARG: i32 = 1 << 5;
77
78    /// EXPR_MID state in MRI
79    pub const EXPR_MID: i32 = 1 << 6;
80
81    /// EXPR_FNAME state in MRI
82    pub const EXPR_FNAME: i32 = 1 << 7;
83
84    /// EXPR_DOT state in MRI
85    pub const EXPR_DOT: i32 = 1 << 8;
86
87    /// EXPR_CLASS state in MRI
88    pub const EXPR_CLASS: i32 = 1 << 9;
89
90    /// EXPR_LABEL state in MRI
91    pub const EXPR_LABEL: i32 = 1 << 10;
92
93    /// EXPR_LABELED state in MRI
94    pub const EXPR_LABELED: i32 = 1 << 11;
95
96    /// EXPR_FITEM state in MRI
97    pub const EXPR_FITEM: i32 = 1 << 12;
98
99    /// EXPR_VALUE state in MRI
100    pub const EXPR_VALUE: i32 = EXPR_BEG;
101
102    /// EXPR_BEG_ANY state in MRI
103    pub const EXPR_BEG_ANY: i32 = EXPR_BEG | EXPR_MID | EXPR_CLASS;
104
105    /// EXPR_ARG_ANY state in MRI
106    pub const EXPR_ARG_ANY: i32 = EXPR_ARG | EXPR_CMDARG;
107
108    /// EXPR_END_ANY state in MRI
109    pub const EXPR_END_ANY: i32 = EXPR_END | EXPR_ENDARG | EXPR_ENDFN;
110
111    /// EXPR_NONE state in MRI
112    pub const EXPR_NONE: i32 = 0;
113}
114use lex_states::*;
115
116impl std::fmt::Debug for LexState {
117    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118        let mut states: Vec<&'static str> = vec![];
119
120        if self.is_some(EXPR_BEG) {
121            states.push("EXPR_BEG")
122        }
123        if self.is_some(EXPR_END) {
124            states.push("EXPR_END")
125        }
126        if self.is_some(EXPR_ENDARG) {
127            states.push("EXPR_ENDARG")
128        }
129        if self.is_some(EXPR_ENDFN) {
130            states.push("EXPR_ENDFN")
131        }
132        if self.is_some(EXPR_ARG) {
133            states.push("EXPR_ARG")
134        }
135        if self.is_some(EXPR_CMDARG) {
136            states.push("EXPR_CMDARG")
137        }
138        if self.is_some(EXPR_MID) {
139            states.push("EXPR_MID")
140        }
141        if self.is_some(EXPR_FNAME) {
142            states.push("EXPR_FNAME")
143        }
144        if self.is_some(EXPR_DOT) {
145            states.push("EXPR_DOT")
146        }
147        if self.is_some(EXPR_CLASS) {
148            states.push("EXPR_CLASS")
149        }
150        if self.is_some(EXPR_LABEL) {
151            states.push("EXPR_LABEL")
152        }
153        if self.is_some(EXPR_FITEM) {
154            states.push("EXPR_FITEM")
155        }
156        if self.is_some(EXPR_NONE) {
157            states.push("EXPR_NONE")
158        }
159
160        if self.is_some(EXPR_VALUE) {
161            states.push("Also(EXPR_VALUE)")
162        }
163        if self.is_some(EXPR_BEG_ANY) {
164            states.push("Also(EXPR_BEG_ANY)")
165        }
166        if self.is_some(EXPR_END_ANY) {
167            states.push("Also(EXPR_END_ANY)")
168        }
169        if self.is_some(EXPR_END_ANY) {
170            states.push("Also(EXPR_END_ANY)")
171        }
172
173        f.write_str(&states.join("|"))
174    }
175}
176
177#[test]
178fn test_fmt() {
179    let mut lex_state = LexState::default();
180    lex_state.set(EXPR_BEG | EXPR_VALUE);
181    assert_eq!(
182        format!("{:?}", lex_state),
183        "EXPR_BEG|Also(EXPR_VALUE)|Also(EXPR_BEG_ANY)"
184    );
185}