@@ -57,9 +57,10 @@ extension Lexer.Cursor {
57
57
58
58
/// A narrow mode that's used for 'try?' and 'try!' to ensure we prefer to
59
59
/// lex a regex literal rather than a binary operator. This is needed as the
60
- /// last token will be a postfix operator, which would normally indicate a
61
- /// binary operator is expected next, but in this case we know it must be an
62
- /// expression. See the comment in `tryScanOperatorAsRegexLiteral` for more info.
60
+ /// `previousTokenKind` will be `.postfixOperator`, which would normally
61
+ /// indicate a binary operator is expected next, but in this case we know it
62
+ /// must be an expression. See the comment in
63
+ /// `tryScanOperatorAsRegexLiteral` for more info.
63
64
/// NOTE: This is a complete hack, do not add new uses of this.
64
65
case preferRegexOverBinaryOperator
65
66
@@ -93,7 +94,8 @@ extension Lexer.Cursor {
93
94
case inStringInterpolation( stringLiteralKind: StringLiteralKind , parenCount: Int )
94
95
95
96
/// We have encountered a regex literal, and have its tokens to work
96
- /// through.
97
+ /// through. `lexemes` is a pointer to the lexemes allocated in the state
98
+ /// stack bump pointer allocator.
97
99
case inRegexLiteral( index: UInt8 , lexemes: UnsafePointer < RegexLiteralLexemes > )
98
100
99
101
/// The mode in which leading trivia should be lexed for this state or `nil`
@@ -212,6 +214,7 @@ extension Lexer.Cursor {
212
214
self . kind = kind
213
215
self . position = position
214
216
}
217
+
215
218
init ( _ kind: TokenDiagnostic . Kind , position: Lexer . Cursor ) {
216
219
self . init ( kind, position: position. position)
217
220
}
@@ -239,6 +242,9 @@ extension Lexer {
239
242
240
243
/// If we have already lexed a token, the kind of the previously lexed token
241
244
var previousTokenKind : RawTokenKind ?
245
+
246
+ /// If the `previousTokenKind` is `.keyword`, the keyword kind. Otherwise
247
+ /// `nil`.
242
248
var previousKeyword : Keyword ?
243
249
244
250
private var stateStack : StateStack = StateStack ( )
@@ -309,18 +315,56 @@ extension Lexer {
309
315
/// for this lexeme.
310
316
let trailingTriviaLexingMode : Lexer . Cursor . TriviaLexingMode ?
311
317
312
- init (
318
+ /// If `tokenKind` is `.keyword`, the kind of keyword produced, otherwise
319
+ /// `nil`.
320
+ let keywordKind : Keyword ?
321
+
322
+ private init (
313
323
_ tokenKind: RawTokenKind ,
314
- flags: Lexer . Lexeme . Flags = [ ] ,
315
- error: Cursor . LexingDiagnostic ? = nil ,
316
- stateTransition: StateTransition ? = nil ,
317
- trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? = nil
324
+ flags: Lexer . Lexeme . Flags ,
325
+ error: Cursor . LexingDiagnostic ? ,
326
+ stateTransition: StateTransition ? ,
327
+ trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? ,
328
+ keywordKind: Keyword ?
318
329
) {
319
330
self . tokenKind = tokenKind
320
331
self . flags = flags
321
332
self . error = error
322
333
self . stateTransition = stateTransition
323
334
self . trailingTriviaLexingMode = trailingTriviaLexingMode
335
+ self . keywordKind = keywordKind
336
+ }
337
+
338
+ /// Create a lexer result. Note that keywords should use `Result.keyword`
339
+ /// instead.
340
+ init (
341
+ _ tokenKind: RawTokenKind ,
342
+ flags: Lexer . Lexeme . Flags = [ ] ,
343
+ error: Cursor . LexingDiagnostic ? = nil ,
344
+ stateTransition: StateTransition ? = nil ,
345
+ trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? = nil
346
+ ) {
347
+ precondition ( tokenKind != . keyword, " Use Result.keyword instead " )
348
+ self . init (
349
+ tokenKind,
350
+ flags: flags,
351
+ error: error,
352
+ stateTransition: stateTransition,
353
+ trailingTriviaLexingMode: trailingTriviaLexingMode,
354
+ keywordKind: nil
355
+ )
356
+ }
357
+
358
+ /// Produce a lexer result for a given keyword.
359
+ static func keyword( _ kind: Keyword ) -> Self {
360
+ Self (
361
+ . keyword,
362
+ flags: [ ] ,
363
+ error: nil ,
364
+ stateTransition: nil ,
365
+ trailingTriviaLexingMode: nil ,
366
+ keywordKind: kind
367
+ )
324
368
}
325
369
}
326
370
}
@@ -366,7 +410,7 @@ extension Lexer.Cursor {
366
410
let result : Lexer . Result
367
411
switch currentState {
368
412
case . normal:
369
- result = lexNormal ( sourceBufferStart: sourceBufferStart)
413
+ result = lexNormal ( sourceBufferStart: sourceBufferStart, preferRegexOverBinaryOperator : false )
370
414
case . preferRegexOverBinaryOperator:
371
415
// In this state we lex a single token with the flag set, and then pop the state.
372
416
result = lexNormal ( sourceBufferStart: sourceBufferStart, preferRegexOverBinaryOperator: true )
@@ -420,7 +464,7 @@ extension Lexer.Cursor {
420
464
cursor: cursor
421
465
)
422
466
self . previousTokenKind = result. tokenKind
423
- self . previousKeyword = result. tokenKind == . keyword ? Keyword ( lexeme . tokenText ) ! : nil
467
+ self . previousKeyword = result. keywordKind
424
468
425
469
return lexeme
426
470
}
@@ -554,6 +598,7 @@ extension Lexer.Cursor.Position {
554
598
self . input = UnsafeBufferPointer ( rebasing: input)
555
599
return c
556
600
}
601
+
557
602
/// Advance the cursor position by `n` bytes. The offset must be valid.
558
603
func advanced( by n: Int ) -> Self {
559
604
precondition ( n > 0 )
@@ -824,7 +869,7 @@ extension Lexer.Cursor {
824
869
extension Lexer . Cursor {
825
870
private mutating func lexNormal(
826
871
sourceBufferStart: Lexer . Cursor ,
827
- preferRegexOverBinaryOperator: Bool = false
872
+ preferRegexOverBinaryOperator: Bool
828
873
) -> Lexer . Result {
829
874
switch self . peek ( ) {
830
875
case UInt8 ( ascii: " @ " ) : _ = self . advance ( ) ; return Lexer . Result ( . atSign)
@@ -1010,7 +1055,7 @@ extension Lexer.Cursor {
1010
1055
return Lexer . Result ( . stringSegment, stateTransition: . pop)
1011
1056
default :
1012
1057
// If we haven't reached the end of the string interpolation, lex as if we were in a normal expression.
1013
- return self . lexNormal ( sourceBufferStart: sourceBufferStart)
1058
+ return self . lexNormal ( sourceBufferStart: sourceBufferStart, preferRegexOverBinaryOperator : false )
1014
1059
}
1015
1060
}
1016
1061
}
@@ -1916,7 +1961,7 @@ extension Lexer.Cursor {
1916
1961
1917
1962
let text = tokStart. text ( upTo: self )
1918
1963
if let keyword = Keyword ( text) , keyword. isLexerClassified {
1919
- return Lexer . Result ( . keyword)
1964
+ return Lexer . Result. keyword ( keyword)
1920
1965
} else if text == " _ " {
1921
1966
return Lexer . Result ( . wildcard)
1922
1967
} else {
@@ -1977,7 +2022,7 @@ extension Lexer.Cursor {
1977
2022
case UInt8 ( ascii: " ? " ) :
1978
2023
return . postfixQuestionMark
1979
2024
default :
1980
- fatalError ( " Must be at '!' or '?' " )
2025
+ preconditionFailure ( " Must be at '!' or '?' " )
1981
2026
}
1982
2027
} ( )
1983
2028
_ = self . advance ( )
@@ -2006,17 +2051,17 @@ extension Lexer.Cursor {
2006
2051
2007
2052
// Check to see if we have a regex literal starting in the operator.
2008
2053
do {
2009
- var ptr = tokStart
2010
- while ptr . input. baseAddress! < self . input. baseAddress! {
2054
+ var regexScan = tokStart
2055
+ while regexScan . input. baseAddress! < self . input. baseAddress! {
2011
2056
// Scan for the first '/' in the operator to see if it starts a regex
2012
2057
// literal.
2013
- guard ptr . is ( at: " / " ) else {
2014
- _ = ptr . advance ( )
2058
+ guard regexScan . is ( at: " / " ) else {
2059
+ _ = regexScan . advance ( )
2015
2060
continue
2016
2061
}
2017
2062
guard
2018
2063
let result = self . tryLexOperatorAsRegexLiteral (
2019
- at: ptr ,
2064
+ at: regexScan ,
2020
2065
operatorStart: tokStart,
2021
2066
operatorEnd: self ,
2022
2067
sourceBufferStart: sourceBufferStart,
0 commit comments