Replies: 4 comments 5 replies
-
I worked around this limitation by implementing my own public struct Characters: Parser {
struct MinimumNotReachedError: Error {}
let characterSet: CharacterSet
let minimum: Int
let maximum: Int
public init(
in characterSet: CharacterSet,
atLeast minimum: Int = 0,
atMost maximum: Int = .max
) {
self.characterSet = characterSet
self.minimum = minimum
self.maximum = maximum
}
public func parse(_ input: inout Substring) throws -> Substring {
let original = input
var output: Substring.UnicodeScalarView = .init()
while output.count < maximum, !input.unicodeScalars.isEmpty, self.characterSet.contains(input.unicodeScalars.first!) {
output.append(input.unicodeScalars.removeFirst())
}
guard output.count >= minimum else {
input = original
throw MinimumNotReachedError()
}
return Substring(output)
}
} Usage is something like this: var input = "zh-Hans.lproj"
let locale = try Parse {
Characters(in: CharacterSet(charactersIn: "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz-"), atLeast: 2)
".lproj"
End()
}.parse(&input) If this is considered useful, I can post a PR to incude this into the library directly (or feel free to copy & paste). |
Beta Was this translation helpful? Give feedback.
-
Having You can also technically do this with try Many(atLeast: 2) {
First<Substring.UnicodeScalarView>()
.filter(CharacterSet.alphanumerics.contains)
}
.parse("ABC".unicodeScalars) At one point we sketched out how to really deeply integrate the ideas of min/max into parsers so that you could chain on |
Beta Was this translation helpful? Give feedback.
-
@mbrandonw Thank you for the quick & detailed answer. I get it now, I think I'll keep my custom parser then. On the same note, it sounded like you are not interested in adding this custom parser into the library to keep it small. I am interested in exploring the area of regular expression to replace them by a more readable, declarative syntax based on swift-parsing. If I understand you right, you are (currently) not interested in such a feature added to the library directly, right? See also #153. Because if you don't want this area explored within the library, I will probably just create a new library based on swift-parsing where I can then add the missing parts (like the above Also, I'm sure others will create other libs based on this (or already have?), so maybe you want to also consider showcasing libs based on this in the README (or somewhere else). |
Beta Was this translation helpful? Give feedback.
-
As a side note on this, I found the documentation on this parser a bit lacking. From the description I didn't get that it just tries to consume the characters, if no character match it just doesn't do anything, but it doesn't throw an error (which for some reason is what I was expecting) Maybe is worth to improve the documentation overall indicating a bit more specifically what the behaviours in terms of erroring, doing a noop or backtracking. |
Beta Was this translation helpful? Give feedback.
-
I found that
CharacterSet
conforms toParser
, but for some reason it seems to be built as a "any number of characters from the character set" parser, here's it's current implementation (source):Wouldn't an extra struct that accepts arguments similar to
Many
(such asatLeast
andatMost
) make this more useful? Comparing this to regular expressions, where I can specify[abc]*
but also[abc]{3,}
it seems the library is less powerful. Or is there a way I can useMany
andCharacterSet
combined to build such a parser?Beta Was this translation helpful? Give feedback.
All reactions