@@ -2029,6 +2029,80 @@ extension Lexer.Cursor {
2029
2029
return Lexer. Result ( kind, stateTransition: transition)
2030
2030
}
2031
2031
2032
+ /// Classify an operator token given its start and ending cursor.
2033
+ static func class ifyOperatorToken (
2034
+ operStart: Lexer . Cursor,
2035
+ operEnd: Lexer . Cursor,
2036
+ sourceBufferStart: Lexer . Cursor
2037
+ ) - > ( RawTokenKind, error: LexingDiagnostic? ) {
2038
+ // Decide between the binary, prefix, and postfix cases.
2039
+ // It's binary if either both sides are bound or both sides are not bound.
2040
+ // Otherwise, it's postfix if left-bound and prefix if right-bound.
2041
+ let leftBound = operStart. isLeftBound ( sourceBufferStart: sourceBufferStart)
2042
+ let rightBound = operEnd. isRightBound ( isLeftBound: leftBound)
2043
+
2044
+ // Match various reserved words.
2045
+ if operEnd. input. baseAddress! - operStart. input. baseAddress! == 1 {
2046
+ switch operStart. peek ( ) {
2047
+ case UInt8 ( ascii: " = " ) :
2048
+ if leftBound != rightBound {
2049
+ var errorPos = operStart
2050
+
2051
+ if rightBound {
2052
+ _ = errorPos. advance ( )
2053
+ }
2054
+
2055
+ return (
2056
+ . equal,
2057
+ error: LexingDiagnostic (
2058
+ . equalMustHaveConsistentWhitespaceOnBothSides,
2059
+ position: errorPos
2060
+ )
2061
+ )
2062
+ } else {
2063
+ return ( . equal, error: nil )
2064
+ }
2065
+ case UInt8 ( ascii: " & " ) :
2066
+ if leftBound == rightBound || leftBound {
2067
+ break
2068
+ }
2069
+ return ( . prefixAmpersand, error: nil )
2070
+ case UInt8 ( ascii: " . " ) :
2071
+ return ( . period, error: nil )
2072
+ case UInt8 ( ascii: " ? " ) :
2073
+ if ( leftBound) {
2074
+ return ( . postfixQuestionMark, error: nil )
2075
+ }
2076
+ return ( . infixQuestionMark, error: nil )
2077
+ default :
2078
+ break
2079
+ }
2080
+ } else if ( operEnd. input. baseAddress! - operStart. input. baseAddress! == 2 ) {
2081
+ switch ( operStart. peek ( ) , operStart. peek ( at: 1 ) ) {
2082
+ case ( UInt8 ( ascii: " - " ) , UInt8 ( ascii: " > " ) ) : // ->
2083
+ return ( . arrow, error: nil )
2084
+ case ( UInt8 ( ascii: " * " ) , UInt8 ( ascii: " / " ) ) : // */
2085
+ return ( . unknown, error: LexingDiagnostic ( . unexpectedBlockCommentEnd, position: operStart) )
2086
+ default :
2087
+ break
2088
+ }
2089
+ } else {
2090
+ // Verify there is no "*/" in the middle of the identifier token, we reject
2091
+ // it as potentially ending a block comment.
2092
+ if operStart. text ( upTo: operEnd) . contains ( " */ " ) {
2093
+ return ( . unknown, error: LexingDiagnostic ( . unexpectedBlockCommentEnd, position: operStart) )
2094
+ }
2095
+ }
2096
+
2097
+ if leftBound == rightBound {
2098
+ return ( . binaryOperator, error: nil )
2099
+ } else if leftBound {
2100
+ return ( . postfixOperator, error: nil )
2101
+ } else {
2102
+ return ( . prefixOperator, error: nil )
2103
+ }
2104
+ }
2105
+
2032
2106
mutating func lexOperatorIdentifier(
2033
2107
sourceBufferStart: Lexer . Cursor,
2034
2108
preferRegexOverBinaryOperator: Bool
@@ -2087,73 +2161,12 @@ extension Lexer.Cursor {
2087
2161
_ = ptr. advance ( )
2088
2162
}
2089
2163
}
2090
-
2091
- // Decide between the binary, prefix, and postfix cases.
2092
- // It's binary if either both sides are bound or both sides are not bound.
2093
- // Otherwise, it's postfix if left-bound and prefix if right-bound.
2094
- let leftBound = tokStart. isLeftBound ( sourceBufferStart: sourceBufferStart)
2095
- let rightBound = self . isRightBound ( isLeftBound: leftBound)
2096
-
2097
- // Match various reserved words.
2098
- if self . input. baseAddress! - tokStart. input. baseAddress! == 1 {
2099
- switch tokStart. peek ( ) {
2100
- case UInt8 ( ascii: " = " ) :
2101
- if leftBound != rightBound {
2102
- var errorPos = tokStart
2103
-
2104
- if rightBound {
2105
- _ = errorPos. advance ( )
2106
- }
2107
-
2108
- return Lexer . Result (
2109
- . equal,
2110
- error: LexingDiagnostic (
2111
- . equalMustHaveConsistentWhitespaceOnBothSides,
2112
- position: errorPos
2113
- )
2114
- )
2115
- } else {
2116
- return Lexer . Result ( . equal)
2117
- }
2118
- case UInt8 ( ascii: " & " ) :
2119
- if leftBound == rightBound || leftBound {
2120
- break
2121
- }
2122
- return Lexer . Result ( . prefixAmpersand)
2123
- case UInt8 ( ascii: " . " ) :
2124
- return Lexer . Result ( . period)
2125
- case UInt8 ( ascii: " ? " ) :
2126
- if ( leftBound) {
2127
- return Lexer . Result ( . postfixQuestionMark)
2128
- }
2129
- return Lexer . Result ( . infixQuestionMark)
2130
- default :
2131
- break
2132
- }
2133
- } else if ( self . input. baseAddress! - tokStart. input. baseAddress! == 2 ) {
2134
- switch ( tokStart. peek ( ) , tokStart. peek ( at: 1 ) ) {
2135
- case ( UInt8 ( ascii: " - " ) , UInt8 ( ascii: " > " ) ) : // ->
2136
- return Lexer . Result ( . arrow)
2137
- case ( UInt8 ( ascii: " * " ) , UInt8 ( ascii: " / " ) ) : // */
2138
- return Lexer . Result ( . unknown, error: LexingDiagnostic ( . unexpectedBlockCommentEnd, position: tokStart) )
2139
- default :
2140
- break
2141
- }
2142
- } else {
2143
- // Verify there is no "*/" in the middle of the identifier token, we reject
2144
- // it as potentially ending a block comment.
2145
- if tokStart. text ( upTo: self ) . contains ( " */ " ) {
2146
- return Lexer . Result ( . unknown, error: LexingDiagnostic ( . unexpectedBlockCommentEnd, position: tokStart) )
2147
- }
2148
- }
2149
-
2150
- if leftBound == rightBound {
2151
- return Lexer . Result ( . binaryOperator)
2152
- } else if leftBound {
2153
- return Lexer . Result ( . postfixOperator)
2154
- } else {
2155
- return Lexer . Result ( . prefixOperator)
2156
- }
2164
+ let ( kind, error) = Self . classifyOperatorToken (
2165
+ operStart: tokStart,
2166
+ operEnd: self ,
2167
+ sourceBufferStart: sourceBufferStart
2168
+ )
2169
+ return Lexer . Result ( kind, error: error)
2157
2170
}
2158
2171
2159
2172
mutating func lexDollarIdentifier( ) - > Lexer. Result {
0 commit comments