@@ -20,6 +20,7 @@ pub enum LexicalErrorType {
20
20
StringError ,
21
21
UnicodeError ,
22
22
NestingError ,
23
+ IndentationError ,
23
24
TabError ,
24
25
DefaultArgumentError ,
25
26
PositionalArgumentError ,
@@ -36,6 +37,9 @@ impl fmt::Display for LexicalErrorType {
36
37
LexicalErrorType :: FStringError ( error) => write ! ( f, "Got error in f-string: {}" , error) ,
37
38
LexicalErrorType :: UnicodeError => write ! ( f, "Got unexpected unicode" ) ,
38
39
LexicalErrorType :: NestingError => write ! ( f, "Got unexpected nesting" ) ,
40
+ LexicalErrorType :: IndentationError => {
41
+ write ! ( f, "unindent does not match any outer indentation level" )
42
+ }
39
43
LexicalErrorType :: TabError => {
40
44
write ! ( f, "inconsistent use of tabs and spaces in indentation" )
41
45
}
@@ -121,7 +125,7 @@ pub enum ParseErrorType {
121
125
/// Parser encountered an invalid token
122
126
InvalidToken ,
123
127
/// Parser encountered an unexpected token
124
- UnrecognizedToken ( Tok , Vec < String > ) ,
128
+ UnrecognizedToken ( Tok , Option < String > ) ,
125
129
/// Maps to `User` type from `lalrpop-util`
126
130
Lexical ( LexicalErrorType ) ,
127
131
}
@@ -143,10 +147,19 @@ impl From<LalrpopError<Location, Tok, LexicalError>> for ParseError {
143
147
error : ParseErrorType :: Lexical ( error. error ) ,
144
148
location : error. location ,
145
149
} ,
146
- LalrpopError :: UnrecognizedToken { token, expected } => ParseError {
147
- error : ParseErrorType :: UnrecognizedToken ( token. 1 , expected) ,
148
- location : token. 0 ,
149
- } ,
150
+ LalrpopError :: UnrecognizedToken { token, expected } => {
151
+ // Hacky, but it's how CPython does it. See PyParser_AddToken,
152
+ // in particular "Only one possible expected token" comment.
153
+ let expected = if expected. len ( ) == 1 {
154
+ Some ( expected[ 0 ] . clone ( ) )
155
+ } else {
156
+ None
157
+ } ;
158
+ ParseError {
159
+ error : ParseErrorType :: UnrecognizedToken ( token. 1 , expected) ,
160
+ location : token. 0 ,
161
+ }
162
+ }
150
163
LalrpopError :: UnrecognizedEOF { location, .. } => ParseError {
151
164
error : ParseErrorType :: EOF ,
152
165
location,
@@ -167,8 +180,14 @@ impl fmt::Display for ParseErrorType {
167
180
ParseErrorType :: EOF => write ! ( f, "Got unexpected EOF" ) ,
168
181
ParseErrorType :: ExtraToken ( ref tok) => write ! ( f, "Got extraneous token: {:?}" , tok) ,
169
182
ParseErrorType :: InvalidToken => write ! ( f, "Got invalid token" ) ,
170
- ParseErrorType :: UnrecognizedToken ( ref tok, _) => {
171
- write ! ( f, "Got unexpected token {}" , tok)
183
+ ParseErrorType :: UnrecognizedToken ( ref tok, ref expected) => {
184
+ if * tok == Tok :: Indent {
185
+ write ! ( f, "unexpected indent" )
186
+ } else if expected. clone ( ) == Some ( "Indent" . to_string ( ) ) {
187
+ write ! ( f, "expected an indented block" )
188
+ } else {
189
+ write ! ( f, "Got unexpected token {}" , tok)
190
+ }
172
191
}
173
192
ParseErrorType :: Lexical ( ref error) => write ! ( f, "{}" , error) ,
174
193
}
0 commit comments