summaryrefslogtreecommitdiff
path: root/src/parser.rs
diff options
context:
space:
mode:
authorMike Buland <mike@xagasoft.com>2026-06-09 14:02:53 -0700
committerMike Buland <mike@xagasoft.com>2026-06-09 14:02:53 -0700
commit61b54e8f6b177f33a1428ab6a3622503a63cc1d6 (patch)
tree1a8af5f0f40dd72a43f98a5e6e3bdce8a7c45366 /src/parser.rs
parentf724cea337965419618d7d587015c9593a67834d (diff)
downloadcrimtag-61b54e8f6b177f33a1428ab6a3622503a63cc1d6.tar.gz
crimtag-61b54e8f6b177f33a1428ab6a3622503a63cc1d6.tar.bz2
crimtag-61b54e8f6b177f33a1428ab6a3622503a63cc1d6.tar.xz
crimtag-61b54e8f6b177f33a1428ab6a3622503a63cc1d6.zip
Identifiers work!
Diffstat (limited to 'src/parser.rs')
-rw-r--r--src/parser.rs65
1 files changed, 56 insertions, 9 deletions
diff --git a/src/parser.rs b/src/parser.rs
index 297230c..5f53557 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -274,7 +274,7 @@ impl Parser {
274 SymbolType::StartFlat => { 274 SymbolType::StartFlat => {
275 let subtb = self.parse_tag_body( ctx )?; 275 let subtb = self.parse_tag_body( ctx )?;
276 if subtb.is_name(&SymbolType::Output) { 276 if subtb.is_name(&SymbolType::Output) {
277 outputs.push(subtb.build_output(ctx)?); 277 outputs.push(subtb.build_output()?);
278 } else { 278 } else {
279 children.push(subtb.build()?); 279 children.push(subtb.build()?);
280 } 280 }
@@ -437,16 +437,43 @@ impl Parser {
437 } 437 }
438 match ctx.cur().unwrap().symbol() { 438 match ctx.cur().unwrap().symbol() {
439 SymbolType::Literal(s) => { 439 SymbolType::Literal(s) => {
440 tb.add_param( s.to_string() ); 440 tb.add_param( ParamValue::Literal(s.to_string()) );
441 ctx.next();
442 }
443 SymbolType::Token(_) => {
444 if ctx.peek().is("tag data", |s| *s == SymbolType::Equals)? {
445 break;
446 }
447 tb.add_param( self.parse_identifier( ctx )? );
441 } 448 }
442 _ => { 449 _ => {
443 break; 450 break;
444 } 451 }
445 } 452 }
446 ctx.next();
447 } 453 }
448 Ok(()) 454 Ok(())
449 } 455 }
456
457 fn parse_identifier(&self, ctx: &mut Context ) -> ParseResult<ParamValue> {
458 let mut id = Identifier::new();
459
460 loop {
461 if ctx.cur().is("identifier",|s| matches!( s, SymbolType::Token(_) ))? {
462 if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() {
463 id.push( IdentifierValue::Name(s.to_string()) );
464 }
465 } else {
466 return Err(ParseError::new( ctx.cur().unwrap().start().clone(), &format!("Expeceted identifier, found {:?}", ctx.cur().unwrap().symbol() ) ) );
467 }
468
469 if !ctx.next().is("identifier seperator",|s| *s == SymbolType::Period )? {
470 break;
471 }
472 ctx.next();
473 }
474
475 Ok(ParamValue::Identifier(id))
476 }
450 477
451 fn parse_tag_props(&self, ctx: &mut Context, tb: &mut TagBuilder ) -> ParseResult<()> { 478 fn parse_tag_props(&self, ctx: &mut Context, tb: &mut TagBuilder ) -> ParseResult<()> {
452 loop { 479 loop {
@@ -483,13 +510,18 @@ enum TagType {
483 510
484struct TagBuilder<'a> { 511struct TagBuilder<'a> {
485 name: Option<Symbol<'a>>, 512 name: Option<Symbol<'a>>,
486 params: Vec<String>, 513 params: Vec<ParamValue>,
487 props: Properties, 514 props: Properties,
488 children: Vec<Token>, 515 children: Vec<Token>,
489 tag_type: TagType, 516 tag_type: TagType,
490 start_pos: Position, 517 start_pos: Position,
491} 518}
492 519
520enum ParamValue {
521 Literal(String),
522 Identifier(Identifier),
523}
524
493impl<'a> TagBuilder<'a> { 525impl<'a> TagBuilder<'a> {
494 pub fn new(start: &Symbol) -> TagBuilder<'a> { 526 pub fn new(start: &Symbol) -> TagBuilder<'a> {
495 TagBuilder { 527 TagBuilder {
@@ -538,7 +570,7 @@ impl<'a> TagBuilder<'a> {
538 self.name = Some(name); 570 self.name = Some(name);
539 } 571 }
540 572
541 pub fn add_param(&mut self, param: String) { 573 pub fn add_param(&mut self, param: ParamValue) {
542 self.params.push( param ); 574 self.params.push( param );
543 } 575 }
544 576
@@ -565,8 +597,13 @@ impl<'a> TagBuilder<'a> {
565 pub fn build_view(mut self, ctx: &Context, outputs: Vec<Output>) -> ParseResult<View> { 597 pub fn build_view(mut self, ctx: &Context, outputs: Vec<Output>) -> ParseResult<View> {
566 if let Some(sym) = self.name { 598 if let Some(sym) = self.name {
567 if *sym.symbol() == SymbolType::View { 599 if *sym.symbol() == SymbolType::View {
600 let name = if let ParamValue::Literal(s) = self.params.swap_remove(0) {
601 s.to_string()
602 } else {
603 return Err(ParseError::new(Position::none(), "Expected string literal for view name."));
604 };
568 Ok(View { 605 Ok(View {
569 name: self.params.swap_remove(0), 606 name: name,
570 source: ctx.source(), 607 source: ctx.source(),
571 outputs: outputs, 608 outputs: outputs,
572 //theme: Option<String> 609 //theme: Option<String>
@@ -580,11 +617,16 @@ impl<'a> TagBuilder<'a> {
580 } 617 }
581 } 618 }
582 619
583 pub fn build_output(mut self, ctx: &Context) -> ParseResult<Output> { 620 pub fn build_output(mut self) -> ParseResult<Output> {
584 if let Some(sym) = self.name { 621 if let Some(sym) = self.name {
585 if *sym.symbol() == SymbolType::Output { 622 if *sym.symbol() == SymbolType::Output {
623 let name = if let ParamValue::Literal(s) = self.params.swap_remove(0) {
624 s.to_string()
625 } else {
626 return Err(ParseError::new(Position::none(), "Expected string literal for output name."));
627 };
586 Ok(Output { 628 Ok(Output {
587 name: self.params.swap_remove(0), 629 name: name,
588 code: self.children, 630 code: self.children,
589 }) 631 })
590 } else { 632 } else {
@@ -599,7 +641,12 @@ impl<'a> TagBuilder<'a> {
599 if let Some(sym) = self.name { 641 if let Some(sym) = self.name {
600 match sym.symbol() { 642 match sym.symbol() {
601 SymbolType::Show => { 643 SymbolType::Show => {
602 Ok(Token::Show(self.params.swap_remove(0), self.props)) 644 let id = if let ParamValue::Identifier(id) = self.params.swap_remove(0) {
645 id
646 } else {
647 return Err(ParseError::new(Position::none(), "Identifier for show variable name."));
648 };
649 Ok(Token::Show(id, self.props))
603 } 650 }
604 _ => { 651 _ => {
605 Err(ParseError { 652 Err(ParseError {