diff options
| author | Mike Buland <mike@xagasoft.com> | 2026-08-20 08:16:58 -0700 |
|---|---|---|
| committer | Mike Buland <mike@xagasoft.com> | 2026-08-20 08:16:58 -0700 |
| commit | 12c7b851d866401ac4a32c746ed237b051aa3dd3 (patch) | |
| tree | d8c13033a295f9caa7d9ee388ca64272d5dcfa15 /deepcrow/src/lexer.rs | |
| parent | d1e78b4a3454984db74ebf2a302a64b985ce6de4 (diff) | |
| download | deepcrow-main.tar.gz deepcrow-main.tar.bz2 deepcrow-main.tar.xz deepcrow-main.zip | |
Diffstat (limited to '')
| -rw-r--r-- | deepcrow/src/lexer.rs | 105 |
1 files changed, 37 insertions, 68 deletions
diff --git a/deepcrow/src/lexer.rs b/deepcrow/src/lexer.rs index 2528cb6..98fc1c7 100644 --- a/deepcrow/src/lexer.rs +++ b/deepcrow/src/lexer.rs | |||
| @@ -3,7 +3,7 @@ use std::iter::Iterator; | |||
| 3 | use std::str::CharIndices; | 3 | use std::str::CharIndices; |
| 4 | use std::fmt; | 4 | use std::fmt; |
| 5 | 5 | ||
| 6 | use crate::Position; | 6 | use crate::{Position,Range}; |
| 7 | 7 | ||
| 8 | #[derive(Debug,Copy,Clone,PartialEq,Eq)] | 8 | #[derive(Debug,Copy,Clone,PartialEq,Eq)] |
| 9 | pub enum ErrorType { | 9 | pub enum ErrorType { |
| @@ -17,60 +17,45 @@ pub enum TokenType<'a> { | |||
| 17 | EndFlat, | 17 | EndFlat, |
| 18 | EndPoint, | 18 | EndPoint, |
| 19 | 19 | ||
| 20 | View, | ||
| 21 | Output, | ||
| 22 | Show, | ||
| 23 | Loop, | ||
| 24 | If, | ||
| 25 | ElIf, | ||
| 26 | Else, | ||
| 27 | |||
| 28 | Sharp, | 20 | Sharp, |
| 29 | Equals, | 21 | Equals, |
| 30 | Period, | 22 | Period, |
| 31 | Identifier(&'a str), | 23 | Identifier(&'a str), |
| 32 | Literal(&'a str), | 24 | LiteralStr(&'a str), |
| 33 | Text(&'a str), | 25 | Text(&'a str), |
| 34 | Error{ what: ErrorType }, | 26 | Error{ what: ErrorType }, |
| 35 | } | 27 | } |
| 36 | 28 | ||
| 37 | #[derive(Copy,Clone)] | 29 | #[derive(Copy,Clone)] |
| 38 | pub struct Symbol<'a> { | 30 | pub struct Token<'a> { |
| 39 | symbol: TokenType<'a>, | 31 | token: TokenType<'a>, |
| 40 | start: Position, | 32 | pos: Range, |
| 41 | end: Position, | ||
| 42 | } | 33 | } |
| 43 | 34 | ||
| 44 | impl<'a> fmt::Debug for Symbol<'a> { | 35 | impl<'a> fmt::Debug for Token<'a> { |
| 45 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 36 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 46 | write!(f, "{:?} @ {:?}-{:?}", self.symbol, self.start, self.end ) | 37 | write!(f, "{:?} @ {:?}", self.token, self.pos ) |
| 47 | } | 38 | } |
| 48 | } | 39 | } |
| 49 | 40 | ||
| 50 | impl<'a> Symbol<'a> { | 41 | impl<'a> Token<'a> { |
| 51 | pub fn new( symbol: TokenType<'a>, start: Position, end: Position ) -> Self { | 42 | pub fn new( token: TokenType<'a>, start: Position, end: Position ) -> Self { |
| 52 | Self { | 43 | Self { |
| 53 | symbol, start, end, | 44 | token, Range::new( start, end ), |
| 54 | } | 45 | } |
| 55 | } | 46 | } |
| 56 | 47 | ||
| 57 | pub fn check_type<T: Fn( &TokenType ) -> bool>(&self, f: T ) -> bool { | 48 | pub fn check_type<T: Fn( &TokenType ) -> bool>(&self, f: T ) -> bool { |
| 58 | f( &self.symbol ) | 49 | f( &self.token ) |
| 59 | } | ||
| 60 | |||
| 61 | pub fn symbol(&self) -> &TokenType<'a> { | ||
| 62 | &self.symbol | ||
| 63 | } | 50 | } |
| 64 | 51 | ||
| 65 | pub fn start(&self) -> &Position { | 52 | pub fn token(&self) -> &TokenType<'a> { |
| 66 | &self.start | 53 | &self.token |
| 67 | } | 54 | } |
| 68 | 55 | ||
| 69 | /* | 56 | pub fn pos(&self) -> &Range { |
| 70 | pub fn end(&self) -> &Position { | 57 | &self.pos |
| 71 | &self.end | ||
| 72 | } | 58 | } |
| 73 | */ | ||
| 74 | } | 59 | } |
| 75 | 60 | ||
| 76 | #[derive(Debug)] | 61 | #[derive(Debug)] |
| @@ -81,9 +66,7 @@ enum Mode { | |||
| 81 | 66 | ||
| 82 | pub struct Lexer<'a> { | 67 | pub struct Lexer<'a> { |
| 83 | data: &'a str, | 68 | data: &'a str, |
| 84 | chars: CharIndices<'a>, | 69 | src: LookAhead<CharIndices<'a>>, |
| 85 | cur: [Option<(usize, char)>;2], | ||
| 86 | icur: usize, | ||
| 87 | mode: Mode, | 70 | mode: Mode, |
| 88 | pos: Position, | 71 | pos: Position, |
| 89 | } | 72 | } |
| @@ -107,15 +90,10 @@ fn is_valid_token_char( c: char, first: bool ) -> bool { | |||
| 107 | 90 | ||
| 108 | impl<'a> Lexer<'a> { | 91 | impl<'a> Lexer<'a> { |
| 109 | pub fn new( data: &'a str ) -> Lexer<'a> { | 92 | pub fn new( data: &'a str ) -> Lexer<'a> { |
| 110 | let mut chars = data.char_indices(); | 93 | let mut chars = ; |
| 111 | let cur = chars.next(); | ||
| 112 | let cur2 = chars.next(); | ||
| 113 | //println!(" - cur: {:?}, peek: {:?}", cur, cur2 ); | ||
| 114 | Lexer { | 94 | Lexer { |
| 115 | data, | 95 | data, |
| 116 | chars, | 96 | src: LookAhead::new(data.char_indices()), |
| 117 | cur: [cur, cur2], | ||
| 118 | icur: 0, | ||
| 119 | mode: Mode::Text, | 97 | mode: Mode::Text, |
| 120 | pos: Position::new(1,1), | 98 | pos: Position::new(1,1), |
| 121 | } | 99 | } |
| @@ -170,8 +148,8 @@ impl<'a> Lexer<'a> { | |||
| 170 | } | 148 | } |
| 171 | } | 149 | } |
| 172 | 150 | ||
| 173 | fn error( &self, what: ErrorType ) -> Option<Symbol<'a>> { | 151 | fn error( &self, what: ErrorType ) -> Option<Token<'a>> { |
| 174 | Some(Symbol::new( TokenType::Error { | 152 | Some(Token::new( TokenType::Error { |
| 175 | what: what | 153 | what: what |
| 176 | }, self.pos, self.pos )) | 154 | }, self.pos, self.pos )) |
| 177 | } | 155 | } |
| @@ -182,7 +160,7 @@ impl<'a> Lexer<'a> { | |||
| 182 | } | 160 | } |
| 183 | } | 161 | } |
| 184 | 162 | ||
| 185 | fn next_symbol(&mut self) -> Option<Symbol<'a>> { | 163 | fn next_symbol(&mut self) -> Option<Token<'a>> { |
| 186 | // If we hit the end then we're already done. | 164 | // If we hit the end then we're already done. |
| 187 | if self.cur().is_none() { | 165 | if self.cur().is_none() { |
| 188 | return None; | 166 | return None; |
| @@ -206,7 +184,7 @@ impl<'a> Lexer<'a> { | |||
| 206 | } | 184 | } |
| 207 | } | 185 | } |
| 208 | 186 | ||
| 209 | fn parse_text(&mut self) -> Option<Symbol<'a>> { | 187 | fn parse_text(&mut self) -> Option<Token<'a>> { |
| 210 | let start = self.cur_index(); | 188 | let start = self.cur_index(); |
| 211 | let start_pos = self.pos.clone(); | 189 | let start_pos = self.pos.clone(); |
| 212 | while self.next().is_some() && !self.is_start_tag() { } | 190 | while self.next().is_some() && !self.is_start_tag() { } |
| @@ -217,11 +195,11 @@ impl<'a> Lexer<'a> { | |||
| 217 | if start == end { | 195 | if start == end { |
| 218 | None | 196 | None |
| 219 | } else { | 197 | } else { |
| 220 | Some(Symbol::new( TokenType::Text(s), start_pos, end_pos )) | 198 | Some(Token::new( TokenType::Text(s), start_pos, end_pos )) |
| 221 | } | 199 | } |
| 222 | } | 200 | } |
| 223 | 201 | ||
| 224 | fn parse_token(&mut self) -> Option<Symbol<'a>> { | 202 | fn parse_token(&mut self) -> Option<Token<'a>> { |
| 225 | self.skip_ws(); | 203 | self.skip_ws(); |
| 226 | match self.cur() { | 204 | match self.cur() { |
| 227 | Some('"') => { | 205 | Some('"') => { |
| @@ -229,15 +207,15 @@ impl<'a> Lexer<'a> { | |||
| 229 | } | 207 | } |
| 230 | Some('#') => { | 208 | Some('#') => { |
| 231 | self.next(); | 209 | self.next(); |
| 232 | return Some(Symbol::new(TokenType::Sharp, self.pos, self.pos)); | 210 | return Some(Token::new(TokenType::Sharp, self.pos, self.pos)); |
| 233 | } | 211 | } |
| 234 | Some('=') => { | 212 | Some('=') => { |
| 235 | self.next(); | 213 | self.next(); |
| 236 | return Some(Symbol::new(TokenType::Equals, self.pos, self.pos)); | 214 | return Some(Token::new(TokenType::Equals, self.pos, self.pos)); |
| 237 | } | 215 | } |
| 238 | Some('.') => { | 216 | Some('.') => { |
| 239 | self.next(); | 217 | self.next(); |
| 240 | return Some(Symbol::new(TokenType::Period, self.pos, self.pos)); | 218 | return Some(Token::new(TokenType::Period, self.pos, self.pos)); |
| 241 | } | 219 | } |
| 242 | _ => {} | 220 | _ => {} |
| 243 | } | 221 | } |
| @@ -253,20 +231,11 @@ impl<'a> Lexer<'a> { | |||
| 253 | if start == end { | 231 | if start == end { |
| 254 | None | 232 | None |
| 255 | } else { | 233 | } else { |
| 256 | Some(Symbol::new( match s { | 234 | Some(Token::new( TokenType::Identifier(s), start_pos, end_pos )) |
| 257 | "view" => TokenType::View, | ||
| 258 | "show" => TokenType::Show, | ||
| 259 | "output" => TokenType::Output, | ||
| 260 | "loop" => TokenType::Loop, | ||
| 261 | "if" => TokenType::If, | ||
| 262 | "elif" => TokenType::ElIf, | ||
| 263 | "else" => TokenType::Else, | ||
| 264 | _ => TokenType::Identifier(s) | ||
| 265 | }, start_pos, end_pos )) | ||
| 266 | } | 235 | } |
| 267 | } | 236 | } |
| 268 | 237 | ||
| 269 | fn parse_literal_str(&mut self) -> Option<Symbol<'a>> { | 238 | fn parse_literal_str(&mut self) -> Option<Token<'a>> { |
| 270 | if let Some(chr) = self.cur() && chr != '"' { | 239 | if let Some(chr) = self.cur() && chr != '"' { |
| 271 | return self.error( ErrorType::UnexpectedChar(chr) ); | 240 | return self.error( ErrorType::UnexpectedChar(chr) ); |
| 272 | } | 241 | } |
| @@ -277,7 +246,7 @@ impl<'a> Lexer<'a> { | |||
| 277 | let end_pos = self.pos.clone(); | 246 | let end_pos = self.pos.clone(); |
| 278 | self.next(); | 247 | self.next(); |
| 279 | let s = &self.data[start..end]; | 248 | let s = &self.data[start..end]; |
| 280 | Some(Symbol::new(TokenType::Literal(s), start_pos, end_pos )) | 249 | Some(Token::new(TokenType::LiteralStr(s), start_pos, end_pos )) |
| 281 | } | 250 | } |
| 282 | 251 | ||
| 283 | fn is_start_tag(&mut self) -> bool { | 252 | fn is_start_tag(&mut self) -> bool { |
| @@ -289,7 +258,7 @@ impl<'a> Lexer<'a> { | |||
| 289 | } | 258 | } |
| 290 | } | 259 | } |
| 291 | 260 | ||
| 292 | fn parse_start_tag(&mut self) -> Option<Symbol<'a>> { | 261 | fn parse_start_tag(&mut self) -> Option<Token<'a>> { |
| 293 | let start_pos = self.pos.clone(); | 262 | let start_pos = self.pos.clone(); |
| 294 | match self.cur() { | 263 | match self.cur() { |
| 295 | Some('[') => { | 264 | Some('[') => { |
| @@ -298,7 +267,7 @@ impl<'a> Lexer<'a> { | |||
| 298 | let end_pos = self.pos.clone(); | 267 | let end_pos = self.pos.clone(); |
| 299 | self.next(); | 268 | self.next(); |
| 300 | self.mode = Mode::InTag; | 269 | self.mode = Mode::InTag; |
| 301 | Some(Symbol::new( TokenType::StartFlat, start_pos, end_pos ) ) | 270 | Some(Token::new( TokenType::StartFlat, start_pos, end_pos ) ) |
| 302 | } else { | 271 | } else { |
| 303 | None | 272 | None |
| 304 | } | 273 | } |
| @@ -309,7 +278,7 @@ impl<'a> Lexer<'a> { | |||
| 309 | let end_pos = self.pos.clone(); | 278 | let end_pos = self.pos.clone(); |
| 310 | self.next(); | 279 | self.next(); |
| 311 | self.mode = Mode::InTag; | 280 | self.mode = Mode::InTag; |
| 312 | Some(Symbol::new(TokenType::StartPoint, start_pos, end_pos ) ) | 281 | Some(Token::new(TokenType::StartPoint, start_pos, end_pos ) ) |
| 313 | } else { | 282 | } else { |
| 314 | None | 283 | None |
| 315 | } | 284 | } |
| @@ -329,7 +298,7 @@ impl<'a> Lexer<'a> { | |||
| 329 | } | 298 | } |
| 330 | } | 299 | } |
| 331 | 300 | ||
| 332 | fn parse_end_tag(&mut self) -> Option<Symbol<'a>> { | 301 | fn parse_end_tag(&mut self) -> Option<Token<'a>> { |
| 333 | self.skip_ws(); | 302 | self.skip_ws(); |
| 334 | let start_pos = self.pos.clone(); | 303 | let start_pos = self.pos.clone(); |
| 335 | if let Some(chr) = self.cur() && chr == '|' { | 304 | if let Some(chr) = self.cur() && chr == '|' { |
| @@ -339,14 +308,14 @@ impl<'a> Lexer<'a> { | |||
| 339 | let end_pos = self.pos.clone(); | 308 | let end_pos = self.pos.clone(); |
| 340 | self.next(); | 309 | self.next(); |
| 341 | self.mode = Mode::Text; | 310 | self.mode = Mode::Text; |
| 342 | Some(Symbol::new( TokenType::EndFlat, start_pos, end_pos)) | 311 | Some(Token::new( TokenType::EndFlat, start_pos, end_pos)) |
| 343 | } | 312 | } |
| 344 | Some('>') => { | 313 | Some('>') => { |
| 345 | self.next(); | 314 | self.next(); |
| 346 | let end_pos = self.pos.clone(); | 315 | let end_pos = self.pos.clone(); |
| 347 | self.next(); | 316 | self.next(); |
| 348 | self.mode = Mode::Text; | 317 | self.mode = Mode::Text; |
| 349 | Some(Symbol::new( TokenType::EndPoint, start_pos, end_pos)) | 318 | Some(Token::new( TokenType::EndPoint, start_pos, end_pos)) |
| 350 | } | 319 | } |
| 351 | _ => { | 320 | _ => { |
| 352 | None | 321 | None |
| @@ -359,7 +328,7 @@ impl<'a> Lexer<'a> { | |||
| 359 | } | 328 | } |
| 360 | 329 | ||
| 361 | impl<'a> Iterator for Lexer<'a> { | 330 | impl<'a> Iterator for Lexer<'a> { |
| 362 | type Item = Symbol<'a>; | 331 | type Item = Token<'a>; |
| 363 | 332 | ||
| 364 | fn next(&mut self) -> Option<Self::Item> { | 333 | fn next(&mut self) -> Option<Self::Item> { |
| 365 | self.next_symbol() | 334 | self.next_symbol() |
