Skip to content

Reenable motivation tests #344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
130 changes: 111 additions & 19 deletions Tests/RegexBuilderTests/MotivationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@
// FIXME: macOS CI seems to be busted and Linux doesn't have FormatStyle
// So, we disable this file for now

#if false

import _MatchingEngine

import XCTest
import _StringProcessing

import RegexBuilder

#if os(macOS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, is this all that was needed this whole time? 😅

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welp, I guess not. Works on my machine! 🙃


private struct Transaction: Hashable {
enum Kind: Hashable {
case credit
Expand Down Expand Up @@ -140,17 +137,19 @@ private func processWithRuntimeDynamicRegex(
) -> Transaction? {
// FIXME: Shouldn't this init throw?
let regex = try! Regex(pattern)
let dateStrat = Date.FormatStyle(date: .numeric).parseStrategy

guard let result = line.wholeMatch(of: regex)?.output,
let kind = Transaction.Kind(result[1].substring!),
let date = try? Date(String(result[2].substring!), strategy: dateStrat),
let account = result[3].substring.map(String.init),
let amount = try? Decimal(
String(result[4].substring!), format: .currency(code: "USD")) else {
return nil
}

// guard let result = line.match(regex) else { return nil }
//
// // TODO: We should have Regex<DynamicCaptures> or somesuch and `.1`
// // should be the same as `\1`.
// let dynCaps = result.1
//
//
// let kind = Transaction.Kind(result.1.first!.capture as Substring)

return nil
return Transaction(
kind: kind, date: date, account: account, amount: amount)
}

@available(macOS 12.0, *)
Expand Down Expand Up @@ -239,7 +238,8 @@ extension RegexDSLTests {
XCTAssertEqual(
referenceOutput, processWithNSRegularExpression(line))

_ = processWithRuntimeDynamicRegex(line)
XCTAssertEqual(
referenceOutput, processWithRuntimeDynamicRegex(line))

// Static run-time regex
XCTAssertEqual(
Expand All @@ -256,12 +256,104 @@ extension RegexDSLTests {
XCTFail()
continue
}

}

}

}

#endif

extension RegexDSLTests {
func testProposalExample() {
let statement = """
CREDIT 04062020 PayPal transfer $4.99
CREDIT 04032020 Payroll $69.73
DEBIT 04022020 ACH transfer $38.25
DEBIT 03242020 IRS tax payment $52249.98
"""
let expectation: [(TransactionKind, Date, Substring, Double)] = [
(.credit, Date(mmddyyyy: "04062020")!, "PayPal transfer", 4.99),
(.credit, Date(mmddyyyy: "04032020")!, "Payroll", 69.73),
(.debit, Date(mmddyyyy: "04022020")!, "ACH transfer", 38.25),
(.debit, Date(mmddyyyy: "03242020")!, "IRS tax payment", 52249.98),
]

enum TransactionKind: String {
case credit = "CREDIT"
case debit = "DEBIT"
}

struct Date: Hashable {
var month: Int
var day: Int
var year: Int

init?(mmddyyyy: String) {
guard let (_, m, d, y) = mmddyyyy.wholeMatch(of: Regex {
Capture(Repeat(.digit, count: 2), transform: { Int($0)! })
Capture(Repeat(.digit, count: 2), transform: { Int($0)! })
Capture(Repeat(.digit, count: 4), transform: { Int($0)! })
})?.output else {
return nil
}

self.month = m
self.day = d
self.year = y
}
}

let statementRegex = Regex {
// First, lets capture the transaction kind by wrapping our ChoiceOf in a
// TryCapture because we want
TryCapture {
ChoiceOf {
"CREDIT"
"DEBIT"
}
} transform: {
TransactionKind(rawValue: String($0))
}

OneOrMore(.whitespace)

// Next, lets represent our date as 3 separate repeat quantifiers. The first
// two will require 2 digit characters, and the last will require 4. Then
// we'll take the entire substring and try to parse a date out.
TryCapture {
Repeat(.digit, count: 2)
Repeat(.digit, count: 2)
Repeat(.digit, count: 4)
} transform: {
Date(mmddyyyy: String($0))
}

OneOrMore(.whitespace)

// Next, grab the description which can be any combination of word characters,
// digits, etc.
Capture {
OneOrMore(.any, .reluctant)
}

OneOrMore(.whitespace)

"$"

// Finally, we'll grab one or more digits which will represent the whole
// dollars, match the decimal point, and finally get 2 digits which will be
// our cents.
TryCapture {
OneOrMore(.digit)
"."
Repeat(.digit, count: 2)
} transform: {
Double($0)
}
}

for (i, match) in statement.matches(of: statementRegex).enumerated() {
let (_, kind, date, description, amount) = match.output
XCTAssert((kind, date, description, amount) == expectation[i])
}
}
}
32 changes: 32 additions & 0 deletions Tests/RegexBuilderTests/RegexDSLTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,38 @@ class RegexDSLTests: XCTestCase {
XCTAssertEqual(result[b], 42)
}

do {
let key = Reference(Substring.self)
let value = Reference(Int.self)
let input = " "
let regex = Regex {
Capture(as: key) {
Optionally {
OneOrMore(.word)
}
}
":"
Optionally {
Capture(as: value) {
OneOrMore(.digit)
} transform: { Int($0)! }
}
}

let result1 = try XCTUnwrap("age:123".wholeMatch(of: regex))
XCTAssertEqual(result1[key], "age")
XCTAssertEqual(result1[value], 123)

let result2 = try XCTUnwrap(":567".wholeMatch(of: regex))
XCTAssertEqual(result2[key], "")
XCTAssertEqual(result2[value], 567)

let result3 = try XCTUnwrap("status:".wholeMatch(of: regex))
XCTAssertEqual(result3[key], "status")
// Traps:
// XCTAssertEqual(result3[value], nil)
}

// Post-hoc captured references
// #"(?:\w\1|:(\w):)+"#
try _testDSLCaptures(
Expand Down