1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//
extension AST {
public struct CustomCharacterClass: Hashable {
public var start: Located<Start>
public var members: [Member]
public let location: SourceLocation
public init(
_ start: Located<Start>,
_ members: [Member],
_ sr: SourceLocation
) {
self.start = start
self.members = members
self.location = sr
}
public enum Member: Hashable {
/// A nested custom character class `[[ab][cd]]`
case custom(CustomCharacterClass)
/// A character range `a-z`
case range(Range)
/// A single character or escape
case atom(Atom)
/// A quoted sequence. Inside a custom character class this just means
/// the contents should be interpreted literally.
case quote(Quote)
/// Trivia such as non-semantic whitespace.
case trivia(Trivia)
/// A binary operator applied to sets of members `abc&&def`
case setOperation([Member], Located<SetOp>, [Member])
}
public struct Range: Hashable {
public var lhs: Atom
public var dashLoc: SourceLocation
public var rhs: Atom
public var trivia: [AST.Trivia]
public init(
_ lhs: Atom, _ dashLoc: SourceLocation, _ rhs: Atom,
trivia: [AST.Trivia]
) {
self.lhs = lhs
self.dashLoc = dashLoc
self.rhs = rhs
self.trivia = trivia
}
public var location: SourceLocation {
lhs.location.union(with: rhs.location)
}
}
public enum SetOp: String, Hashable {
case subtraction = "--"
case intersection = "&&"
case symmetricDifference = "~~"
}
public enum Start: String, Hashable {
case normal = "["
case inverted = "[^"
}
}
}
extension AST.CustomCharacterClass {
public var isInverted: Bool { start.value == .inverted }
}
extension CustomCC.Member {
private var _associatedValue: Any {
switch self {
case .custom(let c): return c
case .range(let r): return r
case .atom(let a): return a
case .quote(let q): return q
case .trivia(let t): return t
case .setOperation(let lhs, let op, let rhs): return (lhs, op, rhs)
}
}
func `as`<T>(_ t: T.Type = T.self) -> T? {
_associatedValue as? T
}
public var isTrivia: Bool {
if case .trivia = self { return true }
return false
}
public var asTrivia: AST.Trivia? {
guard case .trivia(let t) = self else { return nil }
return t
}
public var isSemantic: Bool {
!isTrivia
}
public var location: SourceLocation {
switch self {
case let .custom(c): return c.location
case let .range(r): return r.location
case let .atom(a): return a.location
case let .quote(q): return q.location
case let .trivia(t): return t.location
case let .setOperation(lhs, dash, rhs):
var loc = dash.location
if let lhs = lhs.first {
loc = loc.union(with: lhs.location)
}
if let rhs = rhs.last {
loc = loc.union(with: rhs.location)
}
return loc
}
}
}
extension AST.CustomCharacterClass {
/// Strips trivia from the character class members.
///
/// This method doesn't recurse into nested custom character classes.
public var strippingTriviaShallow: Self {
var copy = self
copy.members = copy.members.filter(\.isSemantic)
return copy
}
}
|