@@ -19,23 +19,14 @@ struct LoopProgressCondition {
19
19
var currentToken : Lexer . Lexeme ?
20
20
21
21
init ( ) { }
22
- }
23
22
24
- extension TokenConsumer {
25
- /// Check that the token consumer has made progress since `hasProgress` was
26
- /// called the last time with this `loopProgress`.
27
- ///
28
- /// In assert builds, this traps if the loop has not made any parser progress
29
- /// in between two iterations, ie. it checks if the parser's `currentToken`
30
- /// has changed in between two calls to `evaluate`.
31
- /// In non-assert builds, `evaluate()` returns `false` if the loop has not made
32
- /// progress, thus aborting the loop.
33
- func hasProgressed( _ loopProgress: inout LoopProgressCondition ) -> Bool {
23
+ /// Implementation of the above `evaluate` methods.
24
+ fileprivate mutating func evaluate( _ currentToken: Lexer . Lexeme ) -> Bool {
34
25
defer {
35
- loopProgress . currentToken = currentToken
26
+ self . currentToken = currentToken
36
27
}
37
28
38
- guard let previousToken = loopProgress . currentToken else {
29
+ guard let previousToken = self . currentToken else {
39
30
return true
40
31
}
41
32
// The loop has made progress if either
@@ -50,3 +41,36 @@ extension TokenConsumer {
50
41
return hasMadeProgress
51
42
}
52
43
}
44
+
45
+ // Implementing the extension separately on `Parser` and `Parser.Lookahead` is
46
+ // ~1.5% faster than implementing it on `TokenConsumer`.
47
+
48
+ extension Parser {
49
+ /// Check that the token consumer has made progress since `hasProgress` was
50
+ /// called the last time with this `loopProgress`.
51
+ ///
52
+ /// In assert builds, this traps if the loop has not made any parser progress
53
+ /// in between two iterations, ie. it checks if the parser's `currentToken`
54
+ /// has changed in between two calls to `evaluate`.
55
+ /// In non-assert builds, `evaluate()` returns `false` if the loop has not made
56
+ /// progress, thus aborting the loop.
57
+ @inline ( __always)
58
+ func hasProgressed( _ loopProgress: inout LoopProgressCondition ) -> Bool {
59
+ return loopProgress. evaluate ( self . currentToken)
60
+ }
61
+ }
62
+
63
+ extension Parser . Lookahead {
64
+ /// Check that the token consumer has made progress since `hasProgress` was
65
+ /// called the last time with this `loopProgress`.
66
+ ///
67
+ /// In assert builds, this traps if the loop has not made any parser progress
68
+ /// in between two iterations, ie. it checks if the parser's `currentToken`
69
+ /// has changed in between two calls to `evaluate`.
70
+ /// In non-assert builds, `evaluate()` returns `false` if the loop has not made
71
+ /// progress, thus aborting the loop.
72
+ @inline ( __always)
73
+ func hasProgressed( _ loopProgress: inout LoopProgressCondition ) -> Bool {
74
+ return loopProgress. evaluate ( self . currentToken)
75
+ }
76
+ }
0 commit comments