diff options
| author | Mike Buland <mike@xagasoft.com> | 2026-06-07 16:37:28 -0700 |
|---|---|---|
| committer | Mike Buland <mike@xagasoft.com> | 2026-06-07 16:37:28 -0700 |
| commit | 83ab8c67beecfc05684c9400e29f7d77225d3af9 (patch) | |
| tree | 2ec5042814bfb8a485797672cfef66fea04fd85f /src/parser.rs | |
| parent | 3dd9ca69340512e42867b43db689e494bada2000 (diff) | |
| download | crimtag-83ab8c67beecfc05684c9400e29f7d77225d3af9.tar.gz crimtag-83ab8c67beecfc05684c9400e29f7d77225d3af9.tar.bz2 crimtag-83ab8c67beecfc05684c9400e29f7d77225d3af9.tar.xz crimtag-83ab8c67beecfc05684c9400e29f7d77225d3af9.zip | |
Cleaned up a lot of parsing code.
Diffstat (limited to 'src/parser.rs')
| -rw-r--r-- | src/parser.rs | 142 |
1 files changed, 110 insertions, 32 deletions
diff --git a/src/parser.rs b/src/parser.rs index e5ea1f5..2d845cd 100644 --- a/src/parser.rs +++ b/src/parser.rs | |||
| @@ -27,6 +27,7 @@ struct Context<'a> { | |||
| 27 | impl<'a> Context<'a> { | 27 | impl<'a> Context<'a> { |
| 28 | pub fn new( mut ll: Lexer<'a> ) -> Self { | 28 | pub fn new( mut ll: Lexer<'a> ) -> Self { |
| 29 | let cur = [ll.next(), ll.next()]; | 29 | let cur = [ll.next(), ll.next()]; |
| 30 | //println!(" - cur: {:?}, peek: {:?}", cur[0], cur[1] ); | ||
| 30 | Self { | 31 | Self { |
| 31 | cur, | 32 | cur, |
| 32 | icur: 0, | 33 | icur: 0, |
| @@ -37,7 +38,7 @@ impl<'a> Context<'a> { | |||
| 37 | pub fn next(&mut self) -> Option<Symbol<'a>> { | 38 | pub fn next(&mut self) -> Option<Symbol<'a>> { |
| 38 | self.cur[self.icur] = self.ll.next(); | 39 | self.cur[self.icur] = self.ll.next(); |
| 39 | self.icur = (self.icur+1)%2; | 40 | self.icur = (self.icur+1)%2; |
| 40 | println!(" - cur: {:?}, peek: {:?}", self.cur(), self.peek() ); | 41 | //println!(" - cur: {:?}, peek: {:?}", self.cur(), self.peek() ); |
| 41 | self.cur[self.icur] | 42 | self.cur[self.icur] |
| 42 | } | 43 | } |
| 43 | 44 | ||
| @@ -136,7 +137,7 @@ impl Parser { | |||
| 136 | } | 137 | } |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | fn lex_error(&self, error: &Symbol) -> Result<(),Box<dyn Error>> { | 140 | fn lex_error(&self, error: &Symbol) -> Result<Token,Box<dyn Error>> { |
| 140 | if let SymbolType::Error{what} = error.symbol() { | 141 | if let SymbolType::Error{what} = error.symbol() { |
| 141 | Err(Box::new(ParseError { | 142 | Err(Box::new(ParseError { |
| 142 | position: error.start().clone(), | 143 | position: error.start().clone(), |
| @@ -150,17 +151,16 @@ impl Parser { | |||
| 150 | } | 151 | } |
| 151 | } | 152 | } |
| 152 | 153 | ||
| 153 | pub fn parse(&mut self, crim: &mut Crimtag, src: &str ) -> Result<(),Box<dyn Error>> { | 154 | pub fn parse(&mut self, src: &str ) -> Result<Token,Box<dyn Error>> { |
| 154 | let mut ll = Lexer::new( src ); | 155 | let mut ll = Lexer::new( src ); |
| 155 | let mut ctx = Context::new( ll ); | 156 | let mut ctx = Context::new( ll ); |
| 156 | 157 | ||
| 157 | // Parse the root of the file, the input context | 158 | // Parse the root of the file, the input context |
| 158 | self.p_input( &mut ctx )?; | 159 | self.p_input( &mut ctx ) |
| 159 | |||
| 160 | Ok(()) | ||
| 161 | } | 160 | } |
| 162 | 161 | ||
| 163 | fn p_input(&mut self, ctx: &mut Context ) -> Result<(), Box<dyn Error>> { | 162 | fn p_input(&mut self, ctx: &mut Context ) -> Result<Token, Box<dyn Error>> { |
| 163 | let mut children = Vec::new(); | ||
| 164 | loop { | 164 | loop { |
| 165 | if ctx.cur().is_none() { | 165 | if ctx.cur().is_none() { |
| 166 | break; | 166 | break; |
| @@ -168,7 +168,7 @@ impl Parser { | |||
| 168 | match ctx.cur().unwrap().symbol() { | 168 | match ctx.cur().unwrap().symbol() { |
| 169 | SymbolType::Text(_) => { /* Skip top level text */ } | 169 | SymbolType::Text(_) => { /* Skip top level text */ } |
| 170 | SymbolType::StartFlat => { | 170 | SymbolType::StartFlat => { |
| 171 | self.parse_tag( ctx ); | 171 | children.push( self.parse_tag( ctx )? ); |
| 172 | } | 172 | } |
| 173 | SymbolType::Error{..} => { | 173 | SymbolType::Error{..} => { |
| 174 | return self.lex_error( &ctx.cur().unwrap() ); | 174 | return self.lex_error( &ctx.cur().unwrap() ); |
| @@ -179,28 +179,57 @@ impl Parser { | |||
| 179 | } | 179 | } |
| 180 | ctx.next(); | 180 | ctx.next(); |
| 181 | } | 181 | } |
| 182 | Ok(()) | 182 | Ok(Token::Root(children)) |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | fn parse_tag(&mut self, ctx: &mut Context) -> Result<(), Box<dyn Error>> { | 185 | fn parse_tag(&mut self, ctx: &mut Context) -> Result<Token, Box<dyn Error>> { |
| 186 | let mut tb = TagBuilder::new(); | 186 | let mut tb = TagBuilder::new(); |
| 187 | |||
| 188 | println!("--> Begin parse_tag <--"); | ||
| 187 | 189 | ||
| 188 | let start_sym = ctx.cur().unwrap(); | 190 | let start_sym = ctx.cur().unwrap(); |
| 189 | 191 | ||
| 192 | println!("--> Start sym: {:?}", start_sym ); | ||
| 193 | |||
| 190 | if ctx.next().is_some() { | 194 | if ctx.next().is_some() { |
| 191 | if let SymbolType::Token(s) = ctx.next().unwrap().symbol() { | 195 | match ctx.cur().unwrap().symbol() { |
| 192 | tb.set_name( s.to_string() ); | 196 | SymbolType::Fragment | SymbolType::Section | |
| 193 | } else { | 197 | SymbolType::Output => { |
| 194 | return Err(Box::new(ParseError{position: ctx.cur().unwrap().start().clone(), what: "Unexpecetd symbol".to_string()})); | 198 | let name_sym = ctx.cur().unwrap(); |
| 199 | ctx.next(); | ||
| 200 | tb.set_name( name_sym ); | ||
| 201 | } | ||
| 202 | _ => { | ||
| 203 | return Err(Box::new(ParseError{position: ctx.cur().unwrap().start().clone(), what: "Unexpecetd symbol".to_string()})); | ||
| 204 | } | ||
| 195 | } | 205 | } |
| 196 | } else { | 206 | } else { |
| 197 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()})); | 207 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()})); |
| 198 | } | 208 | } |
| 199 | 209 | ||
| 210 | println!("--> Begin parse_tag_params <--"); | ||
| 200 | self.parse_tag_params( ctx, &mut tb )?; | 211 | self.parse_tag_params( ctx, &mut tb )?; |
| 212 | println!("--> End parse_tag_params <--"); | ||
| 213 | println!("--> Begin parse_tag_props <--"); | ||
| 201 | self.parse_tag_props( ctx, &mut tb )?; | 214 | self.parse_tag_props( ctx, &mut tb )?; |
| 215 | println!("--> End parse_tag_props <--"); | ||
| 202 | 216 | ||
| 203 | Ok(()) | 217 | println!("---> {:?}", ctx.cur() ); |
| 218 | if let Some(end_sym) = ctx.cur() { | ||
| 219 | match end_sym.symbol() { | ||
| 220 | SymbolType::EndPoint => { | ||
| 221 | tb.set_type( TagType::BinaryOpen ); | ||
| 222 | } | ||
| 223 | SymbolType::EndFlat => { | ||
| 224 | tb.set_type( TagType::Unary ); | ||
| 225 | } | ||
| 226 | _ => { | ||
| 227 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()})); | ||
| 228 | } | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | tb.build() | ||
| 204 | } | 233 | } |
| 205 | 234 | ||
| 206 | fn parse_tag_params(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> Result<(), Box<dyn Error>> { | 235 | fn parse_tag_params(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> Result<(), Box<dyn Error>> { |
| @@ -209,15 +238,13 @@ impl Parser { | |||
| 209 | 238 | ||
| 210 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()})); | 239 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()})); |
| 211 | } | 240 | } |
| 212 | if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() { | 241 | match ctx.cur().unwrap().symbol() { |
| 213 | if let Some(p) = ctx.peek() { | 242 | SymbolType::Literal(s) => { |
| 214 | if p.check_type(|t| matches!(t, SymbolType::Equals)) { | ||
| 215 | break; | ||
| 216 | } | ||
| 217 | } | ||
| 218 | else { | ||
| 219 | tb.add_param( s.to_string() ); | 243 | tb.add_param( s.to_string() ); |
| 220 | } | 244 | } |
| 245 | _ => { | ||
| 246 | break; | ||
| 247 | } | ||
| 221 | } | 248 | } |
| 222 | ctx.next(); | 249 | ctx.next(); |
| 223 | } | 250 | } |
| @@ -250,6 +277,7 @@ impl Parser { | |||
| 250 | } | 277 | } |
| 251 | } | 278 | } |
| 252 | 279 | ||
| 280 | #[derive(PartialEq)] | ||
| 253 | enum TagType { | 281 | enum TagType { |
| 254 | Unknown, | 282 | Unknown, |
| 255 | Unary, | 283 | Unary, |
| @@ -257,36 +285,86 @@ enum TagType { | |||
| 257 | BinaryClose, | 285 | BinaryClose, |
| 258 | } | 286 | } |
| 259 | 287 | ||
| 260 | struct TagBuilder { | 288 | struct TagBuilder<'a> { |
| 261 | name: String, | 289 | name: Option<Symbol<'a>>, |
| 262 | params: Vec<String>, | 290 | params: Vec<String>, |
| 263 | props: Vec<(String,String)>, | 291 | props: Properties, |
| 292 | children: Vec<Token>, | ||
| 264 | tag_type: TagType, | 293 | tag_type: TagType, |
| 265 | } | 294 | } |
| 266 | 295 | ||
| 267 | impl TagBuilder { | 296 | impl<'a> TagBuilder<'a> { |
| 268 | pub fn new() -> TagBuilder { | 297 | pub fn new() -> TagBuilder<'a> { |
| 269 | TagBuilder { | 298 | TagBuilder { |
| 270 | name: String::new(), | 299 | name: None, |
| 271 | params: Vec::new(), | 300 | params: Vec::new(), |
| 272 | props: Vec::new(), | 301 | props: Properties::new(), |
| 302 | children: Vec::new(), | ||
| 273 | tag_type: TagType::Unknown, | 303 | tag_type: TagType::Unknown, |
| 274 | } | 304 | } |
| 275 | } | 305 | } |
| 276 | 306 | ||
| 277 | pub fn set_name(&mut self, name: String) { | 307 | pub fn has_children(&self) -> bool { |
| 278 | self.name = name; | 308 | if self.tag_type == TagType::BinaryOpen { |
| 309 | true | ||
| 310 | } else { | ||
| 311 | false | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | pub fn is_same_name(&self, name: Symbol<'a>) -> bool { | ||
| 316 | if let Some(a) = self.name { | ||
| 317 | a.symbol() == name.symbol() | ||
| 318 | } else { | ||
| 319 | false | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | pub fn set_name(&mut self, name: Symbol<'a>) { | ||
| 324 | self.name = Some(name); | ||
| 325 | println!("Tag name: {:?}", self.name ); | ||
| 279 | } | 326 | } |
| 280 | 327 | ||
| 281 | pub fn add_param(&mut self, param: String) { | 328 | pub fn add_param(&mut self, param: String) { |
| 329 | println!("Add param: {:?}", param ); | ||
| 282 | self.params.push( param ); | 330 | self.params.push( param ); |
| 283 | } | 331 | } |
| 284 | 332 | ||
| 285 | pub fn add_prop(&mut self, key: String, value: String) { | 333 | pub fn add_prop(&mut self, key: String, value: String) { |
| 286 | self.props.push( (key, value) ); | 334 | println!("Add prop: {:?} = {:?}", key, value ); |
| 335 | self.props.insert( key, value ); | ||
| 336 | } | ||
| 337 | |||
| 338 | pub fn add_child(&mut self, token: Token) { | ||
| 339 | self.children.push( token ); | ||
| 287 | } | 340 | } |
| 288 | 341 | ||
| 289 | pub fn set_type(&mut self, tag_type: TagType) { | 342 | pub fn set_type(&mut self, tag_type: TagType) { |
| 290 | self.tag_type = tag_type; | 343 | self.tag_type = tag_type; |
| 291 | } | 344 | } |
| 345 | |||
| 346 | pub fn build(mut self) -> Result<Token,Box<dyn Error>> { | ||
| 347 | if let Some(sym) = self.name { | ||
| 348 | match sym.symbol() { | ||
| 349 | SymbolType::Fragment => { | ||
| 350 | Ok(Token::Fragment(self.params.swap_remove(0), self.props, self.children)) | ||
| 351 | } | ||
| 352 | SymbolType::Output => { | ||
| 353 | Ok(Token::Section(self.params.swap_remove(0), self.props, self.children)) | ||
| 354 | } | ||
| 355 | _ => { | ||
| 356 | println!("Unkown tag type"); | ||
| 357 | Err(Box::new(ParseError { | ||
| 358 | position: Position::new(0,0), | ||
| 359 | what: "Bad tag type".to_string(), | ||
| 360 | })) | ||
| 361 | } | ||
| 362 | } | ||
| 363 | } else { | ||
| 364 | Err(Box::new(ParseError { | ||
| 365 | position: Position::new(0,0), | ||
| 366 | what: "Bad tag type".to_string(), | ||
| 367 | })) | ||
| 368 | } | ||
| 369 | } | ||
| 292 | } | 370 | } |
