@@ -175,6 +175,8 @@ pub struct Lexer<T: Iterator<Item = char>> {
175
175
pending : Vec < Spanned > ,
176
176
// The current location.
177
177
location : TextSize ,
178
+ // The last emitted token.
179
+ last_emitted : Option < Tok > ,
178
180
// Lexer mode.
179
181
mode : Mode ,
180
182
}
@@ -233,6 +235,7 @@ where
233
235
pending : Vec :: with_capacity ( 5 ) ,
234
236
location : start,
235
237
window : CharWindow :: new ( input) ,
238
+ last_emitted : None ,
236
239
mode,
237
240
} ;
238
241
// Fill the window.
@@ -945,15 +948,22 @@ where
945
948
}
946
949
}
947
950
'%' => {
948
- let tok_start = self . get_pos ( ) ;
949
- self . next_char ( ) ;
950
- if let Some ( '=' ) = self . window [ 0 ] {
951
- self . next_char ( ) ;
952
- let tok_end = self . get_pos ( ) ;
953
- self . emit ( ( Tok :: PercentEqual , TextRange :: new ( tok_start, tok_end) ) ) ;
951
+ if self . mode == Mode :: Jupyter
952
+ && self . nesting == 0
953
+ && matches ! ( self . last_emitted, Some ( Tok :: Equal ) )
954
+ {
955
+ self . lex_and_emit_magic_command ( ) ;
954
956
} else {
955
- let tok_end = self . get_pos ( ) ;
956
- self . emit ( ( Tok :: Percent , TextRange :: new ( tok_start, tok_end) ) ) ;
957
+ let tok_start = self . get_pos ( ) ;
958
+ self . next_char ( ) ;
959
+ if let Some ( '=' ) = self . window [ 0 ] {
960
+ self . next_char ( ) ;
961
+ let tok_end = self . get_pos ( ) ;
962
+ self . emit ( ( Tok :: PercentEqual , TextRange :: new ( tok_start, tok_end) ) ) ;
963
+ } else {
964
+ let tok_end = self . get_pos ( ) ;
965
+ self . emit ( ( Tok :: Percent , TextRange :: new ( tok_start, tok_end) ) ) ;
966
+ }
957
967
}
958
968
}
959
969
'|' => {
@@ -1025,17 +1035,24 @@ where
1025
1035
}
1026
1036
}
1027
1037
'!' => {
1028
- let tok_start = self . get_pos ( ) ;
1029
- self . next_char ( ) ;
1030
- if let Some ( '=' ) = self . window [ 0 ] {
1031
- self . next_char ( ) ;
1032
- let tok_end = self . get_pos ( ) ;
1033
- self . emit ( ( Tok :: NotEqual , TextRange :: new ( tok_start, tok_end) ) ) ;
1038
+ if self . mode == Mode :: Jupyter
1039
+ && self . nesting == 0
1040
+ && matches ! ( self . last_emitted, Some ( Tok :: Equal ) )
1041
+ {
1042
+ self . lex_and_emit_magic_command ( ) ;
1034
1043
} else {
1035
- return Err ( LexicalError {
1036
- error : LexicalErrorType :: UnrecognizedToken { tok : '!' } ,
1037
- location : tok_start,
1038
- } ) ;
1044
+ let tok_start = self . get_pos ( ) ;
1045
+ self . next_char ( ) ;
1046
+ if let Some ( '=' ) = self . window [ 0 ] {
1047
+ self . next_char ( ) ;
1048
+ let tok_end = self . get_pos ( ) ;
1049
+ self . emit ( ( Tok :: NotEqual , TextRange :: new ( tok_start, tok_end) ) ) ;
1050
+ } else {
1051
+ return Err ( LexicalError {
1052
+ error : LexicalErrorType :: UnrecognizedToken { tok : '!' } ,
1053
+ location : tok_start,
1054
+ } ) ;
1055
+ }
1039
1056
}
1040
1057
}
1041
1058
'~' => {
@@ -1292,6 +1309,7 @@ where
1292
1309
1293
1310
// Helper function to emit a lexed token to the queue of tokens.
1294
1311
fn emit ( & mut self , spanned : Spanned ) {
1312
+ self . last_emitted = Some ( spanned. 0 . clone ( ) ) ;
1295
1313
self . pending . push ( spanned) ;
1296
1314
}
1297
1315
}
0 commit comments