@@ -101,6 +101,10 @@ public struct Parser {
101101 /// When this nesting level is exceeded, the parser should stop parsing.
102102 let maximumNestingLevel : Int
103103
104+ let parseLookup : IncrementalParseLookup ?
105+
106+ let parseNodeAffectRange : IncrementalParseNodeAffectRangeCollector ?
107+
104108 /// A default maximum nesting level that is used if the client didn't
105109 /// explicitly specify one. Debug builds of the parser comume a lot more stack
106110 /// space and thus have a lower default maximum nesting level.
@@ -111,7 +115,12 @@ public struct Parser {
111115 #endif
112116
113117 /// Initializes a ``Parser`` from the given string.
114- public init ( _ input: String , maximumNestingLevel: Int ? = nil ) {
118+ public init (
119+ _ input: String ,
120+ maximumNestingLevel: Int ? = nil ,
121+ parseNodeAffectRange: IncrementalParseNodeAffectRangeCollector ? = nil ,
122+ parseTransition: IncrementalParseTransition ? = nil
123+ ) {
115124 self . maximumNestingLevel = maximumNestingLevel ?? Self . defaultMaximumNestingLevel
116125
117126 self . arena = ParsingSyntaxArena (
@@ -126,6 +135,14 @@ public struct Parser {
126135
127136 self . lexemes = Lexer . tokenize ( interned)
128137 self . currentToken = self . lexemes. advance ( )
138+ self . parseNodeAffectRange = parseNodeAffectRange
139+ if let parseTransition,
140+ let parseNodeAffectRange
141+ {
142+ self . parseLookup = IncrementalParseLookup ( transition: parseTransition, nodeAffectRangeCollector: parseNodeAffectRange)
143+ } else {
144+ self . parseLookup = nil
145+ }
129146 }
130147
131148 /// Initializes a ``Parser`` from the given input buffer.
@@ -142,7 +159,13 @@ public struct Parser {
142159 /// arena is created automatically, and `input` copied into the
143160 /// arena. If non-`nil`, `input` must be within its registered
144161 /// source buffer or allocator.
145- public init ( _ input: UnsafeBufferPointer < UInt8 > , maximumNestingLevel: Int ? = nil , arena: ParsingSyntaxArena ? = nil ) {
162+ public init (
163+ _ input: UnsafeBufferPointer < UInt8 > ,
164+ maximumNestingLevel: Int ? = nil ,
165+ parseNodeAffectRange: IncrementalParseNodeAffectRangeCollector ? = nil ,
166+ parseTransition: IncrementalParseTransition ? = nil ,
167+ arena: ParsingSyntaxArena ? = nil
168+ ) {
146169 self . maximumNestingLevel = maximumNestingLevel ?? Self . defaultMaximumNestingLevel
147170
148171 var sourceBuffer : UnsafeBufferPointer < UInt8 >
@@ -159,6 +182,14 @@ public struct Parser {
159182
160183 self . lexemes = Lexer . tokenize ( sourceBuffer)
161184 self . currentToken = self . lexemes. advance ( )
185+ self . parseNodeAffectRange = parseNodeAffectRange
186+ if let parseTransition,
187+ let parseNodeAffectRange
188+ {
189+ self . parseLookup = IncrementalParseLookup ( transition: parseTransition, nodeAffectRangeCollector: parseNodeAffectRange)
190+ } else {
191+ self . parseLookup = nil
192+ }
162193 }
163194
164195 mutating func missingToken( _ kind: RawTokenKind , text: SyntaxText ? = nil ) -> RawTokenSyntax {
@@ -237,6 +268,7 @@ public struct Parser {
237268extension Parser {
238269 /// Retrieves the token following the current token without consuming it.
239270 func peek( ) -> Lexer . Lexeme {
271+ lexemes. recordFurthestOffset ( )
240272 return self . lexemes. peek ( )
241273 }
242274}
@@ -629,3 +661,44 @@ extension Parser {
629661 )
630662 }
631663}
664+
665+ // MARK: Incremental Parsing
666+ extension Parser {
667+ mutating func loadCurrentSyntaxNodeFromCache( for kind: SyntaxKind ) -> Syntax ? {
668+ guard var parseLookup else {
669+ return nil
670+ }
671+
672+ let currentOffset = self . lexemes. getOffsetToStart ( self . currentToken)
673+ if let node = parseLookup. lookUp ( currentOffset, kind: kind) {
674+ self . lexemes. advance ( by: node. byteSize, currentToken: & self . currentToken)
675+ return node
676+ }
677+
678+ return nil
679+ }
680+
681+ func registerNodeForIncrementalParse( node: RawSyntax , startToken: Lexer . Lexeme ) {
682+ guard let parseNodeAffectRange else {
683+ return
684+ }
685+ parseNodeAffectRange. registerNodeForIncrementalParse (
686+ node: node,
687+ length: max ( lookaheadFurthestOffset - self . lexemes. getOffsetToStart ( startToken) , node. byteLength + currentToken. byteLength)
688+ )
689+ }
690+
691+ public var lookaheadFurthestOffset : Int {
692+ return lexemes. lookaheadTracker. pointee. furthestOffset
693+ }
694+ }
695+
696+ /// Record the furthest offset to `sourceBufferStart` that is reached by ``Parser.Peek()`` or ``Lookahead`` in ``Lexer/LexemeSequence``
697+ struct LookaheadTracker {
698+ private( set) var furthestOffset : Int = 0
699+
700+ public mutating func recordFurthestOffset( _ furthestOffset: Int ) {
701+ /// We could lookahead multi-times to find different valid part of a node, so we should take the maximum of the lookahead offset as the possible affect range of a node.
702+ self . furthestOffset = max ( furthestOffset, self . furthestOffset)
703+ }
704+ }
0 commit comments