提问人:Philip Pegden 提问时间:10/6/2023 更新时间:10/6/2023 访问量:25
在词法分析器中使用 Swift RegexBuilder - 将 ChoiceOf 匹配输出元组折叠为 (SubString, TypeOfMatch) 类型
Using Swift RegexBuilder in a lexer - collapsing ChoiceOf match output tuple to (SubString, TypeOfMatch) type
问:
我正在使用 Swift 的词法分析器阶段实现一个解析器。我想知道我的正则表达式语句是否可以改进。RegexBuilder
ChoiceOf
具体来说,在下面的示例代码中,当匹配时,它会生成一个类型的元组,其中成员的数量将等于构造中的正则表达式项的数量。假设块返回类型中的所有正则表达式项,是否仍然有表示它,以便返回类型为 。tokenRegex
(SubString, Token?, Token?, ...)
Token?
ChoiceOf
ChoiceOf
Token
(SubString, Token?)
目前,我通过使用镜像功能折叠匹配输出元组来处理此问题,但如果可能的话,我想跳过这一步:
let token = Mirror(reflecting: match.output).children.compactMap({ $0.value as? Token }).first
下面是完整的示例代码。
import Foundation
import RegexBuilder
enum Token {
case number(Double)
case text(String)
case error(String)
static let tokenRegex = Regex {
ChoiceOf {
numberRegex
textRegex
// Further regex patterns, all returning type Token...
}
}
static let numberRegex = Regex {
Capture {
.localizedDouble(locale: Locale(identifier: "en-US"))
} transform: {
Token.number($0)
}}
static let textRegex = Regex {
Capture {
OneOrMore(.word)
} transform: {
Token.text(String($0))
}}
static func tokenise(_ text: String) -> [Token] {
var stringToParse = text
var tokens: [Token] = []
while !stringToParse.isEmpty {
let (token, matchEndIndex) = findNextToken(in: stringToParse)
tokens.append(token)
stringToParse = String(stringToParse[matchEndIndex...])
}
return tokens
}
static func findNextToken(in string: String) -> (Token, String.Index) {
do {
return if
let match = try tokenRegex.firstMatch(in: string),
let token = Mirror(reflecting: match.output).children.compactMap({ $0.value as? Token }).first
{
(token, match.0.endIndex)
} else {
(.error("Parse error"), string.endIndex)
}
} catch {
return (.error(error.localizedDescription), string.endIndex)
}
}
}
Token.tokenise("123MyDogIsHappy") // Produces -> [Token.double(123.0), Token.text("MyDogIsHappy")]
答: 暂无答案
评论