I'm trying to develop a parser that works off of Swift enums that represent tokens. I would like to be able to validate that a token is one of a certain type (e.g. in this case a certain case of an enum). Looking at the Swift docs, a way to do this without an additional enum isn't apparent to me, and I'm not optimistic. Is the following as close I can get to a more succinct pure Swift language-level solution?
enum SymbolTokenType {
case river, lake, mountain, meadow, valley, openParen, closeParen, logicalAnd, logicalOr, logicalNot
}
enum SymbolToken {
case river (key: RiverKey?)
case lake (key: LakeKey?)
case mountain (key: MountainKey?)
case meadow (key: MeadowKey?)
case valley (key: ValleyKey?)
case openParen
case closeParen
case logicalAnd
case logicalOr
case logicalNot
func validateTokenType(validTypes: [SymbolTokenType] ) -> Bool {
switch(self) {
case .river:
return validTypes.contains(.river)
case .lake:
return validTypes.contains(.lake)
case .mountain:
return validTypes.contains(.mountain)
case .meadow:
return validTypes.contains(.meadow)
case .valley:
return validTypes.contains(.valley)
case .openParen:
return validTypes.contains(.openParen)
case .closeParen:
return validTypes.contains(.closeParen)
case .logicalAnd:
return validTypes.contains(.logicalAnd)
case .logicalOr:
return validTypes.contains(.logicalOr)
case .logicalNot:
return validTypes.contains(.logicalNot)
}
}
}
CodePudding user response:
I would do like this:
enum Token {
case token1
case token2
case token3
func isValid(from container: [Token]) -> Bool {
container.contains(self)
}
}
let validTokens: [Token] = [.token1, .token2]
let testedToken2 = Token.token2
let testedToken3 = Token.token3
testedToken2.isValid(from: validTokens) // True
testedToken3.isValid(from: validTokens) // False
CodePudding user response:
You definitely don't need two enums. You just have to deal with cases with associated values a bit differently.
protocol SimilarComparable: Equatable {
func isSimilar(to other: Self) -> Bool
func isSimilar(toAny others: [Self]) -> Bool
}
extension SimilarComparable {
func isSimilar(toAny others: [Self]) -> Bool {
let result = others.first(where: { $0.isSimilar(to: self) }) != nil
print("Finding similarity to \(self) in \(others) == \(result)")
return result
}
}
enum SymbolToken: SimilarComparable {
case river (key: String?)
case lake (key: String?)
case mountain (key: String?)
case meadow (key: String?)
case valley (key: String?)
case openParen
case closeParen
case logicalAnd
case logicalOr
case logicalNot
func isSimilar(to other: SymbolToken) -> Bool {
let result: Bool
print("Finding similarit to \(self) to \(other) == ", separator: " ", terminator: "")
switch (self, other) {
case (.river, .river):
result = true
case (.lake, .lake):
result = true
case (.mountain, .mountain):
result = true
case (.meadow, .meadow):
result = true
case (.valley, .valley):
result = true
default:
result = self == other
}
print("\(result)")
return result
}
}
Usage would be like this:
_ = SymbolToken.river(key: "Hudson").isSimilar(to: .river(key: "Nile")) // true
_ = SymbolToken.lake(key: "Michigan").isSimilar(to: .lake(key: "Tahoe")) // true
_ = SymbolToken.closeParen.isSimilar(to: .closeParen) // true
_ = SymbolToken.logicalOr.isSimilar(to: .logicalOr) // true
_ = SymbolToken.logicalOr.isSimilar(to: .logicalAnd) // false
let tokens: [SymbolToken] = [
.river(key: "Hudson"),
.lake(key: "Tahoe"),
.closeParen,
.logicalOr,
]
_ = SymbolToken.logicalOr.isSimilar(toAny: tokens) // true
_ = SymbolToken.lake(key: "Michigan").isSimilar(toAny: tokens) // true