diff options
Diffstat (limited to 'src/parser.rs')
| -rw-r--r-- | src/parser.rs | 122 |
1 files changed, 73 insertions, 49 deletions
diff --git a/src/parser.rs b/src/parser.rs index c7a8abe..297230c 100644 --- a/src/parser.rs +++ b/src/parser.rs | |||
| @@ -40,16 +40,18 @@ struct Context<'a> { | |||
| 40 | cur: [Option<Symbol<'a>>;2], | 40 | cur: [Option<Symbol<'a>>;2], |
| 41 | icur: usize, | 41 | icur: usize, |
| 42 | ll: Lexer<'a>, | 42 | ll: Lexer<'a>, |
| 43 | source: usize, | ||
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | impl<'a> Context<'a> { | 46 | impl<'a> Context<'a> { |
| 46 | pub fn new( mut ll: Lexer<'a> ) -> Self { | 47 | pub fn new( mut ll: Lexer<'a>, source: usize ) -> Self { |
| 47 | let cur = [ll.next(), ll.next()]; | 48 | let cur = [ll.next(), ll.next()]; |
| 48 | //println!(" - cur: {:?}, peek: {:?}", cur[0], cur[1] ); | 49 | //println!(" - cur: {:?}, peek: {:?}", cur[0], cur[1] ); |
| 49 | Self { | 50 | Self { |
| 50 | cur, | 51 | cur, |
| 51 | icur: 0, | 52 | icur: 0, |
| 52 | ll | 53 | ll, |
| 54 | source, | ||
| 53 | } | 55 | } |
| 54 | } | 56 | } |
| 55 | 57 | ||
| @@ -75,6 +77,10 @@ impl<'a> Context<'a> { | |||
| 75 | Ok(f( self.cur().unwrap().symbol(), self.peek().unwrap().symbol())) | 77 | Ok(f( self.cur().unwrap().symbol(), self.peek().unwrap().symbol())) |
| 76 | } | 78 | } |
| 77 | } | 79 | } |
| 80 | |||
| 81 | pub fn source(&self) -> usize { | ||
| 82 | self.source | ||
| 83 | } | ||
| 78 | } | 84 | } |
| 79 | 85 | ||
| 80 | trait SymbolHelper { | 86 | trait SymbolHelper { |
| @@ -195,7 +201,7 @@ impl Parser { | |||
| 195 | } | 201 | } |
| 196 | } | 202 | } |
| 197 | 203 | ||
| 198 | fn lex_error(&self, error: &Symbol) -> ParseResult<Token> { | 204 | fn lex_error<T>(&self, error: &Symbol) -> ParseResult<T> { |
| 199 | if let SymbolType::Error{what} = error.symbol() { | 205 | if let SymbolType::Error{what} = error.symbol() { |
| 200 | Err(ParseError { | 206 | Err(ParseError { |
| 201 | position: error.start().clone(), | 207 | position: error.start().clone(), |
| @@ -209,15 +215,15 @@ impl Parser { | |||
| 209 | } | 215 | } |
| 210 | } | 216 | } |
| 211 | 217 | ||
| 212 | pub fn parse(&self, src: &str ) -> ParseResult<Token> { | 218 | pub fn parse(&self, src: &str, source: usize ) -> ParseResult<Vec<View>> { |
| 213 | let ll = Lexer::new( src ); | 219 | let ll = Lexer::new( src ); |
| 214 | let mut ctx = Context::new( ll ); | 220 | let mut ctx = Context::new( ll, source ); |
| 215 | 221 | ||
| 216 | // Parse the root of the file, the input context | 222 | // Parse the root of the file, the input context |
| 217 | self.p_input( &mut ctx ) | 223 | self.p_input( &mut ctx ) |
| 218 | } | 224 | } |
| 219 | 225 | ||
| 220 | fn p_input(&self, ctx: &mut Context ) -> ParseResult<Token> { | 226 | fn p_input(&self, ctx: &mut Context ) -> ParseResult<Vec<View>> { |
| 221 | let mut children = Vec::new(); | 227 | let mut children = Vec::new(); |
| 222 | loop { | 228 | loop { |
| 223 | if ctx.cur().is_none() { | 229 | if ctx.cur().is_none() { |
| @@ -229,7 +235,7 @@ impl Parser { | |||
| 229 | children.push( self.parse_tag_view( ctx )? ); | 235 | children.push( self.parse_tag_view( ctx )? ); |
| 230 | } | 236 | } |
| 231 | SymbolType::Error{..} => { | 237 | SymbolType::Error{..} => { |
| 232 | return self.lex_error( &ctx.cur().unwrap() ); | 238 | self.lex_error( &ctx.cur().unwrap() )?; |
| 233 | } | 239 | } |
| 234 | _ => { | 240 | _ => { |
| 235 | 241 | ||
| @@ -237,11 +243,11 @@ impl Parser { | |||
| 237 | } | 243 | } |
| 238 | ctx.next(); | 244 | ctx.next(); |
| 239 | } | 245 | } |
| 240 | Ok(Token::Root(children)) | 246 | Ok(children) |
| 241 | } | 247 | } |
| 242 | 248 | ||
| 243 | fn parse_tag_view(&self, ctx: &mut Context) -> ParseResult<Token> { | 249 | fn parse_tag_view(&self, ctx: &mut Context) -> ParseResult<View> { |
| 244 | let mut tb = self.parse_open_tag( ctx )?; | 250 | let tb = self.parse_open_tag( ctx )?; |
| 245 | if !tb.is_name( &SymbolType::View ) { | 251 | if !tb.is_name( &SymbolType::View ) { |
| 246 | return Err(ParseError{ | 252 | return Err(ParseError{ |
| 247 | position: tb.start_pos(), | 253 | position: tb.start_pos(), |
| @@ -250,9 +256,10 @@ impl Parser { | |||
| 250 | } | 256 | } |
| 251 | 257 | ||
| 252 | if tb.is_unary() { | 258 | if tb.is_unary() { |
| 253 | return tb.build(); | 259 | return tb.build_view(ctx, Vec::new()); |
| 254 | } | 260 | } |
| 255 | let mut children = Vec::new(); | 261 | let mut children = Vec::new(); |
| 262 | let mut outputs = Vec::new(); | ||
| 256 | 263 | ||
| 257 | //println!("--parse-tag-view-- tag parsed, next token: {:?}", ctx.cur() ); | 264 | //println!("--parse-tag-view-- tag parsed, next token: {:?}", ctx.cur() ); |
| 258 | loop { | 265 | loop { |
| @@ -265,47 +272,37 @@ impl Parser { | |||
| 265 | ctx.next(); | 272 | ctx.next(); |
| 266 | } | 273 | } |
| 267 | SymbolType::StartFlat => { | 274 | SymbolType::StartFlat => { |
| 268 | //child.is_name(SymbolType::Output) | 275 | let subtb = self.parse_tag_body( ctx )?; |
| 269 | children.push( self.parse_tag_body( ctx )? ); | 276 | if subtb.is_name(&SymbolType::Output) { |
| 277 | outputs.push(subtb.build_output(ctx)?); | ||
| 278 | } else { | ||
| 279 | children.push(subtb.build()?); | ||
| 280 | } | ||
| 270 | } | 281 | } |
| 271 | SymbolType::StartPoint => { | 282 | SymbolType::StartPoint => { |
| 272 | let end = self.parse_end_tag( ctx )?; | 283 | let end = self.parse_end_tag( ctx )?; |
| 273 | //println!("End tag: {:?}, open tag: {:?}", end, tb.name() ); | 284 | //println!("End tag: {:?}, open tag: {:?}", end, tb.name() ); |
| 274 | if tb.is_name(end.symbol()) { | 285 | if tb.is_name(end.symbol()) { |
| 275 | // They match, time to decide what we're doing. | 286 | // They match, time to decide what we're doing. |
| 276 | let any_outputs = children.iter().any( | 287 | let any_outputs = outputs.len() > 0; |
| 277 | |t| matches!(t, Token::Output(..)) | 288 | let all_text = children.iter().all( |
| 289 | |t| matches!(t, Token::Text(..)) | ||
| 278 | ); | 290 | ); |
| 279 | if children.iter().all(|t| matches!(t, Token::Text(..)) || matches!(t, Token::Output(..))) { | 291 | if !any_outputs { |
| 280 | // Everything is either text or output | 292 | // Create an implicit output called "content" |
| 281 | if !any_outputs { | 293 | outputs.push(Output{ |
| 282 | // Special case, if it's only text then we create an implicit output. | 294 | name: "content".to_string(), |
| 283 | tb.add_child(Token::Output("content".to_string(), /*Properties::new(),*/ children )); | 295 | code: children, |
| 284 | } | 296 | }); |
| 285 | else { | ||
| 286 | // Standard case, outputs are included, text is | ||
| 287 | // skipped. | ||
| 288 | for token in children { | ||
| 289 | if matches!(token, Token::Output(..)) { | ||
| 290 | tb.add_child( token ); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | } | ||
| 294 | } else { | 297 | } else { |
| 295 | // We have another mix, now check to see if there | 298 | if !all_text { |
| 296 | // are any outptus, if so this is an error. | ||
| 297 | if any_outputs { | ||
| 298 | return Err(ParseError{ | 299 | return Err(ParseError{ |
| 299 | position: *end.start(), | 300 | position: *end.start(), |
| 300 | what: "You cannot mix non-output and output tags in a view.".to_string() | 301 | what: "You cannot mix non-output and output tags in a view.".to_string() |
| 301 | }); | 302 | }); |
| 302 | } else { | ||
| 303 | // No outputs at all, we create an implict output | ||
| 304 | tb.add_child(Token::Output("content".to_string(), /*Properties::new(), */children )); | ||
| 305 | } | 303 | } |
| 306 | } | 304 | } |
| 307 | 305 | return tb.build_view(ctx,outputs); | |
| 308 | return tb.build(); | ||
| 309 | } else { | 306 | } else { |
| 310 | // They don't match, complain. | 307 | // They don't match, complain. |
| 311 | return Err(ParseError{ | 308 | return Err(ParseError{ |
| @@ -392,10 +389,10 @@ impl Parser { | |||
| 392 | Ok(name) | 389 | Ok(name) |
| 393 | } | 390 | } |
| 394 | 391 | ||
| 395 | fn parse_tag_body(&self, ctx: &mut Context ) -> ParseResult<Token> { | 392 | fn parse_tag_body<'a>(&self, ctx: &mut Context<'a> ) -> ParseResult<TagBuilder<'a>> { |
| 396 | let mut tb = self.parse_open_tag( ctx )?; | 393 | let mut tb = self.parse_open_tag( ctx )?; |
| 397 | if tb.is_unary() { | 394 | if tb.is_unary() { |
| 398 | return tb.build(); | 395 | return Ok(tb); |
| 399 | } | 396 | } |
| 400 | 397 | ||
| 401 | loop { | 398 | loop { |
| @@ -408,13 +405,13 @@ impl Parser { | |||
| 408 | ctx.next(); | 405 | ctx.next(); |
| 409 | } | 406 | } |
| 410 | SymbolType::StartFlat => { | 407 | SymbolType::StartFlat => { |
| 411 | tb.add_child( self.parse_tag_body( ctx )? ); | 408 | tb.add_child( self.parse_tag_body( ctx )?.build()? ); |
| 412 | } | 409 | } |
| 413 | SymbolType::StartPoint => { | 410 | SymbolType::StartPoint => { |
| 414 | let end = self.parse_end_tag( ctx )?; | 411 | let end = self.parse_end_tag( ctx )?; |
| 415 | if tb.is_name(end.symbol()) { | 412 | if tb.is_name(end.symbol()) { |
| 416 | // They match, end. | 413 | // They match, end. |
| 417 | return tb.build(); | 414 | return Ok(tb); |
| 418 | } else { | 415 | } else { |
| 419 | // They don't match, complain. | 416 | // They don't match, complain. |
| 420 | return Err(ParseError{ | 417 | return Err(ParseError{ |
| @@ -424,7 +421,7 @@ impl Parser { | |||
| 424 | } | 421 | } |
| 425 | } | 422 | } |
| 426 | SymbolType::Error{..} => { | 423 | SymbolType::Error{..} => { |
| 427 | self.lex_error( &ctx.cur().unwrap() )?; | 424 | return self.lex_error( &ctx.cur().unwrap() ); |
| 428 | } | 425 | } |
| 429 | _ => { | 426 | _ => { |
| 430 | 427 | ||
| @@ -565,15 +562,42 @@ impl<'a> TagBuilder<'a> { | |||
| 565 | self.tag_type | 562 | self.tag_type |
| 566 | } | 563 | } |
| 567 | 564 | ||
| 565 | pub fn build_view(mut self, ctx: &Context, outputs: Vec<Output>) -> ParseResult<View> { | ||
| 566 | if let Some(sym) = self.name { | ||
| 567 | if *sym.symbol() == SymbolType::View { | ||
| 568 | Ok(View { | ||
| 569 | name: self.params.swap_remove(0), | ||
| 570 | source: ctx.source(), | ||
| 571 | outputs: outputs, | ||
| 572 | //theme: Option<String> | ||
| 573 | layout: self.props.get("layout").cloned(), | ||
| 574 | }) | ||
| 575 | } else { | ||
| 576 | Err(ParseError::new(self.start_pos, &format!("Expected tag type view, found {:?}", sym.symbol()))) | ||
| 577 | } | ||
| 578 | } else { | ||
| 579 | Err(ParseError::new(self.start_pos, "Broken Parser? No tag type found when building view.")) | ||
| 580 | } | ||
| 581 | } | ||
| 582 | |||
| 583 | pub fn build_output(mut self, ctx: &Context) -> ParseResult<Output> { | ||
| 584 | if let Some(sym) = self.name { | ||
| 585 | if *sym.symbol() == SymbolType::Output { | ||
| 586 | Ok(Output { | ||
| 587 | name: self.params.swap_remove(0), | ||
| 588 | code: self.children, | ||
| 589 | }) | ||
| 590 | } else { | ||
| 591 | Err(ParseError::new(self.start_pos, &format!("Expected tag type view, found {:?}", sym.symbol()))) | ||
| 592 | } | ||
| 593 | } else { | ||
| 594 | Err(ParseError::new(self.start_pos, "Broken Parser? No tag type found when building view.")) | ||
| 595 | } | ||
| 596 | } | ||
| 597 | |||
| 568 | pub fn build(mut self) -> ParseResult<Token> { | 598 | pub fn build(mut self) -> ParseResult<Token> { |
| 569 | if let Some(sym) = self.name { | 599 | if let Some(sym) = self.name { |
| 570 | match sym.symbol() { | 600 | match sym.symbol() { |
| 571 | SymbolType::View => { | ||
| 572 | Ok(Token::View(self.params.swap_remove(0), self.props, self.children)) | ||
| 573 | } | ||
| 574 | SymbolType::Output => { | ||
| 575 | Ok(Token::Output(self.params.swap_remove(0), /*self.props,*/ self.children)) | ||
| 576 | } | ||
| 577 | SymbolType::Show => { | 601 | SymbolType::Show => { |
| 578 | Ok(Token::Show(self.params.swap_remove(0), self.props)) | 602 | Ok(Token::Show(self.params.swap_remove(0), self.props)) |
| 579 | } | 603 | } |
