<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Returning to the &quot;troubling&quot; issue, I looked at ACE&#39;s repp implementation and saw that my second guess of the behavior&#39;s cause was correct: it is not calling groups iteratively (except internal, iterative groups, as it should), but it is doing global substitution with multiple regex calls. If it finds a match, it performs the substitution and then continues matching from the next position on the transformed string. If the substitution replaces the match with nothing, it matches again from the same position. Normally this is fine but because it is a separate regex call it will even match anchors like ^ on the successive calls. ACE&#39;s implementation uses Boost.Regex, as does Bec&#39;s C++ implementation, and I suspect they are doing the same thing in these situations.<br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">A fix would be to continue matching on the original string while constructing a separate transformed string. After the rule has been fully applied, the original string can be replaced with the fully transformed one.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Even though the fix would alter our underlying tokenization, this seems to only affect one sentence in the ERG&#39;s gold profiles.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Nov 26, 2019 at 12:24 PM <a href="mailto:goodman.m.w@gmail.com">goodman.m.w@gmail.com</a> &lt;<a href="mailto:goodman.m.w@gmail.com">goodman.m.w@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">It turns out my second issue regarding group-local inline flags (e.g., (?i)) was not as trivial as I expected. By using a 3rd party regex library with better support for these advanced features I was able to easily resolve this issue, but it introduced another one: unescaped brackets in character classes are treated as nested sets. In fact I&#39;d already encountered this situation and created an issue for the ERG a few months ago: <a href="https://github.com/delph-in/erg/issues/17" target="_blank">https://github.com/delph-in/erg/issues/17</a>.</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">For now I&#39;ve sidestepped the issue by backing off to the old behavior if there&#39;s an error that is plausibly caused by unescaped brackets, and now I only get a diff for 1 item compared to the REPP standalone tool. The remaining error is the one described in the previous message. But, as you said, PyDelphin might be doing the right thing for that case.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Nov 25, 2019 at 11:59 PM <a href="mailto:goodman.m.w@gmail.com" target="_blank">goodman.m.w@gmail.com</a> &lt;<a href="mailto:goodman.m.w@gmail.com" target="_blank">goodman.m.w@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Hi Stephan and all,</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Nov 25, 2019 at 9:13 PM Stephan Oepen &lt;<a href="mailto:oe@ifi.uio.no" target="_blank">oe@ifi.uio.no</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
also, i am happy to confirm that leaving out the LKB from this comparison is justified, as its implementation of recovering character ranges after all rule applications are complete predates the work by bec (and myself) and is known to give invalid results in some cases.<br></div></blockquote><div><br></div><div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">Thanks for confirming. I have compared the LKB&#39;s implementation in the past, but this time I was short on time and/or being lazy.<br></div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
<br>
in sum, i would look to the REPP standalone tool as the closest we currently have to a reference implementation.  it uses the approach of explicitly keeping track of sub-string correspondences for each rule application, as described here:<br>
<br>
<a href="https://www.aclweb.org/anthology/P12-2074/" rel="noreferrer" target="_blank">https://www.aclweb.org/anthology/P12-2074/</a></div></blockquote><div><br></div><div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">Yes, I referred heavily to this paper as well as ReppTop and to the outputs of the various systems when I wrote my version. I took some notes along the way which I&#39;ve been meaning to migrate to the wiki, but for now I&#39;ve just put them up here: <a href="https://gist.github.com/goodmami/16d907bc2a0e4408456ff596e1e263e6" target="_blank">https://gist.github.com/goodmami/16d907bc2a0e4408456ff596e1e263e6</a>. These notes include details of characterization as well as comparisons of 4 systems (LKB, ACE, PET/standalone, and PyDelphin; I could not easily test agree but I welcome any information to fill in my comparison).<br></div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><br>
<br>
&gt; The third one is more troubling, because it appears that ACE and REPP both apply external group calls iteratively even though the ReppTop wiki is clear that they are should not be iterative. If someone can confirm that the wiki is incorrect, [...]<br>
<br>
this observation is surprising and potentially troubling to me!  the wiki page is in fact correct: unlike internal group calls, external calls should not in and of themselves be iterative; that would unnecessarily lump together two aspects of the REPP specification and potentially constrain modularity, viz. in a scenario where one would like to split out a rule group into an external module (e.g. to be able to parametrically turn it on or off) but does not want iteration over these rules.  if one in fact wants both, it is trivial to wrap an internal iterative group around the external module.<br></div></blockquote><div><br></div><div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">Ok, we agree on the ideal behavior here. I just tried creating a MWE (minimal working example) with nothing but the external with a single rule and the tokenization pattern (see comments here: <a href="https://github.com/delph-in/pydelphin/issues/254" target="_blank">https://github.com/delph-in/pydelphin/issues/254</a>).  Based on my tests with this setup, it now appears that the difference is *not* iterative application but rather a difference in how PyDelphin and the others do global substitutions. The pattern /^ *[:*#]+/ has the ^ anchor, so it should only match the first instance. Perl (which I assume uses PCRE) shows this is the case as well:</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">With ^ anchor:</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">$ echo &#39; # # foo&#39; | perl -e &#39;while (&lt;&gt;) { s/^ *[:*#]+//g; print }&#39;<br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"> # foo</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">Without ^ anchor:<br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">$ echo &#39; # # foo&#39; | perl -e &#39;while (&lt;&gt;) { s/ *[:*#]+//g; print }&#39;<br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"> foo</div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default"><br></div><div style="font-family:arial,helvetica,sans-serif" class="gmail_default">So now I&#39;m wondering how REPP and ACE do global substitutions. PyDelphin gets all matches on a line with a single call to the regex engine, so ^ is only matched once, but if it were to instead get a single match at a time (matching successively starting at the end-position of the previous substitution), then it could match ^ on those successive calls. Perhaps this is what the other tools are doing?<br></div></div></div><br>-- <br><div dir="ltr">-Michael Wayne Goodman</div></div>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr">-Michael Wayne Goodman</div>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr" class="gmail_signature">-Michael Wayne Goodman</div>