From 92dbff3cda66a2a677f0c2306bb8508c64884445 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 11 Jun 2026 10:43:24 -0700 Subject: Broke out error and renamed it. I like the new name, now it could be for all sorts. --- src/parser.rs | 221 ++++++++++++++++++++++++---------------------------------- 1 file changed, 91 insertions(+), 130 deletions(-) (limited to 'src/parser.rs') diff --git a/src/parser.rs b/src/parser.rs index 07bbd93..83144fb 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,41 +1,6 @@ use crate::lexer::*; use crate::*; -use core::error::Error; -use std::fmt; - -#[derive(Debug)] -pub struct ParseError { - position: Position, - what: String, -} - -impl ParseError { - pub fn new( position: Position, what: &str ) -> Self { - ParseError { - position, - what: what.to_string(), - } - } - - pub fn eos( context: &str ) -> Self { - ParseError { - position: Position::none(), - what: format!("Premature end of stream while looking for {}", context), - } - } -} - -impl fmt::Display for ParseError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Error parsing input: {}", "yeah") - } -} - -impl Error for ParseError { } - -pub type ParseResult = Result; - struct Context<'a> { cur: [Option>;2], icur: usize, @@ -70,9 +35,9 @@ impl<'a> Context<'a> { self.cur[(self.icur+1)%2] } - pub fn check_unwrapped bool>(&self, context: &str, f: T) -> ParseResult { + pub fn check_unwrapped bool>(&self, context: &str, f: T) -> CrimResult { if self.cur().is_none() || self.peek().is_none() { - Err(ParseError::eos( context )) + Err(CrimError::eos( context )) } else { Ok(f( self.cur().unwrap().symbol(), self.peek().unwrap().symbol())) } @@ -84,34 +49,37 @@ impl<'a> Context<'a> { } trait SymbolHelper { - fn is bool>(&self, context: &str, f: T ) -> ParseResult; - fn is_valid_tag_name(&self) -> ParseResult; + fn is bool>(&self, context: &str, f: T ) -> CrimResult; + fn is_valid_tag_name(&self) -> CrimResult; } impl<'a> SymbolHelper for Option> { - fn is bool>(&self, context: &str, f: T ) -> ParseResult { + fn is bool>(&self, context: &str, f: T ) -> CrimResult { if let Some(st) = self { Ok(f( &st.symbol() )) } else { - Err(ParseError::eos( context )) + Err(CrimError::eos( context )) } } - fn is_valid_tag_name(&self) -> ParseResult { + fn is_valid_tag_name(&self) -> CrimResult { if let Some(st) = self { Ok(match st.symbol() { SymbolType::Token(_) | SymbolType::View | SymbolType::Output | SymbolType::Loop | + SymbolType::If | + SymbolType::ElseIf | + SymbolType::Else | SymbolType::Show => true, _ => false }) } else { - Err(ParseError{ - position: Position::new(0,0), - what: "Unexpeceted end of stream.".to_string() - }) + Err(CrimError::new( + Position::none(), + "Unexpeceted end of stream.".to_string() + )) } } } @@ -202,21 +170,17 @@ impl Parser { } } - fn lex_error(&self, error: &Symbol) -> ParseResult { + fn lex_error(&self, error: &Symbol) -> CrimResult { if let SymbolType::Error{what} = error.symbol() { - Err(ParseError { - position: error.start().clone(), - what: format!("What: {:?}", *what) - }) + Err(CrimError::new( *error.start(), + format!("What: {:?}", *what) + )) } else { - Err(ParseError { - position: Position::new(0,0), - what: "Not an error?".to_string(), - }) + Err(CrimError::new( Position::none(), "Not an error?".into())) } } - pub fn parse(&self, src: &str, source: usize ) -> ParseResult> { + pub fn parse(&self, src: &str, source: usize ) -> CrimResult> { let ll = Lexer::new( src ); let mut ctx = Context::new( ll, source ); @@ -224,7 +188,7 @@ impl Parser { self.p_input( &mut ctx ) } - fn p_input(&self, ctx: &mut Context ) -> ParseResult> { + fn p_input(&self, ctx: &mut Context ) -> CrimResult> { let mut children = Vec::new(); loop { if ctx.cur().is_none() { @@ -247,13 +211,12 @@ impl Parser { Ok(children) } - fn parse_tag_view(&self, ctx: &mut Context) -> ParseResult { + fn parse_tag_view(&self, ctx: &mut Context) -> CrimResult { let tb = self.parse_open_tag( ctx )?; if !tb.is_name( &SymbolType::View ) { - return Err(ParseError{ - position: tb.start_pos(), - what: "Unexpected tag type, only frament allowed at root".to_string(), - }); + return Err(CrimError::new(tb.start_pos(), + "Unexpected tag type, only frament allowed at root".into() + )); } if tb.is_unary() { @@ -265,7 +228,7 @@ impl Parser { //println!("--parse-tag-view-- tag parsed, next token: {:?}", ctx.cur() ); loop { if ctx.cur().is_none() { - return Err(ParseError::eos(format!("close tag for {:?}", tb.name()).as_str())) + return Err(CrimError::eos(format!("close tag for {:?}", tb.name()).as_str())) } match ctx.cur().unwrap().symbol() { SymbolType::Text(s) => { @@ -297,52 +260,56 @@ impl Parser { }); } else { if !all_text { - return Err(ParseError{ - position: *end.start(), - what: "You cannot mix non-output and output tags in a view.".to_string() - }); + return Err(CrimError::new( + *end.start(), + "You cannot mix non-output and output tags in a view.".to_string() + )); } } return tb.build_view(ctx,outputs); } else { // They don't match, complain. - return Err(ParseError{ - position: *end.start(), - what: "Mismatched open and closing tags.".to_string() - }); + return Err(CrimError::new( + *end.start(), + "Mismatched open and closing tags.".to_string() + )); } } SymbolType::Error{..} => { return self.lex_error( &ctx.cur().unwrap() ); } _ => { - return Err(ParseError{ - position: *ctx.cur().unwrap().start(), - what: format!("Unexpected tag in view root: {:?}", ctx.cur().unwrap().symbol()) - }); + return Err(CrimError::new( + *ctx.cur().unwrap().start(), + format!("Unexpected tag in view root: {:?}", ctx.cur().unwrap().symbol()) + )); } } } } - fn parse_open_tag<'a>(&self, ctx: &mut Context<'a>) -> ParseResult> { + fn parse_open_tag<'a>(&self, ctx: &mut Context<'a>) -> CrimResult> { let start_sym = ctx.cur().unwrap(); let mut tb = TagBuilder::new(&start_sym); if ctx.next().is_some() { match ctx.cur().unwrap().symbol() { SymbolType::View | SymbolType::Show | SymbolType::Loop | + SymbolType::If | SymbolType::ElseIf | SymbolType::Else | SymbolType::Output => { let name_sym = ctx.cur().unwrap(); ctx.next(); tb.set_name( name_sym ); } _ => { - return Err(ParseError{position: ctx.cur().unwrap().start().clone(), what: "Unexpected symbol".to_string()}); + return Err(CrimError::new( + *ctx.cur().unwrap().start(), + "Unexpected symbol".to_string() + )); } } } else { - return Err(ParseError::eos("tag type")); + return Err(CrimError::eos("tag type")); } self.parse_tag_params( ctx, &mut tb )?; @@ -357,9 +324,9 @@ impl Parser { tb.set_type( TagType::Unary ); } _ => { - return Err(ParseError::new( - end_sym.start().clone(), - format!("Unexpected symbol {:?} looking for end of tag.", end_sym.symbol()).as_str() + return Err(CrimError::new( + *end_sym.start(), + format!("Unexpected symbol {:?} looking for end of tag.", end_sym.symbol()) )); } } @@ -370,31 +337,31 @@ impl Parser { Ok(tb) } - fn parse_end_tag<'a>(&self, ctx: &mut Context<'a> ) -> ParseResult> { + fn parse_end_tag<'a>(&self, ctx: &mut Context<'a> ) -> CrimResult> { if !ctx.cur().is("end tag",|s| *s == SymbolType::StartPoint )? { - return Err(ParseError{ - position: *ctx.cur().unwrap().start(), - what: "Invalid end tag?".to_string(), - }); + return Err(CrimError::new( + *ctx.cur().unwrap().start(), + "Invalid end tag?".to_string() + )); } if !ctx.next().is_valid_tag_name()? { - return Err(ParseError{ - position: *ctx.cur().unwrap().start(), - what: "Invalid tag name".to_string(), - }); + return Err(CrimError::new( + *ctx.cur().unwrap().start(), + "Invalid tag name".to_string() + )); } let name = ctx.cur().unwrap(); if !ctx.next().is("end of end tag", |s| *s == SymbolType::EndFlat )? { - return Err(ParseError{ - position: *ctx.cur().unwrap().start(), - what: "Tag should be <| |] style end tag.".to_string(), - }); + return Err(CrimError::new( + *ctx.cur().unwrap().start(), + "Tag should be <| |] style end tag.".to_string(), + )); } ctx.next(); Ok(name) } - fn parse_tag_body<'a>(&self, ctx: &mut Context<'a> ) -> ParseResult> { + fn parse_tag_body<'a>(&self, ctx: &mut Context<'a> ) -> CrimResult> { let mut tb = self.parse_open_tag( ctx )?; if tb.is_unary() { return Ok(tb); @@ -402,7 +369,7 @@ impl Parser { loop { if ctx.cur().is_none() { - return Err(ParseError::eos(format!("close tag for {:?}", tb.name()).as_str())); + return Err(CrimError::eos(format!("close tag for {:?}", tb.name()).as_str())); } match ctx.cur().unwrap().symbol() { SymbolType::Text(s) => { @@ -419,29 +386,29 @@ impl Parser { return Ok(tb); } else { // They don't match, complain. - return Err(ParseError{ - position: *end.start(), - what: "Mismatched open and closing tags.".to_string() - }); + return Err(CrimError::new( + *end.start(), + "Mismatched open and closing tags.".to_string() + )); } } SymbolType::Error{..} => { return self.lex_error( &ctx.cur().unwrap() ); } _ => { - return Err(ParseError{ - position: ctx.cur().unwrap().start().clone(), - what: format!("Unexpected token: {:?}", ctx.cur().unwrap().symbol()), - }); + return Err(CrimError::new( + *ctx.cur().unwrap().start(), + format!("Unexpected token: {:?}", ctx.cur().unwrap().symbol()), + )); } } } } - fn parse_tag_params(&self, ctx: &mut Context, tb: &mut TagBuilder ) -> ParseResult<()> { + fn parse_tag_params(&self, ctx: &mut Context, tb: &mut TagBuilder ) -> CrimResult<()> { loop { if ctx.cur().is_none() { - return Err(ParseError::eos("tag parameters")); + return Err(CrimError::eos("tag parameters")); } match ctx.cur().unwrap().symbol() { SymbolType::Literal(s) => { @@ -462,7 +429,7 @@ impl Parser { Ok(()) } - fn parse_identifier(&self, ctx: &mut Context ) -> ParseResult { + fn parse_identifier(&self, ctx: &mut Context ) -> CrimResult { let mut id = Identifier::new(); loop { @@ -471,7 +438,7 @@ impl Parser { id.push( IdentifierValue::Name(s.to_string()) ); } } else { - return Err(ParseError::new( ctx.cur().unwrap().start().clone(), &format!("Expeceted identifier, found {:?}", ctx.cur().unwrap().symbol() ) ) ); + return Err(CrimError::new( ctx.cur().unwrap().start().clone(), format!("Expeceted identifier, found {:?}", ctx.cur().unwrap().symbol() ) ) ); } if !ctx.next().is("identifier seperator",|s| *s == SymbolType::Period )? { @@ -483,10 +450,10 @@ impl Parser { Ok(ParamValue::Identifier(id)) } - fn parse_tag_props(&self, ctx: &mut Context, tb: &mut TagBuilder ) -> ParseResult<()> { + fn parse_tag_props(&self, ctx: &mut Context, tb: &mut TagBuilder ) -> CrimResult<()> { loop { if ctx.cur().is_none() { - return Err(ParseError::eos("tag properties")); + return Err(CrimError::eos("tag properties")); } if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() { if ctx.peek().is_some_and(|s|s.check_type(|t| matches!(t,SymbolType::Equals))) { @@ -495,7 +462,7 @@ impl Parser { let SymbolType::Literal(lv) = sym.symbol() { tb.add_prop( s.to_string(), lv.to_string() ); } else { - return Err(ParseError{position: Position::new(0,0), what: "Expected quoted literal string".to_string()}); + return Err(CrimError::new(Position::none(),"Expected quoted literal string".to_string())); } } else { break; @@ -607,13 +574,13 @@ impl<'a> TagBuilder<'a> { self.tag_type } - pub fn build_view(mut self, ctx: &Context, outputs: Vec) -> ParseResult { + pub fn build_view(mut self, ctx: &Context, outputs: Vec) -> CrimResult { if let Some(sym) = self.name { if *sym.symbol() == SymbolType::View { let name = if let ParamValue::Literal(s) = self.params.swap_remove(0) { s.to_string() } else { - return Err(ParseError::new(Position::none(), "Expected string literal for view name.")); + return Err(CrimError::new(Position::none(), "Expected string literal for view name.".to_string())); }; Ok(View { name: name, @@ -623,41 +590,41 @@ impl<'a> TagBuilder<'a> { layout: self.props.get("layout").cloned(), }) } else { - Err(ParseError::new(self.start_pos, &format!("Expected tag type view, found {:?}", sym.symbol()))) + Err(CrimError::new(self.start_pos, format!("Expected tag type view, found {:?}", sym.symbol()))) } } else { - Err(ParseError::new(self.start_pos, "Broken Parser? No tag type found when building view.")) + Err(CrimError::new(self.start_pos, "Broken Parser? No tag type found when building view.".to_string())) } } - pub fn build_output(mut self) -> ParseResult { + pub fn build_output(mut self) -> CrimResult { if let Some(sym) = self.name { if *sym.symbol() == SymbolType::Output { let name = if let ParamValue::Literal(s) = self.params.swap_remove(0) { s.to_string() } else { - return Err(ParseError::new(Position::none(), "Expected string literal for output name.")); + return Err(CrimError::new(Position::none(), "Expected string literal for output name.".into())); }; Ok(Output { name: name, code: self.children, }) } else { - Err(ParseError::new(self.start_pos, &format!("Expected tag type view, found {:?}", sym.symbol()))) + Err(CrimError::new(self.start_pos, format!("Expected tag type view, found {:?}", sym.symbol()))) } } else { - Err(ParseError::new(self.start_pos, "Broken Parser? No tag type found when building view.")) + Err(CrimError::new(self.start_pos, "Broken Parser? No tag type found when building view.".into())) } } - pub fn build(mut self) -> ParseResult { + pub fn build(mut self) -> CrimResult { if let Some(sym) = self.name { match sym.symbol() { SymbolType::Loop => { let id = if let ParamValue::Identifier(id) = self.params.swap_remove(0) { id } else { - return Err(ParseError::new(Position::none(), "Identifier for loop variable name.")); + return Err(CrimError::new(Position::none(), "Identifier for loop variable name.".into())); }; Ok(Token::Loop(id, self.children)) } @@ -665,22 +632,16 @@ impl<'a> TagBuilder<'a> { let id = if let ParamValue::Identifier(id) = self.params.swap_remove(0) { id } else { - return Err(ParseError::new(Position::none(), "Identifier for show variable name.")); + return Err(CrimError::new(Position::none(), "Identifier for show variable name.".into())); }; Ok(Token::Show(id, self.props)) } _ => { - Err(ParseError { - position: self.start_pos, - what: "Bad tag type".to_string(), - }) + Err(CrimError::new( self.start_pos, "Bad tag type".into())) } } } else { - Err(ParseError { - position: self.start_pos, - what: "Bad tag type".to_string(), - }) + Err(CrimError::new(self.start_pos, "Bad tag type".into())) } } } -- cgit v1.2.3