prefix match of a regex and optimized dirEntries for regex search

Timothee Cour via Digitalmars-d digitalmars-d at puremagic.com
Thu Jun 19 00:36:45 PDT 2014


On Wed, Jun 18, 2014 at 12:37 PM, Dmitry Olshansky via Digitalmars-d <
digitalmars-d at puremagic.com> wrote:

> 18-Jun-2014 21:38, Timothee Cour via Digitalmars-d пишет:
>
>  I made a simple modification to std.regex to allow an option to prefix
>> match a regex.
>> Formally, if L(R) is the language recognized by a regex R, the language
>> recognized by prefix matching of R  is:
>>
>> L(p(R)) = prefix(L(R)) = {u : uv in L(R) for some v}
>> Trying to come up (by hand or algorithmically) with a regex R' such that
>> L(R') L(p(R)) is awkward and inefficient, eg:
>>
>>  So essentially it's just a set of all partial matches?


Not sure, that depends on your definition of partial matches; how do you
formally define partial matches?

There's a subtlety, let's call my proposal prefixMatch:
"hel".prefixMatch("^hello") //true
"".prefixMatch("^hello") //true
"mel".prefixMatch("^hello") //false

But if the regex doesn't start with `^` then it is not useful:

"whatever".prefixMatch("hello") //true
because the scanner will try each position in the input string and fail,
except for the last one where it'll succeed trivially ("" is a prefix of
"hello").

In other words, this is more useful for one shot matching.

But we can also consider partial partial matches if we provide additional
constraints given via a lambda:

"blabla hel blabla".partialMatch!(a=>a.hit.length>=3) ("hello")
=> finds a match ("hel") because the lambda succeeds on this match.

partialMatch could also be used to find the longest partial match (either
in terms of length of matching string or length of the regex):

auto longestPartialMatch(R)(string input, R regex){
string longest;
while(true){
auto m=partialMatch!(a=>a.hit.length>longest.length) (input,regex);
if(m) longest=a.hit; else return longest;
}

This could be useful for debugging complex regex to see why it didn't
capture a given string for example.



>  R='hello';
>> R'=`|h|he|hell|hello` = `(h(e(l(l(o)?)?)?)?)?`;
>>
>> However thinking in terms of state machine this is much easier and
>> efficient.
>>
>> It looks like this:
>> assert("hel".match(`hello\d+`.regex("p")); //p for prefix match
>>
>>
> Well, since "p" would apply to operation rather then regex I think adding
> a partialMatch function would be simpler.
>

> Plus it may need to return extended information like where in the pattern
> it stopped, so the return type/API may need to be different from normal
> match.


 Good point, I agree.


>
>  If there's interest in adding this I can prepare a pull request and we
>> can discuss more.
>>
>>  Sure partial matching wold be nice to have and any help in this
> direction is warmly welcome.
>

ok, I wanted to make sure there was interest.


>
> Would be cool if you could take a look at
> https://github.com/D-Programming-Language/phobos/pull/2216
>
> It's nothing special except splitting up std.regex into a package but it's
> a stepping stone of going forward with it.


That's a very welcome change, this module is too big currently. That seems
like it would be the 1st phobos module to take advantage of package
feature?


>
>
>  Example use case:
>> I wrote a function to search a file given a regex, and it is optimized
>> to prune directories early on if they fail to prefix match the regex, eg:
>>
>
> I'm not sure I follow - a normal regex match would do essentially the same
> by first checking the prefix and failing on wrong ones. Where is
> optimization?
>
>
The optimization is avoiding unnecessary file system access by pruning
early on directories that we can prove will not contain any file which will
match the regex. Without optimization, you have to consider (and reject)
`abc/bad_subfolder/file_1`. With optimization, you never have to consider
that file (nor ask the file system to list it), as `abc/bad_subfolder/`
fails the prefix regex test (see my example). A normal regex needs to be
applied to the whole path, and you need prefix matching to reject partial
paths (ie, directories).



> What could be interesting is to limit matching to not go beyond say 80
> code units and report if it's (partial) match of given pattern.


That'd be nice; it needs to be as generic as possible; I propose using a
user defined lambda (see above).


>
> --
> Dmitry Olshansky
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20140619/d5ba80c0/attachment-0001.html>


More information about the Digitalmars-d mailing list