From ab308ee658be834d651aa5cef1c4bcbff8b482d3 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Thu, 21 Apr 2022 10:40:26 -0700 Subject: [PATCH 1/4] Revise doc comments for API reference style. - Fix spelling error in parameter name (invertion --> inversion). - Add docs for parameters and return values. - Use indicative instead of imperative for method/function/initializer abstracts. (Match a regex. --> Matches a regex.) - Don't use code voice in abstracts, or symbol names as English nouns. - Use contractions per Apple style. - Turn /// comments that contain notes for this API's implementers into plain // comments, to omit that content from the docs. Move them before the /// comments, to keep doc comments immediately adjacent to the declaration they documents. --- Sources/RegexBuilder/CharacterClass.swift | 6 +- Sources/RegexBuilder/DSL.swift | 11 ++-- Sources/_RegexParser/Regex/AST/AST.swift | 21 ++++--- Sources/_RegexParser/Regex/AST/Atom.swift | 14 +++-- .../Regex/AST/CustomCharClass.swift | 5 +- Sources/_RegexParser/Regex/AST/Group.swift | 13 +++-- .../Regex/AST/MatchingOptions.swift | 11 ++-- .../Regex/AST/Quantification.swift | 2 +- .../Regex/Parse/CaptureStructure.swift | 3 +- Sources/_RegexParser/Regex/Parse/Parse.swift | 4 +- Sources/_RegexParser/Regex/Parse/Source.swift | 10 ++-- .../Regex/Parse/SourceLocation.swift | 8 +-- .../Regex/Parse/SyntaxOptions.swift | 28 +++++----- .../_RegexParser/Regex/Printing/DumpAST.swift | 7 ++- .../Regex/Printing/PrettyPrinter.swift | 50 ++++++++++------- .../Regex/Printing/PrintAsCanonical.swift | 16 ++++-- Sources/_RegexParser/Utility/Misc.swift | 14 +++-- .../_RegexParser/Utility/MissingUnicode.swift | 30 ++++++---- .../Algorithms/Algorithms/Split.swift | 6 +- .../Algorithms/Algorithms/StartsWith.swift | 3 +- .../_StringProcessing/PrintAsPattern.swift | 2 +- .../Regex/AnyRegexOutput.swift | 23 +++++--- Sources/_StringProcessing/Regex/Core.swift | 2 +- Sources/_StringProcessing/Regex/DSLTree.swift | 14 ++--- Sources/_StringProcessing/Regex/Match.swift | 55 +++++++++++-------- Sources/_StringProcessing/Regex/Options.swift | 51 +++++++++++++---- .../_CharacterClassModel.swift | 21 ++++--- 27 files changed, 269 insertions(+), 161 deletions(-) diff --git a/Sources/RegexBuilder/CharacterClass.swift b/Sources/RegexBuilder/CharacterClass.swift index b7d8454bb..3a96ba363 100644 --- a/Sources/RegexBuilder/CharacterClass.swift +++ b/Sources/RegexBuilder/CharacterClass.swift @@ -100,7 +100,7 @@ extension RegexComponent where Self == CharacterClass { members: s.map { .atom(.char($0)) })) } - /// Returns a character class that matches any unicode scalar in the given + /// Returns a character class that matches any Unicode scalar in the given /// sequence. public static func anyOf(_ s: S) -> CharacterClass where S.Element == UnicodeScalar @@ -118,7 +118,7 @@ extension CharacterClass { } } -/// Range syntax for characters in `CharacterClass`es. +/// Returns a character class that includes the characters in the given range. @available(SwiftStdlib 5.7, *) public func ...(lhs: Character, rhs: Character) -> CharacterClass { let range: DSLTree.CustomCharacterClass.Member = .range(.char(lhs), .char(rhs)) @@ -126,7 +126,7 @@ public func ...(lhs: Character, rhs: Character) -> CharacterClass { return CharacterClass(ccc) } -/// Range syntax for unicode scalars in `CharacterClass`es. +/// Returns a character class that includes the Unicode scalars in the given range. @_disfavoredOverload @available(SwiftStdlib 5.7, *) public func ...(lhs: UnicodeScalar, rhs: UnicodeScalar) -> CharacterClass { diff --git a/Sources/RegexBuilder/DSL.swift b/Sources/RegexBuilder/DSL.swift index 62aacc4af..10590fb74 100644 --- a/Sources/RegexBuilder/DSL.swift +++ b/Sources/RegexBuilder/DSL.swift @@ -95,8 +95,8 @@ extension UnicodeScalar: RegexComponent { // Note: Quantifiers are currently gyb'd. extension DSLTree.Node { - /// Generates a DSLTree node for a repeated range of the given DSLTree node. - /// Individual public API functions are in the generated Variadics.swift file. + // Individual public API functions are in the generated Variadics.swift file. + /// Generates a DSL tree node for a repeated range of the given node. @available(SwiftStdlib 5.7, *) static func repeating( _ range: Range, @@ -251,8 +251,10 @@ public struct TryCapture: _BuiltinRegexComponent { // MARK: - Groups -/// An atomic group, i.e. opens a local backtracking scope which, upon successful exit, -/// discards any remaining backtracking points from within the scope +/// An atomic group. +/// +/// This group opens a local backtracking scope which, upon successful exit, +/// discards any remaining backtracking points from within the scope. @available(SwiftStdlib 5.7, *) public struct Local: _BuiltinRegexComponent { public var regex: Regex @@ -265,6 +267,7 @@ public struct Local: _BuiltinRegexComponent { // MARK: - Backreference @available(SwiftStdlib 5.7, *) +/// A backreference. public struct Reference: RegexComponent { let id = ReferenceID() diff --git a/Sources/_RegexParser/Regex/AST/AST.swift b/Sources/_RegexParser/Regex/AST/AST.swift index 409d5a7ee..eae393289 100644 --- a/Sources/_RegexParser/Regex/AST/AST.swift +++ b/Sources/_RegexParser/Regex/AST/AST.swift @@ -9,8 +9,9 @@ // //===----------------------------------------------------------------------===// -/// A regex abstract syntax tree. This is a top-level type that stores the root -/// node. +/// A regex abstract syntax tree. +/// +/// This is a top-level type that stores the root node. public struct AST: Hashable { public var root: AST.Node public var globalOptions: GlobalMatchingOptionSequence? @@ -22,7 +23,7 @@ public struct AST: Hashable { } extension AST { - /// Whether this AST tree has nested somewhere inside it a capture. + /// Whether this AST tree contains at least one capture nested inside of it. public var hasCapture: Bool { root.hasCapture } /// The capture structure of this AST tree. @@ -94,7 +95,9 @@ extension AST.Node { _associatedValue as? T } - /// If this node is a parent node, access its children + /// The child nodes of this node. + /// + /// If the node isn't a parent node, this value is `nil`. public var children: [AST.Node]? { return (_associatedValue as? _ASTParent)?.children } @@ -103,7 +106,7 @@ extension AST.Node { _associatedValue.location } - /// Whether this node is "trivia" or non-semantic, like comments + /// Whether this node is trivia or non-semantic, like comments. public var isTrivia: Bool { switch self { case .trivia: return true @@ -111,7 +114,7 @@ extension AST.Node { } } - /// Whether this node has nested somewhere inside it a capture + /// Whether this node contains at least one capture nested inside of it. public var hasCapture: Bool { switch self { case .group(let g) where g.kind.value.isCapturing: @@ -122,7 +125,7 @@ extension AST.Node { return self.children?.any(\.hasCapture) ?? false } - /// Whether this AST node may be used as the operand of a quantifier such as + /// Whether this node may be used as the operand of a quantifier such as /// `?`, `+` or `*`. public var isQuantifiable: Bool { switch self { @@ -203,7 +206,9 @@ extension AST { } } - /// An Oniguruma absent function. This is used to model a pattern which should + /// An Oniguruma absent function. + /// + /// This is used to model a pattern which should /// not be matched against across varying scopes. public struct AbsentFunction: Hashable, _ASTNode { public enum Start: Hashable { diff --git a/Sources/_RegexParser/Regex/AST/Atom.swift b/Sources/_RegexParser/Regex/AST/Atom.swift index 1f6043d72..e17ce68bb 100644 --- a/Sources/_RegexParser/Regex/AST/Atom.swift +++ b/Sources/_RegexParser/Regex/AST/Atom.swift @@ -415,7 +415,7 @@ extension AST.Atom.CharacterProperty { } extension AST.Atom { - /// Anchors and other built-in zero-width assertions + /// Anchors and other built-in zero-width assertions. @frozen public enum AssertionKind: String { /// \A @@ -574,7 +574,7 @@ extension AST.Atom { } extension AST.Atom.Callout { - /// A tag specifier `[...]` which may appear in an Oniguruma callout. + /// A tag specifier `[...]` that can appear in an Oniguruma callout. public struct OnigurumaTag: Hashable { public var leftBracket: SourceLocation public var name: AST.Located @@ -668,8 +668,10 @@ extension AST.Atom.EscapedBuiltin { } extension AST.Atom { - /// Retrieve the character value of the atom if it represents a literal - /// character or unicode scalar, nil otherwise. + /// Retrieves the character value of the atom. + /// + /// If the atom doesn't represent a literal character or a Unicode scalar, + /// this value is `nil`. public var literalCharacterValue: Character? { switch kind { case .char(let c): @@ -711,9 +713,9 @@ extension AST.Atom { } } - /// Produce a string literal representation of the atom, if possible + /// A string literal representation of the atom, if possible. /// - /// Individual characters will be returned, Unicode scalars will be + /// Individual characters are returned as-is, and Unicode scalars are /// presented using "\u{nnnn}" syntax. public var literalStringValue: String? { switch kind { diff --git a/Sources/_RegexParser/Regex/AST/CustomCharClass.swift b/Sources/_RegexParser/Regex/AST/CustomCharClass.swift index 19e72aef5..c1dd4c620 100644 --- a/Sources/_RegexParser/Regex/AST/CustomCharClass.swift +++ b/Sources/_RegexParser/Regex/AST/CustomCharClass.swift @@ -104,8 +104,9 @@ extension CustomCC.Member { } extension AST.CustomCharacterClass { - /// Strip trivia from the character class members. This does not recurse into - /// nested custom character classes. + /// 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) diff --git a/Sources/_RegexParser/Regex/AST/Group.swift b/Sources/_RegexParser/Regex/AST/Group.swift index a8c4f8b0f..8ecaadeda 100644 --- a/Sources/_RegexParser/Regex/AST/Group.swift +++ b/Sources/_RegexParser/Regex/AST/Group.swift @@ -78,6 +78,7 @@ extension AST { } extension AST.Group.Kind { + /// Whether the group is a capturing group. public var isCapturing: Bool { switch self { case .capture, .namedCapture, .balancedCapture: return true @@ -85,7 +86,9 @@ extension AST.Group.Kind { } } - /// If this is a named group, its name, `nil` otherwise. + /// The name of the group. + /// + /// If the group doesn't have a name, this value is `nil`. public var name: String? { switch self { case .namedCapture(let name): return name.value @@ -96,9 +99,11 @@ extension AST.Group.Kind { } extension AST.Group.Kind { - /// If this group is a lookaround assertion, return its direction - /// and whether it is positive or negative. Otherwise returns - /// `nil`. + /// The direction of a lookaround assertion + /// and an indication of whether the assertion is positive or negative. + /// + /// If the group isn't a lookaheand or lookbehind assertion, + /// this value is `nil`. public var lookaroundKind: (forwards: Bool, positive: Bool)? { switch self { case .lookahead: return (true, true) diff --git a/Sources/_RegexParser/Regex/AST/MatchingOptions.swift b/Sources/_RegexParser/Regex/AST/MatchingOptions.swift index 8e4b31bc5..e779c39fb 100644 --- a/Sources/_RegexParser/Regex/AST/MatchingOptions.swift +++ b/Sources/_RegexParser/Regex/AST/MatchingOptions.swift @@ -10,7 +10,7 @@ //===----------------------------------------------------------------------===// extension AST { - /// An option written in source that changes matching semantics. + /// An option, written in source, that changes matching semantics. public struct MatchingOption: Hashable { public enum Kind { // PCRE options @@ -83,7 +83,7 @@ extension AST { } } - /// A sequence of matching options written in source. + /// A sequence of matching options, written in source. public struct MatchingOptionSequence: Hashable { /// If the sequence starts with a caret '^', its source location, or nil /// otherwise. If this is set, it indicates that all the matching options @@ -138,8 +138,11 @@ extension AST.MatchingOptionSequence: _ASTPrintable { } extension AST { - /// Global matching option specifiers. Unlike `MatchingOptionSequence`, - /// these must appear at the start of the pattern, and apply globally. + /// Global matching option specifiers. + /// + /// Unlike `MatchingOptionSequence`, + /// these options must appear at the start of the pattern, + /// and they apply to the entire pattern. public struct GlobalMatchingOption: _ASTNode, Hashable { /// Determines the definition of a newline for the '.' character class and /// when parsing end-of-line comments. diff --git a/Sources/_RegexParser/Regex/AST/Quantification.swift b/Sources/_RegexParser/Regex/AST/Quantification.swift index f2189cb38..fa7e4de82 100644 --- a/Sources/_RegexParser/Regex/AST/Quantification.swift +++ b/Sources/_RegexParser/Regex/AST/Quantification.swift @@ -59,7 +59,7 @@ extension AST { /// MARK: - Semantic API extension AST.Quantification.Amount { - /// Get the bounds + /// The bounds. public var bounds: (atLeast: Int, atMost: Int?) { switch self { case .zeroOrMore: return (0, nil) diff --git a/Sources/_RegexParser/Regex/Parse/CaptureStructure.swift b/Sources/_RegexParser/Regex/Parse/CaptureStructure.swift index 8298dc207..9cb31c7d9 100644 --- a/Sources/_RegexParser/Regex/Parse/CaptureStructure.swift +++ b/Sources/_RegexParser/Regex/Parse/CaptureStructure.swift @@ -286,10 +286,11 @@ extension CaptureStructure { MemoryLayout.stride + inputUTF8CodeUnitCount + 1 } - /// Encode the capture structure to the given buffer as a serialized + /// Encodes the capture structure to the given buffer as a serialized /// representation. /// /// The encoding rules are as follows: + /// /// ``` /// encode(〚`T`〛) ==> , 〚`T`〛, .end /// 〚`T` (atom)〛 ==> .atom diff --git a/Sources/_RegexParser/Regex/Parse/Parse.swift b/Sources/_RegexParser/Regex/Parse/Parse.swift index a2790924a..ec6e1c26c 100644 --- a/Sources/_RegexParser/Regex/Parse/Parse.swift +++ b/Sources/_RegexParser/Regex/Parse/Parse.swift @@ -577,8 +577,8 @@ fileprivate func defaultSyntaxOptions( } } -/// Parse a given regex string with delimiters, inferring the syntax options -/// from the delimiter used. +/// Parses a given regex string with delimiters, inferring the syntax options +/// from the delimiters used. public func parseWithDelimiters( _ regex: S ) throws -> AST where S.SubSequence == Substring { diff --git a/Sources/_RegexParser/Regex/Parse/Source.swift b/Sources/_RegexParser/Regex/Parse/Source.swift index 6eac16395..23cc0497d 100644 --- a/Sources/_RegexParser/Regex/Parse/Source.swift +++ b/Sources/_RegexParser/Regex/Parse/Source.swift @@ -9,10 +9,12 @@ // //===----------------------------------------------------------------------===// -/// The source given to a parser. This can be bytes in memory, a file on disk, -/// something streamed over a network connection, etc. +// For now, we use String as the source while prototyping... + +/// The source of text being given to a parser. /// -/// For now, we use String... +/// This can be bytes in memory, a file on disk, +/// something streamed over a network connection, and so on. /// public struct Source { var input: Input @@ -37,7 +39,7 @@ extension Source { public typealias Input = String // for wrapper... public typealias Char = Character // for wrapper... - /// A precise point in the input, commonly used for bounded ranges + /// A precise point in the input, commonly used for bounded ranges. public typealias Position = String.Index } diff --git a/Sources/_RegexParser/Regex/Parse/SourceLocation.swift b/Sources/_RegexParser/Regex/Parse/SourceLocation.swift index a58473c96..eb51643bd 100644 --- a/Sources/_RegexParser/Regex/Parse/SourceLocation.swift +++ b/Sources/_RegexParser/Regex/Parse/SourceLocation.swift @@ -62,7 +62,7 @@ public protocol LocatedErrorProtocol: Error { } extension Source { - /// An error with source location info + /// An error that includes information about the location in source code. public struct LocatedError: Error, LocatedErrorProtocol { public let error: E public let location: SourceLocation @@ -77,10 +77,10 @@ extension Source { } } - /// Located value: a value wrapped with a source range + /// A value wrapped with a source range. /// - /// Note: source location is part of value identity, so that the same - /// e.g. `Character` appearing twice can be stored in a data structure + /// Note: Source location is part of value identity so that, for example, the + /// same `Character` value appearing twice can be stored in a data structure /// distinctly. To ignore source locations, use `.value` directly. public struct Located { public var value: T diff --git a/Sources/_RegexParser/Regex/Parse/SyntaxOptions.swift b/Sources/_RegexParser/Regex/Parse/SyntaxOptions.swift index b7c09ea1c..0a6270f1b 100644 --- a/Sources/_RegexParser/Regex/Parse/SyntaxOptions.swift +++ b/Sources/_RegexParser/Regex/Parse/SyntaxOptions.swift @@ -31,31 +31,31 @@ public struct SyntaxOptions: OptionSet { [.endOfLineComments, .nonSemanticWhitespace] } + // NOTE: Currently, this means we have raw quotes. + // Better would be to have real Swift string delimiter parsing logic. + /// `'a "." b' == '/a\Q.\Eb/'` - /// - /// NOTE: Currently, this means we have raw quotes. - /// Better would be to have real Swift string delimiter parsing logic. public static var experimentalQuotes: Self { Self(1 << 2) } + // NOTE: traditional comments are not nested. Currently, we are neither. + // Traditional comments can't have `)`, not even escaped in them either, we + // can. Traditional comments can have `*/` in them, we can't without + // escaping. We don't currently do escaping. + /// `'a /* comment */ b' == '/a(?#. comment )b/'` - /// - /// NOTE: traditional comments are not nested. Currently, we are neither. - /// Traditional comments can't have `)`, not even escaped in them either, we - /// can. Traditional comments can have `*/` in them, we can't without - /// escaping. We don't currently do escaping. public static var experimentalComments: Self { Self(1 << 3) } /// ``` - /// 'a{n...m}' == '/a{n,m}/' - /// 'a{n...*)` - /// `(_: .*)` == `(?:.*)` + /// `(_: .*)` == `(?:.*)` public static var experimentalCaptures: Self { Self(1 << 5) } /// The default syntax for a multi-line regex literal. diff --git a/Sources/_RegexParser/Regex/Printing/DumpAST.swift b/Sources/_RegexParser/Regex/Printing/DumpAST.swift index 8565b14e9..a9cf6b424 100644 --- a/Sources/_RegexParser/Regex/Printing/DumpAST.swift +++ b/Sources/_RegexParser/Regex/Printing/DumpAST.swift @@ -9,10 +9,11 @@ // //===----------------------------------------------------------------------===// -/// AST entities can be pretty-printed or dumped +/// AST entities that can be pretty-printed or dumped. /// -/// Alternative: just use `description` for pretty-print -/// and `debugDescription` for dump +/// As an alternative to this protocol, +/// you can also use the `description` to pretty-print an AST, +/// and `debugDescription` for to dump a debugging representation. public protocol _ASTPrintable: CustomStringConvertible, CustomDebugStringConvertible diff --git a/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift b/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift index f1d8c83b0..c06643aee 100644 --- a/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift +++ b/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift @@ -9,17 +9,25 @@ // //===----------------------------------------------------------------------===// -/// Track and handle state relevant to pretty-printing ASTs. +/// State used when to pretty-printing regex ASTs. public struct PrettyPrinter { // Configuration - /// Cut off pattern conversion after this many levels + /// The maximum number number of levels, from the root of the tree, + /// at which to perform pattern conversion. + /// + /// A `nil` value indicates that there is no maximum, + /// and pattern conversion always takes place. public var maxTopDownLevels: Int? - /// Cut off pattern conversion after this tree height + /// The maximum number number of levels, from the leaf nodes of the tree, + /// at which to perform pattern conversion. + /// + /// A `nil` value indicates that there is no maximum, + /// and pattern conversion always takes place. public var minBottomUpLevels: Int? - /// How many spaces to indent with ("tab-width") + /// The number of spaces used for indentation. public var indentWidth = 2 // Internal state @@ -46,25 +54,27 @@ extension PrettyPrinter { self.minBottomUpLevels = minBottomUpLevels } - /// Output a string directly, without termination, without - /// indentation, and without updating _any_ internal state. + /// Outputs a string directly, without termination or + /// indentation, and without updating any internal state. /// /// This is the low-level interface to the pret /// - /// NOTE: If `s` includes a newline, even at the end, - /// this function will not update any tracking state. + /// - Note: If `s` includes a newline, even at the end, + /// this method does not update any tracking state. public mutating func output(_ s: String) { result += s } - /// Terminate a line, updating any relevant state + /// Terminates a line, updating any relevant state. public mutating func terminateLine() { output("\n") startOfLine = true } - /// Indent a new line, if at the start of a line, otherwise - /// does nothing. Updates internal state. + /// Indents a new line, if at the start of a line, otherwise + /// does nothing. + /// + /// This function updates internal state. public mutating func indent() { guard startOfLine else { return } let numCols = indentLevel * indentWidth @@ -72,7 +82,9 @@ extension PrettyPrinter { startOfLine = false } - // Finish, flush, and clear. Returns the rendered output + // Finish, flush, and clear. + // + // - Returns: The rendered output. public mutating func finish() -> String { defer { result = "" } return result @@ -85,18 +97,18 @@ extension PrettyPrinter { extension PrettyPrinter { /// Print out a new entry. /// - /// This will property indent `s`, update any internal state, - /// and will also terminate the current line. + /// This method indents `s`, updates any internal state, + /// and terminates the current line. public mutating func print(_ s: String) { indent() output("\(s)") terminateLine() } - /// Print out a new entry by invoking `f` until it returns `nil`. + /// Prints out a new entry by invoking `f` until it returns `nil`. /// - /// This will property indent, update any internal state, - /// and will also terminate the current line. + /// This method indents `s`, updates any internal state, + /// and terminates the current line. public mutating func printLine(_ f: () -> String?) { // TODO: What should we do if `f` never returns non-nil? indent() @@ -106,7 +118,7 @@ extension PrettyPrinter { terminateLine() } - /// Execute `f` at one increased level of indentation + /// Executes `f` at one increased level of indentation. public mutating func printIndented( _ f: (inout Self) -> () ) { @@ -115,7 +127,7 @@ extension PrettyPrinter { self.indentLevel -= 1 } - /// Execute `f` inside an indented "block", which has a header + /// Executes `f` inside an indented block, which has a header /// and delimiters. public mutating func printBlock( _ header: String, diff --git a/Sources/_RegexParser/Regex/Printing/PrintAsCanonical.swift b/Sources/_RegexParser/Regex/Printing/PrintAsCanonical.swift index ab961ba51..59c0cc04a 100644 --- a/Sources/_RegexParser/Regex/Printing/PrintAsCanonical.swift +++ b/Sources/_RegexParser/Regex/Printing/PrintAsCanonical.swift @@ -12,7 +12,7 @@ // TODO: Round-tripping tests extension AST { - /// Render using Swift's preferred regex literal syntax + /// Renders using Swift's preferred regex literal syntax. public func renderAsCanonical( showDelimiters delimiters: Bool = false, terminateLine: Bool = false @@ -27,7 +27,7 @@ extension AST { } extension AST.Node { - /// Render using Swift's preferred regex literal syntax + /// Renders using Swift's preferred regex literal syntax. public func renderAsCanonical( showDelimiters delimiters: Bool = false, terminateLine: Bool = false @@ -38,8 +38,12 @@ extension AST.Node { } extension PrettyPrinter { - /// Will output `ast` in canonical form, taking care to - /// also indent and terminate the line (updating internal state) + /// Outputs a regular expression abstract syntax tree in canonical form, + /// indenting and terminating the line, and updating its internal state. + /// + /// - Parameter ast: The abstract syntax tree of the regular expression being output. + /// - Parameter delimiters: Whether to include commas between items. + /// - Parameter terminateLine: Whether to include terminate the line. public mutating func printAsCanonical( _ ast: AST, delimiters: Bool = false, @@ -57,8 +61,8 @@ extension PrettyPrinter { } } - /// Output the `ast` in canonical form, does not indent, terminate, - /// or affect internal state + /// Outputs a regular expression abstract syntax tree in canonical form, + /// without indentation, line termation, or affecting its internal state. mutating func outputAsCanonical(_ ast: AST.Node) { switch ast { case let .alternation(a): diff --git a/Sources/_RegexParser/Utility/Misc.swift b/Sources/_RegexParser/Utility/Misc.swift index 55d3d3adc..bd9bc665e 100644 --- a/Sources/_RegexParser/Utility/Misc.swift +++ b/Sources/_RegexParser/Utility/Misc.swift @@ -111,8 +111,11 @@ extension Collection { } extension Collection where Element: Equatable { - /// Attempt to drop a given prefix from the collection, returning the - /// resulting subsequence, or `nil` if the prefix does not match. + /// Attempts to drop a given prefix from the collection. + /// + /// - Parameter other: The collection that contains the prefix. + /// - Returns: The resulting subsequence, + /// or `nil` if the prefix doesn't match. public func tryDropPrefix( _ other: C ) -> SubSequence? where C.Element == Element { @@ -121,8 +124,11 @@ extension Collection where Element: Equatable { return dropFirst(prefixCount) } - /// Attempt to drop a given suffix from the collection, returning the - /// resulting subsequence, or `nil` if the suffix does not match. + /// Attempts to drop a given suffix from the collection. + /// + /// - Parameter other: The collection that contains the suffix. + /// - Returns: The resulting subsequence, + /// or `nil` if the prefix doesn't match. public func tryDropSuffix( _ other: C ) -> SubSequence? where C.Element == Element { diff --git a/Sources/_RegexParser/Utility/MissingUnicode.swift b/Sources/_RegexParser/Utility/MissingUnicode.swift index 4d819806b..b1a4a07ff 100644 --- a/Sources/_RegexParser/Utility/MissingUnicode.swift +++ b/Sources/_RegexParser/Utility/MissingUnicode.swift @@ -12,13 +12,13 @@ // MARK: - Missing stdlib API extension Unicode { + // Note: The `Script` enum includes the "meta" script type "Katakana_Or_Hiragana", which + // isn't defined by https://www.unicode.org/Public/UCD/latest/ucd/Scripts.txt, + // but is defined by https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt. + // We may want to split it out, as it's the only case that is a union of + // other script types. + /// Character script types. - /// - /// Note this includes the "meta" script type "Katakana_Or_Hiragana", which - /// isn't defined by https://www.unicode.org/Public/UCD/latest/ucd/Scripts.txt, - /// but is defined by https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt. - /// We may want to split it out, as it's the only case that is a union of - /// other script types. @frozen public enum Script: String, Hashable { case adlam = "Adlam" @@ -254,7 +254,8 @@ extension Unicode { case spaceSeparator = "Zs" } - /// A list of unicode properties that can either be true or false. + /// A list of Unicode properties that can either be true or false. + /// /// https://www.unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt @frozen public enum BinaryProperty: String, Hashable { @@ -328,9 +329,10 @@ extension Unicode { } } +// TODO: These should become aliases for the Block (blk) Unicode character +// property. + /// Oniguruma properties that are not covered by Unicode spellings. -/// TODO: These should become aliases for the Block (blk) Unicode character -/// property. @frozen public enum OnigurumaSpecialProperty: String, Hashable { case inBasicLatin = "In_Basic_Latin" @@ -657,18 +659,24 @@ public enum OnigurumaSpecialProperty: String, Hashable { } extension Character { + /// Whether this character represents an octal (base 8) digit, + /// for the purposes of pattern parsing. public var isOctalDigit: Bool { ("0"..."7").contains(self) } + /// Whether this character represents a word character, + /// for the purposes of pattern parsing. public var isWordCharacter: Bool { isLetter || isNumber || self == "_" } - /// Whether this character represents whitespace for the purposes of pattern - /// parsing. + /// Whether this character represents whitespace, + /// for the purposes of pattern parsing. public var isPatternWhitespace: Bool { return unicodeScalars.first!.properties.isPatternWhitespace } } extension UnicodeScalar { + /// Whether this character represents a printable ASCII character, + /// for the purposes of pattern parsing. public var isPrintableASCII: Bool { // Exclude non-printables before the space character U+20, and anything // including and above the DEL character U+7F. diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift index 97d8c80dd..df121d8c5 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/Split.swift @@ -299,9 +299,10 @@ extension Collection where Element: Equatable { // FIXME: Return `some Collection` for SE-0346 /// Returns the longest possible subsequences of the collection, in order, /// around elements equal to the given separator. + /// /// - Parameter separator: The element to be split upon. /// - Returns: A collection of subsequences, split from this collection's - /// elements. + /// elements. @available(SwiftStdlib 5.7, *) public func split( separator: C, @@ -373,9 +374,10 @@ extension BidirectionalCollection where SubSequence == Substring { // FIXME: Return `some Collection` for SE-0346 /// Returns the longest possible subsequences of the collection, in order, /// around elements equal to the given separator. + /// /// - Parameter separator: A regex describing elements to be split upon. /// - Returns: A collection of substrings, split from this collection's - /// elements. + /// elements. @_disfavoredOverload public func split( separator: R, diff --git a/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift b/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift index 0dd91f360..2f45a734b 100644 --- a/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift +++ b/Sources/_StringProcessing/Algorithms/Algorithms/StartsWith.swift @@ -51,9 +51,10 @@ extension BidirectionalCollection where Element: Equatable { extension BidirectionalCollection where SubSequence == Substring { /// Returns a Boolean value indicating whether the initial elements of the /// sequence are the same as the elements in the specified regex. + /// /// - Parameter regex: A regex to compare to this sequence. /// - Returns: `true` if the initial elements of the sequence matches the - /// beginning of `regex`; otherwise, `false`. + /// beginning of `regex`; otherwise, `false`. public func starts(with regex: R) -> Bool { starts(with: RegexConsumer(regex)) } diff --git a/Sources/_StringProcessing/PrintAsPattern.swift b/Sources/_StringProcessing/PrintAsPattern.swift index 91626eb5c..ff85e38f1 100644 --- a/Sources/_StringProcessing/PrintAsPattern.swift +++ b/Sources/_StringProcessing/PrintAsPattern.swift @@ -19,7 +19,7 @@ @_spi(PatternConverter) extension AST { - /// Render as a Pattern DSL + /// Renders as a Pattern DSL. @_spi(PatternConverter) public func renderAsBuilderDSL( maxTopDownLevels: Int? = nil, diff --git a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift index 0d018aa81..3dbe9d84e 100644 --- a/Sources/_StringProcessing/Regex/AnyRegexOutput.swift +++ b/Sources/_StringProcessing/Regex/AnyRegexOutput.swift @@ -13,7 +13,9 @@ @available(SwiftStdlib 5.7, *) extension Regex where Output == AnyRegexOutput { - /// Parse and compile `pattern`, resulting in an existentially-typed capture list. + /// Parses and compiles a regular expression, resulting in an existentially-typed capture list. + /// + /// - Parameter pattern: The regular expression. public init(_ pattern: String) throws { self.init(ast: try parse(pattern, .traditional)) } @@ -21,7 +23,10 @@ extension Regex where Output == AnyRegexOutput { @available(SwiftStdlib 5.7, *) extension Regex { - /// Parse and compile `pattern`, resulting in a strongly-typed capture list. + /// Parses and compiles a regular expression. + /// + /// - Parameter pattern: The regular expression. + /// - Parameter as: The desired type for the output. public init( _ pattern: String, as: Output.Type = Output.self @@ -32,7 +37,7 @@ extension Regex { @available(SwiftStdlib 5.7, *) extension Regex.Match where Output == AnyRegexOutput { - // Ensures `.0` always refers to the whole match. + /// Accesses the whole match using the `.0` syntax. public subscript( dynamicMember keyPath: KeyPath<(Substring, _doNotUse: ()), Substring> ) -> Substring { @@ -44,7 +49,7 @@ extension Regex.Match where Output == AnyRegexOutput { } } -/// A type-erased regex output +/// A type-erased regex output. @available(SwiftStdlib 5.7, *) public struct AnyRegexOutput { let input: String @@ -67,7 +72,7 @@ extension AnyRegexOutput { /// Creates a type-erased regex output from an existing output. /// /// Use this initializer to fit a regex with strongly typed captures into the - /// use site of a dynamic regex, i.e. one that was created from a string. + /// use site of a dynamic regex, like one that was created from a string. public init(_ match: Regex.Match) { // Note: We use type equality instead of `match.output as? ...` to prevent // unexpected optional flattening. @@ -84,7 +89,7 @@ extension AnyRegexOutput { /// /// - Parameter type: The expected output type. /// - Returns: The output, if the underlying value can be converted to the - /// output type, or nil otherwise. + /// output type; otherwise `nil`. public func `as`(_ type: Output.Type) -> Output? { let elements = _elements.map { StructuredCapture( @@ -190,7 +195,7 @@ extension Regex.Match where Output == AnyRegexOutput { /// Creates a type-erased regex match from an existing match. /// /// Use this initializer to fit a regex match with strongly typed captures into the - /// use site of a dynamic regex match, i.e. one that was created from a string. + /// use site of a dynamic regex match, like one that was created from a string. public init(_ match: Regex.Match) { fatalError("FIXME: Not implemented") } @@ -199,8 +204,8 @@ extension Regex.Match where Output == AnyRegexOutput { /// types. /// /// - Parameter type: The expected output type. - /// - Returns: A match generic over the output type if the underlying values can be converted to the - /// output type. Returns `nil` otherwise. + /// - Returns: A match generic over the output type, if the underlying values + /// can be converted to the output type; otherwise, `nil`. public func `as`(_ type: Output.Type) -> Regex.Match? { fatalError("FIXME: Not implemented") } diff --git a/Sources/_StringProcessing/Regex/Core.swift b/Sources/_StringProcessing/Regex/Core.swift index 36d62f674..1f9a35dad 100644 --- a/Sources/_StringProcessing/Regex/Core.swift +++ b/Sources/_StringProcessing/Regex/Core.swift @@ -19,7 +19,7 @@ public protocol RegexComponent { var regex: Regex { get } } -/// A regex represents a string processing algorithm. +/// A regular expression. /// /// let regex = try Regex("a(.*)b") /// let match = "cbaxb".firstMatch(of: regex) diff --git a/Sources/_StringProcessing/Regex/DSLTree.swift b/Sources/_StringProcessing/Regex/DSLTree.swift index ce5beeaca..52eaeffb0 100644 --- a/Sources/_StringProcessing/Regex/DSLTree.swift +++ b/Sources/_StringProcessing/Regex/DSLTree.swift @@ -25,29 +25,29 @@ public struct DSLTree { extension DSLTree { @_spi(RegexBuilder) public indirect enum Node { - /// Try to match each node in order + /// Matches each node in order. /// /// ... | ... | ... case orderedChoice([Node]) - /// Match each node in sequence + /// Match each node in sequence. /// /// ... ... case concatenation([Node]) - /// Capture the result of a subpattern + /// Captures the result of a subpattern. /// /// (...), (?...) case capture( name: String? = nil, reference: ReferenceID? = nil, Node) - /// Match a (non-capturing) subpattern / group + /// Matches a noncapturing subpattern. case nonCapturingGroup(_AST.GroupKind, Node) // TODO: Consider splitting off grouped conditions, or have // our own kind - /// Match a choice of two nodes based on a condition + /// Matches a choice of two nodes, based on a condition. /// /// (?(cond) true-branch | false-branch) /// @@ -63,7 +63,7 @@ extension DSLTree { case atom(Atom) - /// Comments, non-semantic whitespace, etc + /// Comments, non-semantic whitespace, and so on. // TODO: Do we want this? Could be interesting case trivia(String) @@ -73,7 +73,7 @@ extension DSLTree { case quotedLiteral(String) - /// An embedded literal + /// An embedded literal. case regexLiteral(_AST.ASTNode) // TODO: What should we do here? diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index 45df7aeaa..dd36c8823 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -19,7 +19,7 @@ extension Regex { public struct Match { let input: String - /// The range of the overall match + /// The range of the overall match. public let range: Range let rawCaptures: [StructuredCapture] @@ -34,7 +34,7 @@ extension Regex { @available(SwiftStdlib 5.7, *) extension Regex.Match { - /// The produced output from the match operation + /// The output produced from the match operation. public var output: Output { if Output.self == AnyRegexOutput.self { let wholeMatchAsCapture = StructuredCapture( @@ -62,12 +62,12 @@ extension Regex.Match { } } - /// Lookup a capture by name or number + /// Accesses a capture by its name or number. public subscript(dynamicMember keyPath: KeyPath) -> T { output[keyPath: keyPath] } - // Allows `.0` when `Match` is not a tuple. + /// Accesses a capture using the `.0` syntax, even when the match isn't a tuple. @_disfavoredOverload public subscript( dynamicMember keyPath: KeyPath<(Output, _doNotUse: ()), Output> @@ -88,44 +88,50 @@ extension Regex.Match { @available(SwiftStdlib 5.7, *) extension Regex { - /// Match a string in its entirety. + /// Matches a string in its entirety. /// - /// Returns `nil` if no match and throws on abort + /// - Parameter s: The string to match this regular expression against. + /// - Returns: The match, or `nil` if no match was found. public func wholeMatch(in s: String) throws -> Regex.Match? { try _match(s, in: s.startIndex.. Regex.Match? { try _match(s, in: s.startIndex.. Regex.Match? { try _firstMatch(s, in: s.startIndex.. Regex.Match? { try _match(s.base, in: s.startIndex.. Regex.Match? { try _match(s.base, in: s.startIndex.. Regex.Match? { try _firstMatch(s.base, in: s.startIndex..( of r: R ) -> Regex.Match? { try? r.regex.wholeMatch(in: self[...].base) } - /// Match part of the regex, starting at the beginning. - /// - Parameter r: The regex to match against. - /// - Returns: The match if there is one, or `nil` if none. + /// Checks for a match against the string, starting at its beginning. + /// + /// - Parameter r: The regular expression being matched. + /// - Returns: The match, or `nil` if no match was found. public func prefixMatch( of r: R ) -> Regex.Match? { @@ -183,6 +191,7 @@ extension BidirectionalCollection where SubSequence == Substring { extension RegexComponent { public static func ~=(regex: Self, input: String) -> Bool { input.wholeMatch(of: regex) != nil + try? r.regex.wholeMatch(in: self) } public static func ~=(regex: Self, input: Substring) -> Bool { diff --git a/Sources/_StringProcessing/Regex/Options.swift b/Sources/_StringProcessing/Regex/Options.swift index cb0fe044e..24d5c422e 100644 --- a/Sources/_StringProcessing/Regex/Options.swift +++ b/Sources/_StringProcessing/Regex/Options.swift @@ -13,35 +13,57 @@ @available(SwiftStdlib 5.7, *) extension RegexComponent { - /// Returns a regular expression that ignores casing when matching. + /// Returns a regular expression that ignores case when matching. + /// + /// - Parameter ignoresCase: A Boolean value indicating whether to ignore case. + /// - Returns: The modified regular expression. public func ignoresCase(_ ignoresCase: Bool = true) -> Regex { wrapInOption(.caseInsensitive, addingIf: ignoresCase) } - /// Returns a regular expression that only matches ASCII characters as "word - /// characters". + /// Returns a regular expression that matches only ASCII characters as word + /// characters. + /// + /// - Parameter useASCII: A Boolean value indicating whether to match only + /// ASCII characters as word characters. + /// - Returns: The modified regular expression. public func asciiOnlyWordCharacters(_ useASCII: Bool = true) -> Regex { wrapInOption(.asciiOnlyWord, addingIf: useASCII) } - /// Returns a regular expression that only matches ASCII characters as digits. + /// Returns a regular expression that matches only ASCII characters as digits. + /// + /// - Parameter useasciiOnlyDigits: A Boolean value indicating whether to + /// match only ASCII characters as digits. + /// - Returns: The modified regular expression. public func asciiOnlyDigits(_ useASCII: Bool = true) -> Regex { wrapInOption(.asciiOnlyDigit, addingIf: useASCII) } - /// Returns a regular expression that only matches ASCII characters as space + /// Returns a regular expression that matches only ASCII characters as space /// characters. + /// + /// - Parameter asciiOnlyWhitespace: A Boolean value indicating whether to + /// match only ASCII characters as space characters. + /// - Returns: The modified regular expression. public func asciiOnlyWhitespace(_ useASCII: Bool = true) -> Regex { wrapInOption(.asciiOnlySpace, addingIf: useASCII) } - /// Returns a regular expression that only matches ASCII characters when + /// Returns a regular expression that matches only ASCII characters when /// matching character classes. + /// + /// - Parameter useASCII: A Boolean value indicating whether to match only + /// ASCII characters when matching character classes. + /// - Returns: The modified regular expression. public func asciiOnlyCharacterClasses(_ useASCII: Bool = true) -> Regex { wrapInOption(.asciiOnlyPOSIXProps, addingIf: useASCII) } /// Returns a regular expression that uses the specified word boundary algorithm. + /// + /// - Parameter wordBoundaryKind: The algorithm to use for determining word boundaries. + /// - Returns: The modified regular expression. public func wordBoundaryKind(_ wordBoundaryKind: RegexWordBoundaryKind) -> Regex { wrapInOption(.unicodeWordBoundaries, addingIf: wordBoundaryKind == .unicodeLevel2) } @@ -51,6 +73,7 @@ extension RegexComponent { /// /// - Parameter dotMatchesNewlines: A Boolean value indicating whether `.` /// should match a newline character. + /// - Returns: The modified regular expression. public func dotMatchesNewlines(_ dotMatchesNewlines: Bool = true) -> Regex { wrapInOption(.singleLine, addingIf: dotMatchesNewlines) } @@ -65,6 +88,7 @@ extension RegexComponent { /// /// - Parameter matchLineEndings: A Boolean value indicating whether `^` and /// `$` should match the start and end of lines, respectively. + /// - Returns: The modified regular expression. public func anchorsMatchLineEndings(_ matchLineEndings: Bool = true) -> Regex { wrapInOption(.multiline, addingIf: matchLineEndings) } @@ -124,6 +148,9 @@ extension RegexComponent { /// // Prints "true" /// print(decomposed.contains(queRegexScalar)) /// // Prints "false" + /// + /// - Parameter semanticLevel: The semantics to use during matching. + /// - Returns: The modified regular expression. public func matchingSemantics(_ semanticLevel: RegexSemanticLevel) -> Regex { switch semanticLevel.base { case .graphemeCluster: @@ -144,14 +171,18 @@ public struct RegexSemanticLevel: Hashable { internal var base: Representation - /// Match at the default semantic level of a string, where each matched - /// element is a `Character`. + /// Match at the character level. + /// + /// At this semantic level, each matched element is a `Character` value. + /// This is the default semantic level. public static var graphemeCluster: RegexSemanticLevel { .init(base: .graphemeCluster) } - /// Match at the semantic level of a string's `UnicodeScalarView`, where each - /// matched element is a `UnicodeScalar` value. + /// Match at the Unicode scalar level. + /// + /// At this semantic level, the string's `UnicodeScalarView` is used for matching, + /// and each matched element is a `UnicodeScalar` value. public static var unicodeScalar: RegexSemanticLevel { .init(base: .unicodeScalar) } diff --git a/Sources/_StringProcessing/_CharacterClassModel.swift b/Sources/_StringProcessing/_CharacterClassModel.swift index c02725e33..4d0c12c1f 100644 --- a/Sources/_StringProcessing/_CharacterClassModel.swift +++ b/Sources/_StringProcessing/_CharacterClassModel.swift @@ -139,23 +139,30 @@ public struct _CharacterClassModel: Hashable { return result } - /// Returns an inverted character class if true is passed, otherwise the - /// same character class is returned. - func withInversion(_ invertion: Bool) -> Self { + /// Conditionally inverts a character class. + /// + /// - Parameter inversion: Indicates whether to invert the character class. + /// - Returns: The inverted character class if `inversion` is `true`; + /// otherwise, the same character class. + func withInversion(_ inversion: Bool) -> Self { var copy = self - if invertion { + if inversion { copy.isInverted.toggle() } return copy } - /// Returns the inverse character class. + /// Inverts a character class. public var inverted: Self { return withInversion(true) } - /// Returns the end of the match of this character class in `str`, if - /// it matches. + /// Returns the end of the match of this character class in the string. + /// + /// - Parameter str: The string to match against. + /// - Parameter at: The index to start matching. + /// - Parameter options: Options for the match operation. + /// - Returns: The index of the end of the match, or `nil` if there is no match. func matches(in str: String, at i: String.Index, with options: MatchingOptions) -> String.Index? { switch matchLevel { case .graphemeCluster: From 96df14d0379acbe0fce937f39d7da690a3186faa Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Tue, 26 Apr 2022 13:28:17 -0700 Subject: [PATCH 2/4] Fix cut-off sentence. Co-authored-by: Nate Cook --- Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift b/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift index c06643aee..bf379fc14 100644 --- a/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift +++ b/Sources/_RegexParser/Regex/Printing/PrettyPrinter.swift @@ -57,7 +57,7 @@ extension PrettyPrinter { /// Outputs a string directly, without termination or /// indentation, and without updating any internal state. /// - /// This is the low-level interface to the pret + /// This is the low-level interface to the pretty printer. /// /// - Note: If `s` includes a newline, even at the end, /// this method does not update any tracking state. From 0e59bdf59b4b4d96381aeb6add164fdae31584ca Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Tue, 26 Apr 2022 20:45:30 -0600 Subject: [PATCH 3/4] Update Sources/_StringProcessing/Regex/Match.swift --- Sources/_StringProcessing/Regex/Match.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index dd36c8823..9937f1e03 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -191,7 +191,6 @@ extension String { extension RegexComponent { public static func ~=(regex: Self, input: String) -> Bool { input.wholeMatch(of: regex) != nil - try? r.regex.wholeMatch(in: self) } public static func ~=(regex: Self, input: Substring) -> Bool { From ac618f63eb2071703406c806f44ec63f57247f78 Mon Sep 17 00:00:00 2001 From: Alex Martini Date: Wed, 27 Apr 2022 11:08:27 -0700 Subject: [PATCH 4/4] Back out an accidental source change. Confirmed (using the command below) that this branch now contains only changes to doc comments, changes to // comments where content was moved into or out of a doc comment, and one spelling correction to code. % git diff origin/main... | grep -v '^+ *///\|- *///' | grep -v '^@@' | grep -v '^ ' | grep -v '^+++\|^---' | grep -v '^diff --git' | grep -v '^index ' + // Individual public API functions are in the generated Variadics.swift file. +// For now, we use String as the source while prototyping... + + // NOTE: Currently, this means we have raw quotes. + // Better would be to have real Swift string delimiter parsing logic. + + // NOTE: traditional comments are not nested. Currently, we are neither. + // Traditional comments can't have `)`, not even escaped in them either, we + // can. Traditional comments can have `*/` in them, we can't without + // escaping. We don't currently do escaping. + - // Finish, flush, and clear. Returns the rendered output + // Finish, flush, and clear. + // + // - Returns: The rendered output. + // Note: The `Script` enum includes the "meta" script type "Katakana_Or_Hiragana", which + // isn't defined by https://www.unicode.org/Public/UCD/latest/ucd/Scripts.txt, + // but is defined by https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt. + // We may want to split it out, as it's the only case that is a union of + // other script types. + +// TODO: These should become aliases for the Block (blk) Unicode character +// property. + - // Ensures `.0` always refers to the whole match. - // Allows `.0` when `Match` is not a tuple. - func withInversion(_ invertion: Bool) -> Self { + func withInversion(_ inversion: Bool) -> Self { - if invertion { + if inversion { --- Sources/_StringProcessing/Regex/Match.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/_StringProcessing/Regex/Match.swift b/Sources/_StringProcessing/Regex/Match.swift index 9937f1e03..8172e993b 100644 --- a/Sources/_StringProcessing/Regex/Match.swift +++ b/Sources/_StringProcessing/Regex/Match.swift @@ -165,7 +165,7 @@ extension Regex { } @available(SwiftStdlib 5.7, *) -extension String { +extension BidirectionalCollection where SubSequence == Substring { /// Checks for a match against the string in its entirety. /// /// - Parameter r: The regular expression being matched.