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 std::str::ParseBoolError;
|
||||||
use thiserror::Error;
|
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
|
/// ## Example
|
||||||
///
|
///
|
||||||
|
|
@ -28,19 +30,14 @@ use thiserror::Error;
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SpannedError<'a, T: Error + Debug> {
|
pub struct SpannedError<T: Error + Debug> {
|
||||||
span: Span,
|
span: Span,
|
||||||
source: &'a str,
|
|
||||||
error: T,
|
error: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Error + Debug> SpannedError<'a, T> {
|
impl<T: Error + Debug> SpannedError<T> {
|
||||||
pub fn new(error: T, span: Span, source: &'a str) -> Self {
|
pub fn new(error: T, span: Span) -> Self {
|
||||||
SpannedError {
|
SpannedError { span, error }
|
||||||
span,
|
|
||||||
source,
|
|
||||||
error,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(&self) -> &T {
|
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)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
Some(&self.error)
|
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);
|
const METRICS: DefaultMetrics = DefaultMetrics::with_tab_stop(4);
|
||||||
|
|
||||||
impl<'a, T: Error + Debug> fmt::Display for SpannedError<'a, T> {
|
impl<T: Error + Debug> SpannedError<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
pub fn display_with_source(&self, source: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let start = get_position(self.source, self.span.start);
|
let start = get_position(source, self.span.start);
|
||||||
let end = get_position(self.source, self.span.end);
|
let end = get_position(source, self.span.end);
|
||||||
let span = SourceSpan::new(start, end, end.next_line());
|
let span = SourceSpan::new(start, end, end.next_line());
|
||||||
|
|
||||||
let mut fmt = Formatter::with_margin_color(Color::Blue);
|
let mut fmt = Formatter::with_margin_color(Color::Blue);
|
||||||
let buffer = SourceBuffer::new(
|
let buffer = SourceBuffer::new(
|
||||||
self.source.chars().map(|char| Result::<char, ()>::Ok(char)),
|
source.chars().map(|char| Result::<char, ()>::Ok(char)),
|
||||||
Position::default(),
|
Position::default(),
|
||||||
METRICS,
|
METRICS,
|
||||||
);
|
);
|
||||||
|
|
@ -186,15 +189,14 @@ impl ExpectToken for Token {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ResultExt<'a, T, E: Error + Debug> {
|
pub trait ResultExt<T, E: Error + Debug> {
|
||||||
fn with_span(self, span: Span, source: &'a str) -> Result<T, SpannedError<'a, E>>;
|
fn with_span(self, span: Span) -> Result<T, SpannedError<E>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, E: Into<ParseError>> ResultExt<'a, T, ParseError> for Result<T, E> {
|
impl<T, E: Into<ParseError>> ResultExt<T, ParseError> for Result<T, E> {
|
||||||
fn with_span(self, span: Span, source: &'a str) -> Result<T, SpannedError<'a, ParseError>> {
|
fn with_span(self, span: Span) -> Result<T, SpannedError<ParseError>> {
|
||||||
self.map_err(|error| SpannedError {
|
self.map_err(|error| SpannedError {
|
||||||
span,
|
span,
|
||||||
source,
|
|
||||||
error: error.into(),
|
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)]
|
#[derive(Logos, Debug, PartialEq, Clone)]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
|
|
@ -165,3 +165,38 @@ fn test_lex_float() {
|
||||||
assert_eq!(lex.next(), Some(Token::Float));
|
assert_eq!(lex.next(), Some(Token::Float));
|
||||||
assert_eq!(lex.next(), None);
|
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
|
let token = self
|
||||||
.lexer
|
.lexer
|
||||||
.next()
|
.next()
|
||||||
|
|
@ -56,24 +56,24 @@ impl<'source> Parser<'source> {
|
||||||
Token::Array,
|
Token::Array,
|
||||||
Token::SquareOpen,
|
Token::SquareOpen,
|
||||||
])
|
])
|
||||||
.with_span(self.lexer.span(), self.source)?;
|
.with_span(self.lexer.span())?;
|
||||||
let value = match token {
|
let value = match token {
|
||||||
Token::Bool => Value::Bool(
|
Token::Bool => Value::Bool(
|
||||||
self.lexer
|
self.lexer
|
||||||
.slice()
|
.slice()
|
||||||
.to_ascii_lowercase()
|
.to_ascii_lowercase()
|
||||||
.parse()
|
.parse()
|
||||||
.with_span(self.lexer.span(), self.source)?,
|
.with_span(self.lexer.span())?,
|
||||||
),
|
),
|
||||||
Token::Integer => {
|
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::Null => Value::Null,
|
||||||
Token::Array => Value::Array(self.parse_array(ArraySyntax::Long)?),
|
Token::Array => Value::Array(self.parse_array(ArraySyntax::Long)?),
|
||||||
Token::SquareOpen => Value::Array(self.parse_array(ArraySyntax::Short)?),
|
Token::SquareOpen => Value::Array(self.parse_array(ArraySyntax::Short)?),
|
||||||
|
|
@ -86,14 +86,14 @@ impl<'source> Parser<'source> {
|
||||||
fn parse_array(
|
fn parse_array(
|
||||||
&mut self,
|
&mut self,
|
||||||
syntax: ArraySyntax,
|
syntax: ArraySyntax,
|
||||||
) -> Result<HashMap<Key, Value>, SpannedError<'source, ParseError>> {
|
) -> Result<HashMap<Key, Value>, SpannedError<ParseError>> {
|
||||||
let mut builder = ArrayBuilder::default();
|
let mut builder = ArrayBuilder::default();
|
||||||
|
|
||||||
if syntax == ArraySyntax::Long {
|
if syntax == ArraySyntax::Long {
|
||||||
self.lexer
|
self.lexer
|
||||||
.next()
|
.next()
|
||||||
.expect_token(&[Token::BracketOpen])
|
.expect_token(&[Token::BracketOpen])
|
||||||
.with_span(self.lexer.span(), self.source)?;
|
.with_span(self.lexer.span())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -115,7 +115,7 @@ impl<'source> Parser<'source> {
|
||||||
.lexer
|
.lexer
|
||||||
.next()
|
.next()
|
||||||
.expect_token(&[syntax.close_bracket(), Token::Comma, Token::Arrow])
|
.expect_token(&[syntax.close_bracket(), Token::Comma, Token::Arrow])
|
||||||
.with_span(self.lexer.span(), self.source)?;
|
.with_span(self.lexer.span())?;
|
||||||
|
|
||||||
match next {
|
match next {
|
||||||
Token::BracketClose => {
|
Token::BracketClose => {
|
||||||
|
|
@ -137,7 +137,7 @@ impl<'source> Parser<'source> {
|
||||||
Value::String(str) => Key::String(str),
|
Value::String(str) => Key::String(str),
|
||||||
value => {
|
value => {
|
||||||
let err = ParseError::InvalidArrayKey(InvalidArrayKeyError(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);
|
return Err(span_err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -147,7 +147,7 @@ impl<'source> Parser<'source> {
|
||||||
.lexer
|
.lexer
|
||||||
.next()
|
.next()
|
||||||
.expect_token(&[syntax.close_bracket(), Token::Comma])
|
.expect_token(&[syntax.close_bracket(), Token::Comma])
|
||||||
.with_span(self.lexer.span(), self.source)?
|
.with_span(self.lexer.span())?
|
||||||
{
|
{
|
||||||
Token::BracketClose => {
|
Token::BracketClose => {
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue