quasilyte / phpgrep

Syntax-aware grep for PHP code.
MIT License
236 stars 10 forks source link

Patterns that don't always work without a proper backtracking support in matcher #42

Closed quasilyte closed 3 years ago

quasilyte commented 4 years ago

All cases below where the pattern doesn't match when it should are a result of no backtracking support inside the matcher.

The ${"*"} node stops when no more nodes are left inside the block or when the next pattern node can be matched instead. If we fail a match after that, we never try to continue from the last ${"*"} to see if we can stop at a different point and accept the match.

Backtracking would make matching slower, but some (how many?) cases where we need it can be determined during the pattern compile time. For the block that doesn't require it we can generate a non-backtracking node kind.

Some examples that yield the unexpected results:

<?php

f(${"*"}, $_)
// matches f(1)
// doesn't match f(1, 2)
// doesn't match f(1, 2, 3)
//
// Potential solution: generate "ends-with" pattern for this case,
// check that the last node matches, ignore everything before it.

f(${"*"}, 1, 1, ${"*"})
// matches f(1, 1, 1)
// doesn't match f(1, 1)
// doesn't match f(0, 1, 0, 1, 1, 0)
//
// Either implement backtracking or reject such patterns during the compile time.

global ${"*"}, $x, $x
// matches global $a, $a
// doesn't match global $a, $b, $b
quasilyte commented 3 years ago

63