Skip to content

Commit aec8d23

Browse files
committed
Allow multi-character operators
1 parent 59c49c0 commit aec8d23

1 file changed

Lines changed: 36 additions & 17 deletions

File tree

ShapeScript/Lexer.swift

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ public enum Keyword: String, CaseIterable {
4747
case `import`
4848
}
4949

50-
public enum PrefixOperator: Character {
50+
public enum PrefixOperator: String {
5151
case plus = "+"
5252
case minus = "-"
5353
}
5454

55-
public enum InfixOperator: Character {
55+
public enum InfixOperator: String {
5656
case plus = "+"
5757
case minus = "-"
5858
case times = "*"
@@ -186,6 +186,7 @@ public extension String {
186186
private let whitespace = " \t"
187187
private let linebreaks = "\n\r\r\n"
188188
private let punctuation = "/()[]{}"
189+
private let operators = "+-*/<>=!?&|%^~"
189190
private let letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
190191
private let digits = "0123456789"
191192
private let alphanumerics = digits + letters
@@ -216,7 +217,7 @@ private extension Substring {
216217
if nextIndex != endIndex, self[nextIndex] == "/" {
217218
removeFirst()
218219
removeFirst()
219-
while let scalar = first, !scalar.isLinebreak {
220+
while let c = first, !c.isLinebreak {
220221
removeFirst()
221222
}
222223
}
@@ -256,7 +257,7 @@ private extension Substring {
256257
}
257258

258259
mutating func readOperator(spaceBefore: Bool) -> TokenType? {
259-
let start = self
260+
var start = self
260261
switch popFirst() {
261262
case "{": return .lbrace
262263
case "}": return .rbrace
@@ -268,23 +269,41 @@ private extension Substring {
268269
}
269270
self = start
270271
return nil
271-
case let scalar?:
272-
if let op = InfixOperator(rawValue: scalar) {
273-
guard let next = first else {
274-
// technically postfix, but we don't have those
275-
return .infix(op)
276-
}
277-
if !spaceBefore || next.isWhitespace || next.isLinebreak {
272+
case let c? where operators.contains(c):
273+
func toOp(_ string: String) -> TokenType? {
274+
if let op = InfixOperator(rawValue: string) {
275+
guard let next = first else {
276+
// technically postfix, but we don't have those
277+
return .infix(op)
278+
}
279+
if !spaceBefore || next.isWhitespace || next.isLinebreak {
280+
return .infix(op)
281+
}
282+
if let op = PrefixOperator(rawValue: string) {
283+
return .prefix(op)
284+
}
278285
return .infix(op)
279-
}
280-
if let op = PrefixOperator(rawValue: scalar) {
286+
} else if let op = PrefixOperator(rawValue: string) {
281287
return .prefix(op)
288+
} else {
289+
return nil
282290
}
283-
return .infix(op)
284-
} else if let op = PrefixOperator(rawValue: scalar) {
285-
return .prefix(op)
286291
}
287-
fallthrough
292+
var string = String(c)
293+
var op = toOp(string)
294+
if op != nil {
295+
start = self
296+
}
297+
while let c = first, operators.contains(c) {
298+
removeFirst()
299+
string.append(c)
300+
if let nextOp = toOp(string) {
301+
op = nextOp
302+
start = self
303+
}
304+
}
305+
self = start
306+
return op
288307
default:
289308
self = start
290309
return nil

0 commit comments

Comments
 (0)