@@ -291,6 +291,16 @@ impl<T: Text + Send> Lexer<T> {
291291 } ) ;
292292 Waiting
293293 }
294+ 'c' if self . characters . peek ( ) . is ( '\'' ) => {
295+ // C `char` literal
296+ self . state = State :: String ( StringState {
297+ value : String :: new ( ) ,
298+ closing_char : self . characters . next ( ) . unwrap ( ) . 0 ,
299+ modifier : StringModifier :: CharLiteral ,
300+ start_source : source,
301+ } ) ;
302+ Waiting
303+ }
294304 _ if c. is_alphabetic ( ) || c == '_' => {
295305 self . state = State :: Identifier ( IdentifierState {
296306 identifier : String :: from ( c) ,
@@ -355,40 +365,46 @@ impl<T: Text + Send> Lexer<T> {
355365
356366 let state = self . state . as_mut_string ( ) ;
357367
358- match self . characters . next ( ) {
359- Character :: At ( c, c_source) => {
360- if c == state. closing_char {
361- let value = std:: mem:: take ( & mut state. value ) ;
362- let modifier = state. modifier ;
363- let start_source = state. start_source ;
364- self . state = State :: Idle ;
365-
366- Has ( TokenKind :: String ( StringLiteral { value, modifier } ) . at ( start_source) )
367- } else if c == '\\' {
368- if let Character :: At ( next_c, _) = self . characters . next ( ) {
369- match next_c {
370- 'n' => state. value . push ( '\n' ) ,
371- 'r' => state. value . push ( '\r' ) ,
372- 't' => state. value . push ( '\t' ) ,
373- _ => state. value . push ( next_c) ,
374- }
375-
376- Waiting
377- } else {
378- Has (
379- TokenKind :: Error ( "Expected character after string esacpe '\\ '" . into ( ) )
380- . at ( c_source) ,
381- )
382- }
383- } else {
384- state. value . push ( c) ;
385- Waiting
368+ let Character :: At ( c, c_source) = self . characters . next ( ) else {
369+ let message = match state. modifier {
370+ StringModifier :: Normal | StringModifier :: NullTerminated => {
371+ "Unclosed string literal"
386372 }
387- }
388- Character :: End ( _) => {
389- Has ( TokenKind :: Error ( "Unclosed string literal" . into ( ) ) . at ( state. start_source ) )
390- }
373+ StringModifier :: CharLiteral => "Unclosed character literal" ,
374+ } ;
375+
376+ return Has ( TokenKind :: Error ( message. into ( ) ) . at ( state. start_source ) ) ;
377+ } ;
378+
379+ if c == state. closing_char {
380+ let value = std:: mem:: take ( & mut state. value ) ;
381+ let modifier = state. modifier ;
382+ let start_source = state. start_source ;
383+ self . state = State :: Idle ;
384+
385+ return Has ( TokenKind :: String ( StringLiteral { value, modifier } ) . at ( start_source) ) ;
386+ }
387+
388+ if c != '\\' {
389+ state. value . push ( c) ;
390+ return Waiting ;
391391 }
392+
393+ let Character :: At ( next_c, _) = self . characters . next ( ) else {
394+ return Has (
395+ TokenKind :: Error ( "Expected character after escaping '\\ '" . into ( ) ) . at ( c_source) ,
396+ ) ;
397+ } ;
398+
399+ match next_c {
400+ 'n' => state. value . push ( '\n' ) ,
401+ 'r' => state. value . push ( '\r' ) ,
402+ 't' => state. value . push ( '\t' ) ,
403+ '"' | '\'' => state. value . push ( next_c) ,
404+ _ => return Has ( TokenKind :: Error ( "Unrecognized escape sequence" . into ( ) ) . at ( c_source) ) ,
405+ }
406+
407+ Waiting
392408 }
393409
394410 fn feed_number ( & mut self ) -> FeedResult < Token > {
0 commit comments