mirror of
https://codeberg.org/icewind/php-literal-parser.git
synced 2026-06-03 10:34:08 +02:00
dont store source in SpannedError
This commit is contained in:
parent
9dc0f567ca
commit
5e8ad8f513
3 changed files with 74 additions and 37 deletions
44
src/error.rs
44
src/error.rs
|
|
@ -13,7 +13,9 @@ use std::num::ParseFloatError;
|
|||
use std::str::ParseBoolError;
|
||||
use thiserror::Error;
|
||||
|
||||
/// An error and related source span, will print out the problematic code fragment and error on `Display`
|
||||
/// An error and related source span
|
||||
///
|
||||
/// You can pretty-print the error with the offending source by using `display_with_source`
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
|
|
@ -28,19 +30,14 @@ use thiserror::Error;
|
|||
/// ```
|
||||
///
|
||||
#[derive(Debug)]
|
||||
pub struct SpannedError<'a, T: Error + Debug> {
|
||||
pub struct SpannedError<T: Error + Debug> {
|
||||
span: Span,
|
||||
source: &'a str,
|
||||
error: T,
|
||||
}
|
||||
|
||||
impl<'a, T: Error + Debug> SpannedError<'a, T> {
|
||||
pub fn new(error: T, span: Span, source: &'a str) -> Self {
|
||||
SpannedError {
|
||||
span,
|
||||
source,
|
||||
error,
|
||||
}
|
||||
impl<T: Error + Debug> SpannedError<T> {
|
||||
pub fn new(error: T, span: Span) -> Self {
|
||||
SpannedError { span, error }
|
||||
}
|
||||
|
||||
pub fn error(&self) -> &T {
|
||||
|
|
@ -48,23 +45,29 @@ impl<'a, T: Error + Debug> SpannedError<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Error + Debug + 'static> Error for SpannedError<'a, T> {
|
||||
impl<T: Error + Debug + 'static> Error for SpannedError<T> {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
Some(&self.error)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Error + Debug> Display for SpannedError<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
<T as Display>::fmt(&self.error, f)
|
||||
}
|
||||
}
|
||||
|
||||
const METRICS: DefaultMetrics = DefaultMetrics::with_tab_stop(4);
|
||||
|
||||
impl<'a, T: Error + Debug> fmt::Display for SpannedError<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let start = get_position(self.source, self.span.start);
|
||||
let end = get_position(self.source, self.span.end);
|
||||
impl<T: Error + Debug> SpannedError<T> {
|
||||
pub fn display_with_source(&self, source: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let start = get_position(source, self.span.start);
|
||||
let end = get_position(source, self.span.end);
|
||||
let span = SourceSpan::new(start, end, end.next_line());
|
||||
|
||||
let mut fmt = Formatter::with_margin_color(Color::Blue);
|
||||
let buffer = SourceBuffer::new(
|
||||
self.source.chars().map(|char| Result::<char, ()>::Ok(char)),
|
||||
source.chars().map(|char| Result::<char, ()>::Ok(char)),
|
||||
Position::default(),
|
||||
METRICS,
|
||||
);
|
||||
|
|
@ -186,15 +189,14 @@ impl ExpectToken for Token {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ResultExt<'a, T, E: Error + Debug> {
|
||||
fn with_span(self, span: Span, source: &'a str) -> Result<T, SpannedError<'a, E>>;
|
||||
pub trait ResultExt<T, E: Error + Debug> {
|
||||
fn with_span(self, span: Span) -> Result<T, SpannedError<E>>;
|
||||
}
|
||||
|
||||
impl<'a, T, E: Into<ParseError>> ResultExt<'a, T, ParseError> for Result<T, E> {
|
||||
fn with_span(self, span: Span, source: &'a str) -> Result<T, SpannedError<'a, ParseError>> {
|
||||
impl<T, E: Into<ParseError>> ResultExt<T, ParseError> for Result<T, E> {
|
||||
fn with_span(self, span: Span) -> Result<T, SpannedError<ParseError>> {
|
||||
self.map_err(|error| SpannedError {
|
||||
span,
|
||||
source,
|
||||
error: error.into(),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
37
src/lexer.rs
37
src/lexer.rs
|
|
@ -1,4 +1,4 @@
|
|||
use logos::Logos;
|
||||
use logos::{Lexer, Logos, Span};
|
||||
|
||||
#[derive(Logos, Debug, PartialEq, Clone)]
|
||||
pub enum Token {
|
||||
|
|
@ -165,3 +165,38 @@ fn test_lex_float() {
|
|||
assert_eq!(lex.next(), Some(Token::Float));
|
||||
assert_eq!(lex.next(), None);
|
||||
}
|
||||
|
||||
pub struct SpannedToken<'source> {
|
||||
pub token: Token,
|
||||
pub span: Span,
|
||||
pub source: &'source str,
|
||||
}
|
||||
|
||||
impl<'source> SpannedToken<'source> {
|
||||
pub fn slice(&self) -> &'source str {
|
||||
&self.source[self.span.clone()]
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TokenStream<'source> {
|
||||
lexer: Lexer<'source, Token>,
|
||||
}
|
||||
|
||||
impl<'source> TokenStream<'source> {
|
||||
pub fn source(&self) -> &'source str {
|
||||
self.lexer.source()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'source> Iterator for TokenStream<'source> {
|
||||
type Item = SpannedToken<'source>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let token = self.lexer.next()?;
|
||||
Some(SpannedToken {
|
||||
token,
|
||||
span: self.lexer.span(),
|
||||
source: self.lexer.source(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ impl<'source> Parser<'source> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(&mut self) -> Result<Value, SpannedError<'source, ParseError>> {
|
||||
pub fn parse(&mut self) -> Result<Value, SpannedError<ParseError>> {
|
||||
let token = self
|
||||
.lexer
|
||||
.next()
|
||||
|
|
@ -56,24 +56,24 @@ impl<'source> Parser<'source> {
|
|||
Token::Array,
|
||||
Token::SquareOpen,
|
||||
])
|
||||
.with_span(self.lexer.span(), self.source)?;
|
||||
.with_span(self.lexer.span())?;
|
||||
let value = match token {
|
||||
Token::Bool => Value::Bool(
|
||||
self.lexer
|
||||
.slice()
|
||||
.to_ascii_lowercase()
|
||||
.parse()
|
||||
.with_span(self.lexer.span(), self.source)?,
|
||||
.with_span(self.lexer.span())?,
|
||||
),
|
||||
Token::Integer => {
|
||||
Value::Int(parse_int(self.lexer.slice()).with_span(self.lexer.span(), self.source)?)
|
||||
Value::Int(parse_int(self.lexer.slice()).with_span(self.lexer.span())?)
|
||||
}
|
||||
Token::Float => {
|
||||
Value::Float(parse_float(self.lexer.slice()).with_span(self.lexer.span())?)
|
||||
}
|
||||
Token::LiteralString => {
|
||||
Value::String(parse_string(self.lexer.slice()).with_span(self.lexer.span())?)
|
||||
}
|
||||
Token::Float => Value::Float(
|
||||
parse_float(self.lexer.slice()).with_span(self.lexer.span(), self.source)?,
|
||||
),
|
||||
Token::LiteralString => Value::String(
|
||||
parse_string(self.lexer.slice()).with_span(self.lexer.span(), self.source)?,
|
||||
),
|
||||
Token::Null => Value::Null,
|
||||
Token::Array => Value::Array(self.parse_array(ArraySyntax::Long)?),
|
||||
Token::SquareOpen => Value::Array(self.parse_array(ArraySyntax::Short)?),
|
||||
|
|
@ -86,14 +86,14 @@ impl<'source> Parser<'source> {
|
|||
fn parse_array(
|
||||
&mut self,
|
||||
syntax: ArraySyntax,
|
||||
) -> Result<HashMap<Key, Value>, SpannedError<'source, ParseError>> {
|
||||
) -> Result<HashMap<Key, Value>, SpannedError<ParseError>> {
|
||||
let mut builder = ArrayBuilder::default();
|
||||
|
||||
if syntax == ArraySyntax::Long {
|
||||
self.lexer
|
||||
.next()
|
||||
.expect_token(&[Token::BracketOpen])
|
||||
.with_span(self.lexer.span(), self.source)?;
|
||||
.with_span(self.lexer.span())?;
|
||||
}
|
||||
|
||||
loop {
|
||||
|
|
@ -115,7 +115,7 @@ impl<'source> Parser<'source> {
|
|||
.lexer
|
||||
.next()
|
||||
.expect_token(&[syntax.close_bracket(), Token::Comma, Token::Arrow])
|
||||
.with_span(self.lexer.span(), self.source)?;
|
||||
.with_span(self.lexer.span())?;
|
||||
|
||||
match next {
|
||||
Token::BracketClose => {
|
||||
|
|
@ -137,7 +137,7 @@ impl<'source> Parser<'source> {
|
|||
Value::String(str) => Key::String(str),
|
||||
value => {
|
||||
let err = ParseError::InvalidArrayKey(InvalidArrayKeyError(value));
|
||||
let span_err = SpannedError::new(err, key_or_value_span, self.source);
|
||||
let span_err = SpannedError::new(err, key_or_value_span);
|
||||
return Err(span_err);
|
||||
}
|
||||
};
|
||||
|
|
@ -147,7 +147,7 @@ impl<'source> Parser<'source> {
|
|||
.lexer
|
||||
.next()
|
||||
.expect_token(&[syntax.close_bracket(), Token::Comma])
|
||||
.with_span(self.lexer.span(), self.source)?
|
||||
.with_span(self.lexer.span())?
|
||||
{
|
||||
Token::BracketClose => {
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue