Skip to content

Commit 1fd898c

Browse files
committed
new_syntax_error working without full compiler
Fix #4100
1 parent 42b95a9 commit 1fd898c

4 files changed

Lines changed: 58 additions & 74 deletions

File tree

‎core/src/error.rs‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::fmt::Display;
2-
31
use crate::Location;
2+
use std::fmt::Display;
43

54
#[derive(Debug, PartialEq, Eq)]
65
pub struct BaseError<T> {
@@ -87,3 +86,24 @@ where
8786
}
8887
}
8988
}
89+
90+
impl<T> CompileError<T> {
91+
pub fn from<U>(error: BaseError<U>, source: &str) -> Self
92+
where
93+
T: From<U>,
94+
{
95+
let statement = get_statement(source, error.location);
96+
CompileError {
97+
body: error.into(),
98+
statement,
99+
}
100+
}
101+
}
102+
103+
fn get_statement(source: &str, loc: Location) -> Option<String> {
104+
if loc.column() == 0 || loc.row() == 0 {
105+
return None;
106+
}
107+
let line = source.split('\n').nth(loc.row() - 1)?.to_owned();
108+
Some(line + "\n")
109+
}

‎parser/src/error.rs‎

Lines changed: 33 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ impl From<FStringError> for LalrpopError<Location, Tok, LexicalError> {
117117
}
118118

119119
/// Represents an error during parsing
120-
#[derive(Debug, PartialEq)]
121-
pub struct ParseError(rustpython_compiler_core::BaseError<ParseErrorType>);
120+
pub type ParseError = rustpython_compiler_core::BaseError<ParseErrorType>;
122121

123122
#[derive(Debug, PartialEq)]
124123
pub enum ParseErrorType {
@@ -134,66 +133,44 @@ pub enum ParseErrorType {
134133
Lexical(LexicalErrorType),
135134
}
136135

137-
impl From<ParseError> for rustpython_compiler_core::BaseError<ParseErrorType> {
138-
fn from(err: ParseError) -> Self {
139-
err.0
140-
}
141-
}
142-
143-
impl From<ParseError> for ParseErrorType {
144-
fn from(err: ParseError) -> Self {
145-
err.0.error
146-
}
147-
}
148-
149136
/// Convert `lalrpop_util::ParseError` to our internal type
150-
impl ParseError {
151-
fn new(error: ParseErrorType, location: Location, source_path: String) -> Self {
152-
Self(rustpython_compiler_core::BaseError {
153-
error,
137+
pub(crate) fn parse_error_from_lalrpop(
138+
err: LalrpopError<Location, Tok, LexicalError>,
139+
source_path: &str,
140+
) -> ParseError {
141+
let source_path = source_path.to_owned();
142+
match err {
143+
// TODO: Are there cases where this isn't an EOF?
144+
LalrpopError::InvalidToken { location } => ParseError {
145+
error: ParseErrorType::Eof,
154146
location,
155147
source_path,
156-
})
157-
}
158-
159-
pub(crate) fn from_lalrpop(
160-
err: LalrpopError<Location, Tok, LexicalError>,
161-
source_path: &str,
162-
) -> Self {
163-
let source_path = source_path.to_owned();
164-
match err {
165-
// TODO: Are there cases where this isn't an EOF?
166-
LalrpopError::InvalidToken { location } => {
167-
ParseError::new(ParseErrorType::Eof, location, source_path)
168-
}
169-
LalrpopError::ExtraToken { token } => {
170-
ParseError::new(ParseErrorType::ExtraToken(token.1), token.0, source_path)
171-
}
172-
LalrpopError::User { error } => ParseError::new(
173-
ParseErrorType::Lexical(error.error),
174-
error.location,
148+
},
149+
LalrpopError::ExtraToken { token } => ParseError {
150+
error: ParseErrorType::ExtraToken(token.1),
151+
location: token.0,
152+
source_path,
153+
},
154+
LalrpopError::User { error } => ParseError {
155+
error: ParseErrorType::Lexical(error.error),
156+
location: error.location,
157+
source_path,
158+
},
159+
LalrpopError::UnrecognizedToken { token, expected } => {
160+
// Hacky, but it's how CPython does it. See PyParser_AddToken,
161+
// in particular "Only one possible expected token" comment.
162+
let expected = (expected.len() == 1).then(|| expected[0].clone());
163+
ParseError {
164+
error: ParseErrorType::UnrecognizedToken(token.1, expected),
165+
location: token.0,
175166
source_path,
176-
),
177-
LalrpopError::UnrecognizedToken { token, expected } => {
178-
// Hacky, but it's how CPython does it. See PyParser_AddToken,
179-
// in particular "Only one possible expected token" comment.
180-
let expected = (expected.len() == 1).then(|| expected[0].clone());
181-
ParseError::new(
182-
ParseErrorType::UnrecognizedToken(token.1, expected),
183-
token.0,
184-
source_path,
185-
)
186-
}
187-
LalrpopError::UnrecognizedEOF { location, .. } => {
188-
ParseError::new(ParseErrorType::Eof, location, source_path)
189167
}
190168
}
191-
}
192-
}
193-
194-
impl fmt::Display for ParseError {
195-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196-
self.0.fmt(f)
169+
LalrpopError::UnrecognizedEOF { location, .. } => ParseError {
170+
error: ParseErrorType::Eof,
171+
location,
172+
source_path,
173+
},
197174
}
198175
}
199176

@@ -237,16 +214,3 @@ impl ParseErrorType {
237214
)
238215
}
239216
}
240-
241-
impl std::ops::Deref for ParseError {
242-
type Target = rustpython_compiler_core::BaseError<ParseErrorType>;
243-
fn deref(&self) -> &Self::Target {
244-
&self.0
245-
}
246-
}
247-
248-
impl Error for ParseError {
249-
fn source(&self) -> Option<&(dyn Error + 'static)> {
250-
None
251-
}
252-
}

‎parser/src/fstring.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ impl<'a> FStringParser<'a> {
186186
vec![self.expr(ExprKind::FormattedValue {
187187
value: Box::new(
188188
parse_fstring_expr(&expression)
189-
.map_err(|e| InvalidExpression(Box::new(e.into())))?,
189+
.map_err(|e| InvalidExpression(Box::new(e.error)))?,
190190
),
191191
conversion: conversion as _,
192192
format_spec: spec,
@@ -204,7 +204,7 @@ impl<'a> FStringParser<'a> {
204204
self.expr(ExprKind::FormattedValue {
205205
value: Box::new(
206206
parse_fstring_expr(&expression)
207-
.map_err(|e| InvalidExpression(Box::new(e.into())))?,
207+
.map_err(|e| InvalidExpression(Box::new(e.error)))?,
208208
),
209209
conversion: (if conversion == ConversionFlag::None && spec.is_none()
210210
{

‎parser/src/parser.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub fn parse(source: &str, mode: Mode, source_path: &str) -> Result<ast::Mod, Pa
7474

7575
python::TopParser::new()
7676
.parse(tokenizer)
77-
.map_err(|e| ParseError::from_lalrpop(e, source_path))
77+
.map_err(|e| crate::error::parse_error_from_lalrpop(e, source_path))
7878
}
7979

8080
#[cfg(test)]

0 commit comments

Comments
 (0)