Skip to content

Commit d284710

Browse files
committed
Sink a few functions from Parser down to TokenConsumer
1 parent f94cb2a commit d284710

File tree

3 files changed

+91
-99
lines changed

3 files changed

+91
-99
lines changed

Sources/SwiftParser/Parser.swift

Lines changed: 39 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -153,33 +153,12 @@ public struct Parser: TokenConsumer {
153153
self.lexemes = Lexer.tokenize(sourceBuffer)
154154
self.currentToken = self.lexemes.advance()
155155
}
156-
}
157-
158-
// MARK: Inspecting Tokens
159-
160-
extension Parser {
161-
/// Retrieves the token following the current token without consuming it.
162-
@_spi(RawSyntax)
163-
public func peek() -> Lexer.Lexeme {
164-
return self.lexemes.peek()
165-
}
166-
}
167-
168-
// MARK: Consuming Tokens
169-
170-
extension Parser {
171-
/// After calling `consume(ifAnyFrom:)` we know which token we are positioned
172-
/// at based on that function's return type. This handle allows consuming that
173-
/// token.
174-
struct TokenConsumptionHandle {
175-
/// The kind that is expected to be consumed if the handle is eaten.
176-
var tokenKind: RawTokenKind
177-
}
178156

179157
@_spi(RawSyntax)
180158
public mutating func missingToken(_ kind: RawTokenKind) -> RawTokenSyntax {
181159
return RawTokenSyntax(missing: kind, arena: arena)
182160
}
161+
183162
/// Consumes the current token and advances the lexer to the next token.
184163
///
185164
/// - Returns: The token that was consumed.
@@ -195,7 +174,21 @@ extension Parser {
195174
arena: arena
196175
)
197176
}
177+
}
178+
179+
// MARK: Inspecting Tokens
198180

181+
extension Parser {
182+
/// Retrieves the token following the current token without consuming it.
183+
@_spi(RawSyntax)
184+
public func peek() -> Lexer.Lexeme {
185+
return self.lexemes.peek()
186+
}
187+
}
188+
189+
// MARK: Consuming Tokens
190+
191+
extension Parser {
199192
/// Consumes the current token and sets its kind to the given `TokenKind`,
200193
/// then advances the lexer to the next token.
201194
///
@@ -208,6 +201,11 @@ extension Parser {
208201
return self.consumeAnyToken()
209202
}
210203

204+
}
205+
206+
// MARK: Consuming Tokens with Lookahead
207+
208+
extension Parser {
211209
/// If the current token has `kind1` and is followed by `kind2` consume both tokens and return them.
212210
/// Otherwise, return `nil`.
213211
@_spi(RawSyntax)
@@ -233,54 +231,31 @@ extension Parser {
233231
return nil
234232
}
235233
}
234+
}
236235

237-
/// Examines the current token and consumes it if its kind matches the
238-
/// given `TokenKind` and additionally satisfies `condition`. If a token was
239-
/// consumed, the result is that token, else the result is `nil`.
236+
// MARK: Expecting Tokens
237+
238+
extension Parser {
239+
/// Attempts to consume a token of the given kind, synthesizing a missing
240+
/// token if the current token's kind does not match.
241+
///
242+
/// This method does not try to eat unexpected until it finds the token of the specified `kind`.
243+
/// In general, `expect` or `expectAny` should be preferred.
240244
///
241245
/// - Parameter kind: The kind of token to consume.
242-
/// - Returns: A token of the given kind if one was consumed, else `nil`.
246+
/// - Returns: A token of the given kind.
243247
@_spi(RawSyntax)
244-
public mutating func consume(
245-
if kind: RawTokenKind,
246-
where condition: (Lexer.Lexeme, Self) -> Bool
247-
) -> Token? {
248-
guard self.at(kind) && condition(self.currentToken, self) else {
249-
return nil
250-
}
251-
return self.consumeAnyToken()
252-
}
253-
254-
/// Examines the current token and consumes it if its kind is in `kinds` and
255-
/// additionally satisfies `condition`. If a token was consumed, the result is
256-
/// that token, else the result is `nil`.
257-
///
258-
/// - Parameter kind: The kinds of token to consume.
259-
/// - Returns: A token of the given kind if one was consumed, else `nil`.
260-
public mutating func consume(ifAny kinds: RawTokenKind..., where condition: (Lexer.Lexeme, Parser) -> Bool) -> Token? {
261-
for kind in kinds {
262-
if let consumed = self.consume(if: kind, where: condition) {
263-
return consumed
264-
}
265-
}
266-
return nil
267-
}
268-
269-
/// Checks whether the parser is currently positioned at any token in `Subset`.
270-
/// If this is the case, return the `Subset` case that the parser is positioned in
271-
/// as well as a handle to consume that token.
272-
func at<Subset: RawTokenKindSubset>(anyIn subset: Subset.Type) -> (Subset, TokenConsumptionHandle)? {
273-
for kind in Subset.allCases {
274-
if self.at(kind.rawTokenKind) && kind.accepts(lexeme: currentToken, parser: self) {
275-
return (kind, TokenConsumptionHandle(tokenKind: kind.rawTokenKind))
248+
public mutating func expectWithoutLookahead(_ kind: RawTokenKind, _ text: SyntaxText? = nil) -> RawTokenSyntax {
249+
if self.currentToken.tokenKind == kind {
250+
if let text = text {
251+
if self.currentToken.tokenText == text {
252+
return self.consumeAnyToken()
253+
}
254+
} else {
255+
return self.consumeAnyToken()
276256
}
277257
}
278-
return nil
279-
}
280-
281-
/// Eat a token that we know we are currently positioned at, based on `at(anyIn:)`.
282-
mutating func eat(_ handle: TokenConsumptionHandle) -> RawTokenSyntax {
283-
return consume(if: handle.tokenKind)!
258+
return RawTokenSyntax(missing: kind, arena: self.arena)
284259
}
285260

286261
/// Attempts to consume a token of the given kind.
@@ -335,28 +310,6 @@ extension Parser {
335310
}
336311
return (nil, RawTokenSyntax(missing: defaultKind, arena: self.arena))
337312
}
338-
339-
/// Attempts to consume a token of the given kind, synthesizing a missing
340-
/// token if the current token's kind does not match.
341-
///
342-
/// This method does not try to eat unexpected until it finds the token of the specified `kind`.
343-
/// In general, `expect` or `expectAny` should be preferred.
344-
///
345-
/// - Parameter kind: The kind of token to consume.
346-
/// - Returns: A token of the given kind.
347-
@_spi(RawSyntax)
348-
public mutating func expectWithoutLookahead(_ kind: RawTokenKind, _ text: SyntaxText? = nil) -> RawTokenSyntax {
349-
if self.currentToken.tokenKind == kind {
350-
if let text = text {
351-
if self.currentToken.tokenText == text {
352-
return self.consumeAnyToken()
353-
}
354-
} else {
355-
return self.consumeAnyToken()
356-
}
357-
}
358-
return RawTokenSyntax(missing: kind, arena: self.arena)
359-
}
360313
}
361314

362315
// MARK: Spliting Tokens

Sources/SwiftParser/RawTokenKindSubset.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@
1515
/// Allows callers of `at(anyOf:)` to expect being positioned at a subset of all
1616
/// `RawTokenKind`s.
1717
protocol RawTokenKindSubset: CaseIterable {
18+
associatedtype ParserType = Parser
19+
1820
var rawTokenKind: RawTokenKind { get }
1921

2022
/// Allows more flexible rejection of further token kinds based on the token's
2123
/// contents or lookahead. Useful to e.g. look for contextual keywords.
22-
func accepts(lexeme: Lexer.Lexeme, parser: Parser) -> Bool
24+
func accepts(lexeme: Lexer.Lexeme, parser: ParserType) -> Bool
2325
}
2426

2527
extension RawTokenKindSubset {
26-
func accepts(lexeme: Lexer.Lexeme, parser: Parser) -> Bool {
28+
func accepts(lexeme: Lexer.Lexeme, parser: ParserType) -> Bool {
2729
return true
2830
}
2931
}

Sources/SwiftParser/TokenConsumer.swift

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public protocol TokenConsumer {
2323
mutating func missingToken(_ kind: RawTokenKind) -> Token
2424
}
2525

26-
// MARK: Consuming Tokens
26+
// MARK: Checking if we are at one specific token
2727

2828
extension TokenConsumer {
2929
/// Returns whether the kind of the current token matches the given
@@ -44,27 +44,64 @@ extension TokenConsumer {
4444
return kind.contains(self.currentToken.tokenKind)
4545
}
4646

47+
/// Checks whether the parser is currently positioned at any token in `Subset`.
48+
/// If this is the case, return the `Subset` case that the parser is positioned in
49+
/// as well as a handle to consume that token.
50+
func at<Subset: RawTokenKindSubset>(anyIn subset: Subset.Type) -> (Subset, TokenConsumptionHandle)? where Subset.ParserType == Self {
51+
for kind in Subset.allCases {
52+
if self.at(kind.rawTokenKind) && kind.accepts(lexeme: currentToken, parser: self) {
53+
return (kind, TokenConsumptionHandle(tokenKind: kind.rawTokenKind))
54+
}
55+
}
56+
return nil
57+
}
58+
59+
/// Eat a token that we know we are currently positioned at, based on `at(anyIn:)`.
60+
mutating func eat(_ handle: TokenConsumptionHandle) -> Token {
61+
return consume(if: handle.tokenKind)!
62+
}
63+
}
64+
65+
// MARK: Consuming tokens
66+
67+
/// After calling `consume(ifAnyFrom:)` we know which token we are positioned
68+
/// at based on that function's return type. This handle allows consuming that
69+
/// token.
70+
struct TokenConsumptionHandle {
71+
/// The kind that is expected to be consumed if the handle is eaten.
72+
var tokenKind: RawTokenKind
73+
}
74+
75+
extension TokenConsumer {
4776
/// Examines the current token and consumes it if its kind matches the
48-
/// given `TokenKind`. If a token was consumed, the result is that token, else
49-
/// the result is `nil`.
77+
/// given `TokenKind` and additionally satisfies `condition`. If a token was
78+
/// consumed, the result is that token, else the result is `nil`.
5079
///
5180
/// - Parameter kind: The kind of token to consume.
5281
/// - Returns: A token of the given kind if one was consumed, else `nil`.
53-
public mutating func consume(if kind: RawTokenKind) -> Token? {
54-
guard self.at(kind) else {
55-
return nil
82+
@_spi(RawSyntax)
83+
public mutating func consume(
84+
if kind: RawTokenKind,
85+
where condition: (Lexer.Lexeme, Self) -> Bool = { (_, _) in true}
86+
) -> Token? {
87+
if self.at(kind) && condition(self.currentToken, self) {
88+
return self.consumeAnyToken()
5689
}
57-
return self.consumeAnyToken()
90+
return nil
5891
}
5992

60-
/// Examines the current token and consumes it if its kind is in `kinds`. If a
61-
/// token was consumed, the result is that token, else the result is `nil`.
93+
/// Examines the current token and consumes it if its kind is in `kinds` and
94+
/// additionally satisfies `condition`. If a token was consumed, the result is
95+
/// that token, else the result is `nil`.
6296
///
6397
/// - Parameter kind: The kinds of token to consume.
6498
/// - Returns: A token of the given kind if one was consumed, else `nil`.
65-
public mutating func consume(ifAny kinds: RawTokenKind...) -> Token? {
99+
public mutating func consume(
100+
ifAny kinds: RawTokenKind...,
101+
where condition: (Lexer.Lexeme, Self) -> Bool = { (_, _) in true }
102+
) -> Token? {
66103
for kind in kinds {
67-
if let consumed = self.consume(if: kind) {
104+
if let consumed = self.consume(if: kind, where: condition) {
68105
return consumed
69106
}
70107
}

0 commit comments

Comments
 (0)