Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/Test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set Swift version
if: matrix.os == 'ubuntu-18.04'
run: echo "5.3-DEVELOPMENT-SNAPSHOT-2020-08-08-a" > .swift-version
- name: Install Swift
uses: YOCKOW/Action-setup-swift@master
- name: Build
Expand Down
2 changes: 1 addition & 1 deletion .swift-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.2.4
5.3
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@
<key>baselineIntegrationDisplayName</key>
<string>7 May 2020 at 21:25:02</string>
</dict>
<key>com.apple.dt.XCTMetric_CPU.instructions_retired</key>
<dict>
<key>baselineAverage</key>
<real>3.9872e+06</real>
<key>baselineIntegrationDisplayName</key>
<string>Local Baseline</string>
</dict>
</dict>
<key>testOneOrMore()</key>
<dict>
Expand Down
48 changes: 41 additions & 7 deletions Sources/Patterns/Atomic Patterns/Line.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,46 @@
// Created by Kåre Morstøl on 25/05/2020.
//

public protocol CharacterLike: Hashable {
var isNewline: Bool { get }
}

extension Character: CharacterLike {}
extension String.UTF8View.Element: CharacterLike {
@inlinable
public var isNewline: Bool {
// “\n” (U+000A): LINE FEED (LF), U+000B: LINE TABULATION (VT), U+000C: FORM FEED (FF), “\r” (U+000D): CARRIAGE RETURN (CR)
self < 14 && self > 9
}
}

// U+0085: NEXT LINE (NEL), U+2028: LINE SEPARATOR, U+2029: PARAGRAPH SEPARATOR
@usableFromInline
let newlines = Set([0x000A as UInt16, 0x000B, 0x000C, 0x000D, 0x0085, 0x2028, 0x2029].map { Unicode.Scalar($0)! })

extension String.UnicodeScalarView.Element: CharacterLike {
@inlinable
public var isNewline: Bool {
newlines.contains(self)
}
}

extension String.UTF16View.Element: CharacterLike {
@inlinable
public var isNewline: Bool {
Unicode.Scalar(self).map(newlines.contains(_:)) ?? false
}
}

/// Matches one line, not including newline characters.
public struct Line: Pattern {
public struct Line<Input: BidirectionalCollection>: Pattern
where Input.Element: CharacterLike, Input.Index == String.Index {
public init() {}

public var description: String { "Line()" }

public static let start = Start()
public static let end = End()

@inlinable
public func createInstructions(_ instructions: inout Instructions) throws {
public func createInstructions(_ instructions: inout ContiguousArray<Instruction<Input>>) throws {
try (Start() • Skip() • End()).createInstructions(&instructions)
}

Expand All @@ -31,7 +60,7 @@ public struct Line: Pattern {
}

@inlinable
public func createInstructions(_ instructions: inout Instructions) {
public func createInstructions(_ instructions: inout ContiguousArray<Instruction<Input>>) {
instructions.append(.checkIndex(self.parse(_:at:)))
}
}
Expand All @@ -48,8 +77,13 @@ public struct Line: Pattern {
}

@inlinable
public func createInstructions(_ instructions: inout Instructions) {
public func createInstructions(_ instructions: inout ContiguousArray<Instruction<Input>>) {
instructions.append(.checkIndex(self.parse(_:at:)))
}
}
}

extension Line where Input == String {
public static let start = Start()
public static let end = End()
}
57 changes: 49 additions & 8 deletions Sources/Patterns/Atomic Patterns/Literal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,75 @@ import Foundation
/// Matches a sequence of elements.
///
/// If empty, it will always succeed without consuming any input.
public struct Literal: Pattern {
public struct Literal<Input: BidirectionalCollection>: Pattern where Input.Element: Hashable {
public let elements: Input

public var description: String {
#""\#(String(elements).replacingOccurrences(of: "\n", with: "\\n"))""#
#""\#(String(describing: elements).replacingOccurrences(of: "\n", with: "\\n"))""#
}

@inlinable
public init(_ input: Input) {
elements = input
}

/// Matches `sequence`.
@inlinable
public init<S: Sequence>(_ sequence: S) where S.Element == Pattern.Input.Element {
self.elements = Pattern.Input(sequence)
public init<S: Sequence>(_ sequence: S) where S.Element == Input.Element, Input == String {
self.elements = Input(sequence)
}

@inlinable
public func createInstructions(_ instructions: inout ContiguousArray<Instruction<Input>>) {
instructions.append(contentsOf: elements.map(Instruction<Input>.elementEquals))
}
}

extension Literal where Input == String {
/// Matches this character.
@inlinable
public init(_ character: Character) {
self.init(String(character))
}
}

// MARK: Create from string literal.

extension Literal: ExpressibleByUnicodeScalarLiteral where Input: LosslessStringConvertible {
@inlinable
public func createInstructions(_ instructions: inout Instructions) {
instructions.append(contentsOf: elements.map(Instruction.elementEquals))
public init(unicodeScalarLiteral value: StaticString) {
elements = Input(String(describing: value))!
}
}

extension Literal: ExpressibleByStringLiteral {
extension Literal: ExpressibleByExtendedGraphemeClusterLiteral where Input: LosslessStringConvertible {
public typealias ExtendedGraphemeClusterLiteralType = StaticString
}

extension Literal: ExpressibleByStringLiteral where Input: LosslessStringConvertible {
@inlinable
public init(stringLiteral value: StaticString) {
self.init(String(describing: value))
elements = Input(String(describing: value))!
}
}

extension String.UTF8View: LosslessStringConvertible {
@inlinable
public init?(_ description: String) {
self = description.utf8
}
}

extension String.UTF16View: LosslessStringConvertible {
@inlinable
public init?(_ description: String) {
self = description.utf16
}
}

extension String.UnicodeScalarView: LosslessStringConvertible {
@inlinable
public init?(_ description: String) {
self = description.unicodeScalars
}
}
Loading