-
Notifications
You must be signed in to change notification settings - Fork 50
Add assertions to the DSL #154
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
Conversation
case .startOfSubject: fatalError("Not yet supported") | ||
case .endOfSubjectBeforeNewline: fatalError("Not yet supported") | ||
case .endOfSubject: fatalError("Not yet supported") | ||
case .firstMatchingPositionInSubject: fatalError("Not yet supported") | ||
case .textSegmentBoundary: return .notTextSegment | ||
case .startOfLine: fatalError("Not yet supported") | ||
case .endOfLine: fatalError("Not yet supported") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't currently have a representation for these negated assertions in the AST, since things like notWordBoundary
are represented as specific individual cases. These fatalError
'd cases don't have a regex literal equivalent, but would be available if we use an API like Assertion.wordBoundary.inverted
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we going to an AST here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DSLTree
tracks assertions using AST.Atom.AssertionKind
right now.
case endOfLine | ||
case wordBoundary | ||
case lookahead(DSLTree.Node) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this meant to be a listing of built-in assertions, or are each of these the kinds of assertions someone could write?
case .startOfSubject: fatalError("Not yet supported") | ||
case .endOfSubjectBeforeNewline: fatalError("Not yet supported") | ||
case .endOfSubject: fatalError("Not yet supported") | ||
case .firstMatchingPositionInSubject: fatalError("Not yet supported") | ||
case .textSegmentBoundary: return .notTextSegment | ||
case .startOfLine: fatalError("Not yet supported") | ||
case .endOfLine: fatalError("Not yet supported") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we going to an AST here?
Tests/RegexTests/RegexDSLTests.swift
Outdated
("aaaaabc", nil), | ||
captureType: Substring.self, ==) | ||
{ | ||
Assertion.startOfLine |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many of the built-in ones are more commonly called "anchors", which might be worth considering too.
`lookahead` is moved to a free function, since it isn't an anchor like the others
22e5194
to
f629a4a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
var result = self | ||
result.isInverted.toggle() | ||
return result | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we want an isInverted
then? Also, is it the case that all anchors can be inverted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know that a property makes sense if we aren't going to also expose kind
as public API, and the purpose of this is just to carry the regex
wrapper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything in this PR can be inverted, just need a little more plumbing. If we want to provide the functionality of a "reset match" assertion, that could just be a separate function or type, since it isn't an anchor anyway.
@swift-ci Please test Linux platform |
} | ||
|
||
public func lookahead<R: RegexProtocol>( | ||
isNegative: Bool = false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While generally Boolean properties should read like an assertion about the receiver, I'm not sure it's quite as useful for function parameters. In this case, isNegative
is not forming a phrase with the base name to produce Boolean result, but a dictation by the caller to modify the behavior of the callee. As such, I wonder if we should call it negative
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, this is like the second parameter in split(separator: "-", omittingEmptySubsequences: false)
. 👍🏻
@swift-ci Please test Linux platform |
@swift-ci Please test Linux platform |
This adds an
Anchor
type that handles the different kinds of assertions supported by regular expression literals. Some spelling are different — instead of separate\w
and\W
assertions, this design provides justAnchor.wordBoundary
as well as aninverted
property that is available on all assertions. (This property should perhaps be namednegated
instead.) That is,\W
in a regex literal maps toAnchor.wordBoundary.inverted
.A
lookahead(isNegative:)
function provides the positive/negative lookahead functionality from regex literals.