Fix parse error returning the token after the error
This commit is contained in:
		
							parent
							
								
									6dfd98eba3
								
							
						
					
					
						commit
						0f782dcb96
					
				| @ -128,7 +128,7 @@ impl Parse for PrimaryExpression { | ||||
|                     stream.expect(Token::BracketClose)?; | ||||
|                     Expression(Kind::Array(expressions), stream.get_range().unwrap()) | ||||
|                 } | ||||
|                 _ => Err(stream.expected_err("identifier, constant, parentheses or brackets")?)?, | ||||
|                 _ => Err(stream.expected_err("expression")?)?, | ||||
|             } | ||||
|         } else { | ||||
|             Err(stream.expected_err("expression")?)? | ||||
| @ -391,7 +391,8 @@ impl Parse for Block { | ||||
|                 // Special list of expressions that are simply not warned about,
 | ||||
|                 // if semicolon is missing.
 | ||||
|                 if !matches!(e, Expression(ExpressionKind::IfExpr(_), _)) { | ||||
|                     println!("Oh no, does this statement lack ;"); | ||||
|                     // In theory could ignore the missing semicolon..
 | ||||
|                     return Err(stream.expected_err("expected semicolon to complete statement")?); | ||||
|                 } | ||||
| 
 | ||||
|                 statements.push(BlockLevelStatement::Expression(e)); | ||||
| @ -445,7 +446,7 @@ impl<T: Parse + std::fmt::Debug> Parse for NamedFieldList<T> { | ||||
|                     stream.next(); | ||||
|                 } // Consume comma
 | ||||
|                 Some(Token::BraceClose) => break, | ||||
|                 Some(_) | None => Err(stream.expected_err("another field or closing brace")?)?, | ||||
|                 Some(_) | None => Err(stream.expecting_err("another field or closing brace")?)?, | ||||
|             } | ||||
|         } | ||||
|         Ok(NamedFieldList(fields)) | ||||
| @ -478,7 +479,7 @@ impl Parse for ValueIndex { | ||||
|         match stream.peek() { | ||||
|             Some(Token::BracketOpen) => Ok(ValueIndex::Array(stream.parse()?)), | ||||
|             Some(Token::Dot) => Ok(ValueIndex::Struct(stream.parse()?)), | ||||
|             _ => Err(stream.expected_err("value or struct index")?), | ||||
|             _ => Err(stream.expecting_err("value or struct index")?), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -534,7 +535,7 @@ impl Parse for BlockLevelStatement { | ||||
|                             Stmt::Return(ReturnType::Soft, e) | ||||
|                         } | ||||
|                     } else { | ||||
|                         Err(stream.expected_err("expression")?)? | ||||
|                         Err(stream.expecting_err("expression")?)? | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @ -605,7 +606,7 @@ impl Parse for TopLevelStatement { | ||||
|                     range, | ||||
|                 }) | ||||
|             } | ||||
|             _ => Err(stream.expected_err("import or fn")?)?, | ||||
|             _ => Err(stream.expecting_err("import or fn")?)?, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -156,8 +156,8 @@ impl ReidError { | ||||
|             let pass_err = pass::Error { | ||||
|                 metadata: Metadata { | ||||
|                     source_module_id: module, | ||||
|                     range: Default::default(), | ||||
|                     position: error.get_position().copied(), | ||||
|                     range: *error.get_range().unwrap_or(&Default::default()), | ||||
|                     position: None, | ||||
|                 }, | ||||
|                 kind: error, | ||||
|             }; | ||||
| @ -185,24 +185,16 @@ impl std::fmt::Display for ReidError { | ||||
|         for error in sorted_errors { | ||||
|             let meta = error.get_meta(); | ||||
|             let module = self.map.get_module(&meta.source_module_id).unwrap(); | ||||
|             let (position_fmt, line_fmt) = if let Some(tokens) = &module.tokens { | ||||
|             let position = if let Some(tokens) = &module.tokens { | ||||
|                 let range_tokens = meta.range.into_tokens(&tokens); | ||||
|                 let highlight_position = get_position(&range_tokens).unwrap(); | ||||
|                 let full_lines = get_full_lines(&tokens, highlight_position); | ||||
|                 let lines_position = get_position(&full_lines).unwrap(); | ||||
|                 ( | ||||
|                     fmt_positions(highlight_position), | ||||
|                     Some(fmt_lines( | ||||
|                         module.source.as_ref().unwrap(), | ||||
|                         lines_position, | ||||
|                         highlight_position, | ||||
|                         8, | ||||
|                     )?), | ||||
|                 ) | ||||
| 
 | ||||
|                 dbg!(&error); | ||||
|                 dbg!(&meta.range, &tokens[meta.range.start]); | ||||
|                 get_position(&range_tokens).or(meta.position.map(|p| (p, p))) | ||||
|             } else if let Some(position) = meta.position { | ||||
|                 (fmt_positions((position, position)), None) | ||||
|                 Some((position, position)) | ||||
|             } else { | ||||
|                 ("unknown".to_owned(), None) | ||||
|                 None | ||||
|             }; | ||||
| 
 | ||||
|             if curr_module != Some(meta.source_module_id) { | ||||
| @ -223,9 +215,16 @@ impl std::fmt::Display for ReidError { | ||||
|             writeln!(f)?; | ||||
|             write!(f, "  Error: ")?; | ||||
|             writeln!(f, "{}", color_err(format!("{}", error))?)?; | ||||
|             write!(f, "{:>20}{}", color_warn("At: ")?, position_fmt)?; | ||||
|             if let Some(line_fmt) = line_fmt { | ||||
|                 writeln!(f, "{}", line_fmt)?; | ||||
|             write!( | ||||
|                 f, | ||||
|                 "{:>20}{}", | ||||
|                 color_warn("At: ")?, | ||||
|                 position | ||||
|                     .map(|p| fmt_positions(p)) | ||||
|                     .unwrap_or(String::from("{unknown}")), | ||||
|             )?; | ||||
|             if let (Some(position), Some(source)) = (position, &module.source) { | ||||
|                 writeln!(f, "{}", fmt_lines(source, position, 6)?)?; | ||||
|             } | ||||
|         } | ||||
|         Ok(()) | ||||
| @ -238,7 +237,7 @@ impl TokenRange { | ||||
|             .iter() | ||||
|             .skip(self.start) | ||||
|             .by_ref() | ||||
|             .take(self.end - self.start) | ||||
|             .take(self.end + 1 - self.start) | ||||
|             .collect::<Vec<_>>() | ||||
|     } | ||||
| } | ||||
| @ -252,29 +251,16 @@ fn get_position(tokens: &Vec<&FullToken>) -> Option<(Position, Position)> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn get_full_lines<'v>( | ||||
|     tokens: &'v Vec<FullToken>, | ||||
|     (start, end): (Position, Position), | ||||
| ) -> Vec<&'v FullToken> { | ||||
|     let (first_token_pos, _) = tokens | ||||
|         .iter() | ||||
|         .enumerate() | ||||
|         .find(|(_, token)| token.position.1 == start.1) | ||||
|         .unwrap(); | ||||
|     tokens | ||||
|         .iter() | ||||
|         .skip(first_token_pos) | ||||
|         .by_ref() | ||||
|         .take_while(|token| token.position.1 <= end.1) | ||||
|         .collect::<Vec<_>>() | ||||
| fn into_full_lines<'v>((start, end): (Position, Position)) -> (Position, Position) { | ||||
|     (Position(0, start.1), Position(u32::MAX, end.1)) | ||||
| } | ||||
| 
 | ||||
| fn fmt_lines( | ||||
|     source: &String, | ||||
|     (line_start, line_end): (Position, Position), | ||||
|     (highlight_start, highlight_end): (Position, Position), | ||||
|     ident: usize, | ||||
| ) -> Result<String, std::fmt::Error> { | ||||
|     let (line_start, line_end) = into_full_lines((highlight_start, highlight_end)); | ||||
|     let mut cursor = Cursor { | ||||
|         position: Position(0, 1), | ||||
|         char_stream: source.chars(), | ||||
|  | ||||
| @ -24,11 +24,31 @@ impl<'a, 'b> TokenStream<'a, 'b> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns expected-error for the next token in-line. Useful in conjunction
 | ||||
|     /// with [`TokenStream::peek`]
 | ||||
|     pub fn expected_err<T: Into<String>>(&mut self, expected: T) -> Result<Error, Error> { | ||||
|         let next_token = self.previous().unwrap_or(Token::Eof); | ||||
|         Ok(Error::Expected( | ||||
|             expected.into(), | ||||
|             self.peek().unwrap_or(Token::Eof), | ||||
|             self.get_next_position()?, | ||||
|             next_token, | ||||
|             TokenRange { | ||||
|                 start: self.position - 1, | ||||
|                 end: self.position - 1, | ||||
|             }, | ||||
|         )) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns expected-error for the previous token that was already consumed.
 | ||||
|     /// Useful in conjunction with [`TokenStream::next`]
 | ||||
|     pub fn expecting_err<T: Into<String>>(&mut self, expected: T) -> Result<Error, Error> { | ||||
|         let next_token = self.peek().unwrap_or(Token::Eof); | ||||
|         Ok(Error::Expected( | ||||
|             expected.into(), | ||||
|             next_token, | ||||
|             TokenRange { | ||||
|                 start: self.position, | ||||
|                 end: self.position, | ||||
|             }, | ||||
|         )) | ||||
|     } | ||||
| 
 | ||||
| @ -38,10 +58,10 @@ impl<'a, 'b> TokenStream<'a, 'b> { | ||||
|                 self.position += 1; | ||||
|                 Ok(()) | ||||
|             } else { | ||||
|                 Err(self.expected_err(token)?) | ||||
|                 Err(self.expecting_err(token)?) | ||||
|             } | ||||
|         } else { | ||||
|             Err(self.expected_err(token)?) | ||||
|             Err(self.expecting_err(token)?) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -55,6 +75,14 @@ impl<'a, 'b> TokenStream<'a, 'b> { | ||||
|         value | ||||
|     } | ||||
| 
 | ||||
|     pub fn previous(&mut self) -> Option<Token> { | ||||
|         if (self.position as i32 - 1) < 0 { | ||||
|             None | ||||
|         } else { | ||||
|             Some(self.tokens[self.position - 1].token.clone()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn peek(&mut self) -> Option<Token> { | ||||
|         if self.tokens.len() < self.position { | ||||
|             None | ||||
| @ -147,11 +175,11 @@ impl<'a, 'b> TokenStream<'a, 'b> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn get_next_position(&self) -> Result<Position, Error> { | ||||
|     fn get_position(&self, offset: usize) -> Result<Position, Error> { | ||||
|         if self.tokens.is_empty() { | ||||
|             Err(Error::FileEmpty) | ||||
|         } else { | ||||
|             let token_idx = self.position.min(self.tokens.len() - 1); | ||||
|             let token_idx = (self.position - 1).min(self.tokens.len() - 1); | ||||
|             Ok(self.tokens[token_idx].position) | ||||
|         } | ||||
|     } | ||||
| @ -210,7 +238,7 @@ impl std::iter::Sum for TokenRange { | ||||
| #[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum Error { | ||||
|     #[error("Expected {} got {:?}", .0, .1)] | ||||
|     Expected(String, Token, Position), | ||||
|     Expected(String, Token, TokenRange), | ||||
|     #[error("Source file contains no tokens")] | ||||
|     FileEmpty, | ||||
|     /// Only use this error in situations where the error never ends up for the end-user!
 | ||||
| @ -222,7 +250,7 @@ pub enum Error { | ||||
| } | ||||
| 
 | ||||
| impl Error { | ||||
|     pub fn get_position(&self) -> Option<&Position> { | ||||
|     pub fn get_range(&self) -> Option<&TokenRange> { | ||||
|         match self { | ||||
|             Error::Expected(_, _, pos) => Some(pos), | ||||
|             Error::FileEmpty => None, | ||||
|  | ||||
| @ -5,7 +5,7 @@ struct Test { | ||||
|     second: [u32; 4] | ||||
| } | ||||
| 
 | ||||
| fn main() -> u32 { | ||||
| fn main() -> v u32 { | ||||
|     let mut value = [Test { | ||||
|         field: 5, | ||||
|         second: [6, 3, "hello", 8], | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user