%<> assignment with mode modifier (?J) erroneously point to the last group

Posted by Kahenraz on Sat 14 Apr 2018 08:16 AM — 4 posts, 18,257 views.

#0
This is regarding PCRE regular expression matching and has to do with an incorrect result being assigned to the matching %<> that is passed along to a script; Lua in my case.

Regex:

(?J)^(You poke (?P<thing>.+)|You prod (?P<thing>.+))$


Trigger:

<triggers>
  <trigger
   enabled="y"
   keep_evaluating="y"
   match="(?J)^(You poke (?P&lt;thing&gt;.+)|You prod (?P&lt;thing&gt;.+))$"
   regexp="y"
   send_to="12"
  >
  <send>
    print("Thing -- " .. "%&lt;thing&gt;")
  </send>
  </trigger>
</triggers>


Test:

You poke a rock
You prod a rock


Result:

You poke a rock
Thing -- 
You prod a rock
Thing -- a rock


The expected result is for "thing" to be "a rock" for both poking and prodding.

The problem is that the value assigned to %<thing> is always the last group which may not have a value for the named group as it wasn't a match. This can be demonstrated by swapping the order of the logical expression:

(?J)^(You prod (?P<thing>.+)|You poke (?P<thing>.+))$


I can confirm that the PCRE library which MUSH uses does handle this expression correctly:

Regex = "(?J)^(You poke (?P<thing>.+)|You prod (?P<thing>.+))$"
Regex = rex.new(Regex)

_, _, Table = Regex:match("You poke a rock")
print(Table[2])
print(Table[3])
print()

Regex = "(?J)^(You prod (?P<thing>.+)|You poke (?P<thing>.+))$"
Regex = rex.new(Regex)

_, _, Table = Regex:match("You poke a rock")
print(Table[2])
print(Table[3])


Result:

a rock
false

false
a rock


This is most likely due to an error in handling the result from the match when Mush assigns values to its special %<> variables.
Australia Forum Administrator #1
I am somewhat astounded at this, because this feature was added in version 4.06 on 26 Apr 2007 and would have been tested to make sure it works. There was a bugfix on 7 May 2007 related to using the same name in multiple places. This would necessarily have required testing to ensure it worked properly.

I can only assume that in one of the upgrades to the PCRE code in the last 11 years they changed the way the duplicate named groups works, a change that wasn't noticed by anyone, including me.

I have pushed a change to the code which seems to fix it, although I am not 100% confident. Perhaps you can test it and let me know.

Get the pre-release version and see what happens.

http://www.gammon.com.au/forum/?id=13903
#2
I think this broke something. Testing with release #f99ffb2.

Regex:

^You poke at (?P<thing>.+) with (?P<with>.+)$


Script:

print("Thing: %<thing>")
print("With: %<with>")


Copy/Paste:

<triggers>
  <trigger
   enabled="y"
   group="-- TEST"
   match="^You poke at (?P&lt;thing&gt;.+) with (?P&lt;with&gt;.+)$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>print("Thing: %&lt;thing&gt;")
print("With: %&lt;with&gt;")
</send>
  </trigger>
</triggers>


Test:

You poke at a rock with a stick


Expected output:

Thing: a rock
With: a stick


Actual output:

Thing: a stick
With: a stick
Amended on Mon 16 Apr 2018 12:34 AM by Kahenraz
Australia Forum Administrator #3
Try the latest pre-release now.