makepad_live_compiler/
live_token.rs

1use {
2    std::{
3        rc::Rc,
4        fmt,
5        ops::Deref,
6        ops::DerefMut,
7    },
8    crate::{
9        makepad_math::Vec4,
10        makepad_live_tokenizer::{
11            LiveId,
12            Delim,
13            FullToken
14        },
15        live_ptr::{LiveFileId},
16        span::TextSpan
17    }
18};
19
20#[derive(Clone, Debug, PartialEq)]
21pub struct TokenWithSpan {
22    pub span: TextSpan,
23    pub token: LiveToken,
24}
25
26impl Deref for TokenWithSpan {
27    type Target = LiveToken;
28    fn deref(&self) -> &Self::Target {&self.token}
29}
30
31impl DerefMut for TokenWithSpan {
32    fn deref_mut(&mut self) -> &mut Self::Target {&mut self.token}
33}
34
35impl fmt::Display for TokenWithSpan {
36    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37        write!(f, "{} ", self.token)
38    }
39}
40
41#[derive(Clone, Debug, PartialEq)]
42pub enum LiveToken {
43    Punct(LiveId),
44    Ident(LiveId),
45    
46    Open(Delim),
47    Close(Delim),
48    
49    String (Rc<String>),
50    Bool(bool),
51    Int(i64),
52    Float(f64),
53    Color(u32),
54    
55    Eof,
56}
57
58impl LiveToken {
59
60    pub fn as_float(&self) -> Option<f64> {
61        match self {
62            Self::Float(v) => Some(*v),
63            Self::Int(v) => Some(*v as f64),
64            _ => None
65        }
66    }
67    pub fn as_vec4(&self) -> Option<Vec4> {
68        match self {
69            Self::Color(c) => Some(Vec4::from_u32(*c)),
70            _ => None
71        }
72    }    
73    
74    pub fn is_open(&self) -> bool {
75        matches!(self, LiveToken::Open(_))
76    }
77    
78    pub fn is_close(&self) -> bool {
79        matches!(self, LiveToken::Close(_))
80    }
81    
82    pub fn is_open_delim(&self, delim: Delim) -> bool {
83        match self {
84            LiveToken::Open(d) => *d == delim,
85            _ => false
86        }
87    }
88    
89    pub fn is_close_delim(&self, delim: Delim) -> bool {
90        match self {
91            LiveToken::Close(d) => *d == delim,
92            _ => false
93        }
94    }
95    
96    pub fn is_int(&self) -> bool {
97        matches!(self, LiveToken::Int(_))
98    }
99    
100    
101    pub fn is_float(&self) -> bool {
102        matches!(self, LiveToken::Float(_))
103    }
104    
105        
106    pub fn is_color(&self) -> bool {
107        matches!(self, LiveToken::Color(_))
108    }
109
110    pub fn is_bool(&self) -> bool {
111        matches!(self, LiveToken::Bool(_))
112    }
113
114    pub fn is_parsed_number(&self) -> bool {
115        matches!(self, LiveToken::Int(_) | LiveToken::Float(_))
116    }
117    
118    pub fn is_value_type(&self) -> bool {
119        matches!(self, LiveToken::Color(_) | LiveToken::Bool(_) | LiveToken::Int(_) | LiveToken::Float(_))
120    }
121        
122    pub fn is_ident(&self) -> bool {
123        matches!(self, LiveToken::Ident(_))
124    }
125    
126    pub fn is_punct(&self) -> bool {
127        matches!(self, LiveToken::Punct(_))
128    }
129    
130    pub fn is_punct_id(&self, id: LiveId) -> bool {
131        match self {
132            LiveToken::Punct(v) => *v == id,
133            _ => false
134        }
135    }
136    
137    pub fn is_parse_equal(&self, other: &LiveToken) -> bool {
138        match self {
139            LiveToken::String(p) => if let LiveToken::String(o) = other {*p == *o}else {false},
140            LiveToken::Punct(p) => if let LiveToken::Punct(o) = other {*p == *o}else {false},
141            LiveToken::Ident(p) => if let LiveToken::Ident(o) = other {*p == *o}else {false},
142            LiveToken::Open(p) => if let LiveToken::Open(o) = other {*p == *o}else {false},
143            LiveToken::Close(p) => if let LiveToken::Close(o) = other {*p == *o}else {false},
144            LiveToken::Bool(_) => matches!(other, LiveToken::Bool(_)),
145            LiveToken::Int(_) => if let LiveToken::Int(_) = other {true} else { matches!(other, LiveToken::Float(_)) },
146            LiveToken::Float(_) => if let LiveToken::Float(_) = other {true} else { matches!(other, LiveToken::Int(_)) },
147            LiveToken::Color(_) => matches!(other, LiveToken::Color(_)),
148            LiveToken::Eof => matches!(other, LiveToken::Eof),
149        }
150    }
151    
152    pub fn from_full_token(full_token: &FullToken) -> Option<Self> {
153        match full_token {
154            FullToken::String(s) => Some(LiveToken::String(s.clone())),
155            FullToken::Punct(p) => Some(LiveToken::Punct(*p)),
156            FullToken::Ident(p) => Some(LiveToken::Ident(*p)),
157            FullToken::Open(p) => Some(LiveToken::Open(*p)),
158            FullToken::Close(p) => Some(LiveToken::Close(*p)),
159            FullToken::Bool(p) => Some(LiveToken::Bool(*p)),
160            FullToken::Int(p) => Some(LiveToken::Int(*p)),
161            FullToken::Float(p) => Some(LiveToken::Float(*p)),
162            FullToken::Color(p) => Some(LiveToken::Color(*p)),
163            _ => None
164        }
165    }
166}
167
168impl fmt::Display for LiveToken {
169    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
170        match self {
171            Self::Eof => write!(f, "<eof>"),
172            Self::String(v) => write!(f, "{}", v),
173            Self::Punct(id) => write!(f, "{}", id),
174            Self::Ident(id) => write!(f, "{}", id),
175            Self::Open(Delim::Paren) => write!(f, "("),
176            Self::Open(Delim::Brace) => write!(f, "{{"),
177            Self::Open(Delim::Bracket) => write!(f, "["),
178            Self::Close(Delim::Paren) => write!(f, ")"),
179            Self::Close(Delim::Brace) => write!(f, "}}"),
180            Self::Close(Delim::Bracket) => write!(f, "]"),
181            Self::Bool(lit) => write!(f, "{}", lit),
182            Self::Int(lit) => write!(f, "{}", lit),
183            Self::Float(lit) => write!(f, "{}", lit),
184            Self::Color(lit) => write!(f, "#{:x}", lit),
185        }
186    }
187}
188
189impl LiveTokenId {
190    pub fn new(file_id: LiveFileId, token: usize) -> Self {
191        let file_id = file_id.to_index();
192        if file_id > 0x3fe || token > 0x3ffff {
193            panic!();
194        }
195        LiveTokenId(
196            (((file_id as u32 + 1) & 0x3ff) << 18) | ((token as u32) & 0x3ffff)
197        )
198    }
199    
200    pub fn is_empty(&self) -> bool {
201        ((self.0 >> 18) & 0x3ff) == 0
202    }
203    
204    pub fn token_index(&self) -> usize {
205        (self.0 & 0x3ffff) as usize
206    }
207    
208    pub fn file_id(&self) -> Option<LiveFileId> {
209        let id = (self.0 >> 18) & 0x3ff;
210        if id == 0{
211            None
212        }
213        else{
214            Some(LiveFileId((id - 1) as u16))
215        }
216    }
217    
218    pub fn to_bits(&self) -> u32 {self.0}
219    pub fn from_bits(v: u32) -> Option<Self> {
220        if (v & 0xf000_0000) != 0 {
221            panic!();
222        }
223        if ((v >> 18) & 0x3ff) == 0 {
224            None
225        } else {
226            Some(Self(v))
227        }
228    }
229}
230
231#[derive(Clone, Default, Copy, Eq, Ord, Hash, PartialOrd, PartialEq)]
232pub struct LiveTokenId(u32);
233
234impl fmt::Debug for LiveTokenId {
235    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236        write!(f, "TokenId(token_index:{}, file_id:{})", self.token_index(), self.file_id().unwrap_or(LiveFileId::new(0)).to_index())
237    }
238}
239