<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Cut points in PEG</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Extended Abstract</string-name>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Roman R. Redziejowski</string-name>
          <email>roman.redz@swipnet.se</email>
        </contrib>
      </contrib-group>
      <abstract>
        <p>This is a short note inspired by some ideas and results from [3, 6-8]. It is about Parsing Expression Grammars (PEGs) introduced by Ford in [1]. PEG specifies a language by defining for it a parser with limited backtracking. All of the quoted papers contain a detailed introduction to PEG, so it is not repeated here. Backtracking means that if e1 in a choice expression e1=e2 fails, the parser returns to the position it had before the attempt at e1, and tries e2 on the same input. Limited backtracking means that once e1 succeeded, e2 will not be tried on the same input upon a subsequent failure. In some cases, a failure of e1 may mean that e2 is also bound to fail, so there is no need to try it; one can terminate e1=e2 straight away and return failure. As an example, consider this grammar:</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>Introduction</title>
      <p>S = E $
E = T +E / T
T = a / b</p>
      <p>E = T # + " E / T
Suppose that at some point during the parse of S, expression E is applied to
input w. It starts by calling T. Clearly, if T fails, w does not start with a or b,
so the second alternative, being the same T, must also fail. Suppose now that
T + succeeds, after which E fails. One can easily see that the only thing that
can follow E in the parse of S is $. Thus, applying the second alternative to w
will result in a successful parse only if w = a$ or w = b$. But T + succeeding
on w means that w is none of these. So, trying the second alternative will not
result in a successful parse.</p>
      <p>We have identified two points in the expression for E, indicated below by #
and ", such that you do not need to backtrack if you fail before # or after ".</p>
      <sec id="sec-1-1">
        <title>We shall refer to them as ”cut points”.</title>
        <p>Thanks to the backtracking being limited, one can use the so-called ”packrat”
technology to run the PEG parser in a linear time. The technology consists in
saving all results to be reused in the case of backtracking. It means buying speed
at the cost of large memory consumption.</p>
        <p>Mizushima et al. [6] noted that after passing a " cut point, one can discard
the saved results that would be needed by e2. In this way, one can greatly reduce
the memory requirement.</p>
        <p>In a recent paper [3], Maidl et al. discuss the way in which a PEG parser
may provide meaningful information on why it failed to parse a given input. The
traditional way is to report the failure that occurred farthest down in the input.
But, some failures may be quite innocent, such as a failure of e1 in e1=e2 that is
followed by a success of e2. In section 5 of [3], the authors present an extension
to PEG to help reporting ”real” failures. Its use suggests that a ”real” failure
is one occurring in the ”no return” zone, such as before # and after " in the
example above.
2</p>
      </sec>
    </sec>
    <sec id="sec-2">
      <title>Finding cut points</title>
      <p>As follows from the above, i is interesting to find cut points in a given grammar.
To see how this can be done, we consider a minimal grammar without
iteration and predicates as used in [7, 8]. It has starting symbol S and end-of-input
marker $. As in [7, 8], we denote by Tail(e) the set of all terminated strings that
can follow an application of e in a parse starting with S. For convenience, we
consider choice expressions of the form e0 e1=e2 that can be easily desugared to
the primitive form used in [7, 8]. The input alphabet is denoted by .</p>
      <p>The grammar may be alternatively interpreted as a grammar in Backus-Naur
Form (BNF), with "/" denoting the unordered choice. We denote by L(e) the
language defined by e when interpreted as BNF.</p>
      <p>The following has been shown in [5] (the proof is found also in [4, 7, 8]):
Proposition 1. If expression e succeeds on input w, it consumes a string
belonging to L(e), meaning that w 2 L(e) ∗.</p>
      <p>
        To say something about w in case of failing e requires that each sequence
expression e1e2 satisfies this condition:
8x;y xy 2 L(e1e2) ∗ ^ x 2 L(e1) ) y 2 L(e2) ∗:
(
        <xref ref-type="bibr" rid="ref1">1</xref>
        )
Using the formal method from [4, 5, 7, 8] one can verify the following:
Proposition 2. In a grammar satisfying (
        <xref ref-type="bibr" rid="ref1">1</xref>
        ), if expression e fails on input w
then w 2= L(e) ∗.
      </p>
      <sec id="sec-2-1">
        <title>Using Proposition 1 one can verify:</title>
        <p>Proposition 3. A sufficient condition for " after e0 in A = e0 e1=e2 is:</p>
        <p>L(e0) ∗ \ L(e2) Tail(A) = ∅:</p>
      </sec>
      <sec id="sec-2-2">
        <title>Using Propositions 1 and 2 one can verify:</title>
        <p>
          Proposition 4. A sufficient condition for # after e0 in e0 e1=e2 in a grammar
satisfying (
          <xref ref-type="bibr" rid="ref1">1</xref>
          ) is:
        </p>
        <p>
          L(e0) ∗:
(
          <xref ref-type="bibr" rid="ref2">2</xref>
          )
        </p>
      </sec>
    </sec>
    <sec id="sec-3">
      <title>Using rst expressions</title>
      <p>
        As the inclusion and emptiness of intersection of context-free languages are in
general undecidable, there is no mechanical way to to represent a given expression
as e0 e1 satisfying (
        <xref ref-type="bibr" rid="ref2">2</xref>
        ) or (
        <xref ref-type="bibr" rid="ref3">3</xref>
        ). Mizushima et al. [6] uses the set of ”first terminals”
as e0. This works if the grammar is LL(
        <xref ref-type="bibr" rid="ref1">1</xref>
        ). We extend this to a wider class of
grammars by using ”first expressions”. A first expression of e is any expression
first such that L(first) + and L(e) L(first) ∗.
      </p>
      <p>Given A = e1=e2, suppose there exist first expressions first1; first2 such
that:</p>
      <p>L(e1)</p>
      <p>L(first1) ∗;
L(e2) Tail(A)</p>
      <p>L(first2) ∗;</p>
      <p>
        L(first1) ∗ \ L(first2) ∗ = ∅:
One can easily see that L(first1) ∗ \ L(e2) Tail(A) = ∅. If e1 = first1 e1′ for
some e1′, we have, according to (
        <xref ref-type="bibr" rid="ref2">2</xref>
        ), a " cut point in e1 after first1.
For E in our example, (
        <xref ref-type="bibr" rid="ref4 ref5 ref6">4–6</xref>
        ) are satisfied by first1 = T + and first2 = T $,
identifying the " cut point after T +.
      </p>
      <p>
        Suppose that instead of (
        <xref ref-type="bibr" rid="ref6">6</xref>
        ), first1 and first2 satisfy
      </p>
      <p>L(first2)</p>
      <p>
        L(first1) ∗:
We have then L(e2) Tail(A) L(first1) ∗. If e1 = first1 e1′ for some e1′, we
have, according to (
        <xref ref-type="bibr" rid="ref3">3</xref>
        ), a # cut point in e1 after first1.
      </p>
      <p>For E in our example, the conditions are satisfied by first1 = first2 = T ,
identifying the # cut point after T .</p>
      <p>
        A special case of first1 and first2 are the sets of ”first terminals” used in [6].
In that special case, (
        <xref ref-type="bibr" rid="ref4 ref5 ref6">4–6</xref>
        ) are conditions for the grammar being LL(
        <xref ref-type="bibr" rid="ref1">1</xref>
        ). Allowing
first1 and first2 to be arbitrary expressions extends the results from [6] to
grammars that have been in [7,8] referred to as LL(kP). These are the grammars
where a top-down parser can choose its way by examining the input within the
reach of k parsing procedures. (Note that our example in the Introduction is
LL(2P).)
4
      </p>
    </sec>
    <sec id="sec-4">
      <title>External cut point</title>
      <p>It is often difficult to represent e1 as first1 e1′. This is solved in [6] by replacing
A = e1=e2 with:</p>
      <p>
        A = (! first2) e1 = e2:
(
        <xref ref-type="bibr" rid="ref8">8</xref>
        )
Obviously e2 must fail once ! first2 succeeded, so we have " after (! first2).
To verify that this also works for first expressions, we have to introduce the
not-predicate "!" into our grammar. It can be done in a restricted way, by
defining ! e0 e1=e2 as a new expression and formally specifying its semantics.
(
        <xref ref-type="bibr" rid="ref4">4</xref>
        )
(
        <xref ref-type="bibr" rid="ref5">5</xref>
        )
(
        <xref ref-type="bibr" rid="ref6">6</xref>
        )
(
        <xref ref-type="bibr" rid="ref7">7</xref>
        )
      </p>
      <p>
        Assuming that the grammar satisfies (
        <xref ref-type="bibr" rid="ref1">1</xref>
        ) and first1; first2 satisfy (
        <xref ref-type="bibr" rid="ref4 ref5 ref6">4–6</xref>
        ),
one can use Propositions 1 and 2 to verify that:
– (! first2) e1 = e2 is equivalent to e1 = e2 in the sense that both either consume
the same text, or both fail, on the same input.
– If ! first2 succeeds then e2 fails.
5
      </p>
    </sec>
    <sec id="sec-5">
      <title>Labeled failures</title>
      <p>In the standard version of PEG, a failing expression returns just an indication
that it failed. In the modification suggested in Section 5 of [3], failing expression
returns a label which may conveniently be a complete error message. One
distinguished such label is just ”fail”. A failing terminal returns ”fail” by default.
Other labels are created by the new expression *l which forces an immediate
failure with label l. The meaning of choice e1=e2 is redefined so that if e1 fails
with label ”fail”, e2 is tried in the normal way and the expression terminates
with the result of e2. If e1 fails with label other than ”fail”, the whole expression
fails immediately with that label without trying e2. Of course, this can only be
safe before # and after ".</p>
      <p>The technique can be used in our example like this:</p>
      <p>E = (T / *t) + (E / *e) / T
where t may be the message ”Term expected” and e the message ”Expression
expected”. The result is the message ”Term expected” for a failure before # and
”Expression expected” for a failure after ".
6</p>
    </sec>
    <sec id="sec-6">
      <title>Problems</title>
      <p>
        The sets of ”first terminals” of e can be mechanically computed by restricting
to terminals the set First∗(e) where First is the relation describing which
expressions appear as first in the definition of a given expression. Condition (
        <xref ref-type="bibr" rid="ref6">6</xref>
        )
boils down to checking that two sets of letters are disjoint. This means that the
cut points (
        <xref ref-type="bibr" rid="ref8">8</xref>
        ) can always be automatically inserted. But it works only for LL(
        <xref ref-type="bibr" rid="ref1">1</xref>
        )
grammars, while the backtracking of PEG is often used just to avoid the LL(
        <xref ref-type="bibr" rid="ref1">1</xref>
        )
restriction.
      </p>
      <p>
        It is suggested in [7, 8] how to find first1; first2 satisfying (
        <xref ref-type="bibr" rid="ref4 ref5">4,5</xref>
        ) among the
subsets of First∗(e1) and First∗(e2). But, checking (
        <xref ref-type="bibr" rid="ref6">6</xref>
        ) for these subsets cannot,
in general, be done in a mechanical way. It appears that finding cut points in
non-LL(
        <xref ref-type="bibr" rid="ref1">1</xref>
        ) grammars must to a large extent be done manually. The same applies
to insertion of labeled failures, even if one solves the problem of a mechanical
generation of meaningful message texts.
      </p>
      <p>An anonymous reviewer pointed out that manually inserted cut points and
labeled failures make the grammar completely unreadable. One has to find a
way of conveying the information in another way. This can, for example, be done
in semantic procedures, which in some parser generators (such as the author’s
”Mouse”) are separated from the grammar.</p>
      <p>A recent note [2] to the PEG discussion forum pointed out an important
fact: cut points are local to a specific expression. Their use for discarding saved
results and for generating diagnostics must be considered in the context in which
the expression is invoked. Suppose expression e invoked e′. Passing a cut point
in e′ does not mean that e passed its cut point; e may still need its saved results.
Similarly, a ”serious” termination of e′ may turn out to be an ”innocent” one
in e. This must be taken into account when designing any scheme using cut
points.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          1.
          <string-name>
            <surname>Ford</surname>
            ,
            <given-names>B.</given-names>
          </string-name>
          :
          <article-title>Parsing expression grammars: A recognition-based syntactic foundation</article-title>
          . In: Jones,
          <string-name>
            <given-names>N.D.</given-names>
            ,
            <surname>Leroy</surname>
          </string-name>
          ,
          <string-name>
            <surname>X</surname>
          </string-name>
          . (eds.)
          <source>Proceedings of the 31st ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages</source>
          ,
          <string-name>
            <surname>POPL</surname>
          </string-name>
          <year>2004</year>
          . pp.
          <volume>111</volume>
          {
          <fpage>122</fpage>
          . ACM, Venice, Italy (
          <volume>14</volume>
          {
          <issue>16</issue>
          <year>January 2004</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          2.
          <string-name>
            <surname>Hobbelt</surname>
          </string-name>
          , G.:
          <article-title>Breaking the Mizushima(2010) cut operator</article-title>
          ,
          <source>PEG Archives</source>
          ,
          <year>July 2014</year>
          , https://lists.csail.mit.edu/pipermail/peg/2014-July/000629.html
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          3.
          <string-name>
            <surname>Maidl</surname>
            ,
            <given-names>A.M.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Medeiros</surname>
            ,
            <given-names>S.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Mascarenhas</surname>
            ,
            <given-names>F.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Ierusalimschy</surname>
            ,
            <given-names>R.</given-names>
          </string-name>
          :
          <source>Error reporting in Parsing Expression Grammars. Tech. rep., PUC-Rio</source>
          , UFRJ Rio de Janeiro, UFRN Natal,
          <string-name>
            <surname>Brazil</surname>
          </string-name>
          (
          <year>2014</year>
          ), http://arxiv.org/pdf/1405.6646v1.pdf
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          4.
          <string-name>
            <surname>Mascarenhas</surname>
            ,
            <given-names>F.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Medeiros</surname>
            ,
            <given-names>S.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Ierusalimschy</surname>
          </string-name>
          , R.:
          <article-title>On the relation between contextfree grammars and Parsing Expression Grammars</article-title>
          .
          <source>Tech. rep.</source>
          , UFRJ Rio de Janeiro, UFS Aracaju, PUC-Rio,
          <source>Brazil</source>
          (
          <year>2013</year>
          ), http://arxiv.org/pdf/1304.3177v1
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          5.
          <string-name>
            <surname>Medeiros</surname>
            ,
            <given-names>S.</given-names>
          </string-name>
          : Correspond^encia entre PEGs e Classes de Gramaticas Livres de Contexto.
          <source>Ph.D. thesis</source>
          , Pontif cia Universidade Catolica do Rio de Janeiro (
          <year>Aug 2010</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          6.
          <string-name>
            <surname>Mizushima</surname>
            ,
            <given-names>K.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Maeda</surname>
            ,
            <given-names>A.</given-names>
          </string-name>
          ,
          <string-name>
            <surname>Yamaguchi</surname>
            ,
            <given-names>Y.</given-names>
          </string-name>
          :
          <article-title>Packrat parsers can handle practical grammars in mostly constant space</article-title>
          . In: Lerner,
          <string-name>
            <given-names>S.</given-names>
            ,
            <surname>Rountev</surname>
          </string-name>
          ,
          <string-name>
            <surname>A</surname>
          </string-name>
          . (eds.)
          <source>Proceedings of the 9th ACM SIGPLAN-SIGSOFT Workshop on Program Analysis for Software Tools and Engineering</source>
          , PASTE'
          <fpage>10</fpage>
          , Toronto, Ontario, Canada, June 5-6,
          <year>2010</year>
          . pp.
          <volume>29</volume>
          {
          <fpage>36</fpage>
          .
          <string-name>
            <surname>ACM</surname>
          </string-name>
          (
          <year>2010</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          7.
          <string-name>
            <surname>Redziejowski</surname>
            ,
            <given-names>R.R.</given-names>
          </string-name>
          :
          <source>From EBNF to PEG. Fundamenta Informaticae</source>
          <volume>128</volume>
          (
          <issue>1-2</issue>
          ),
          <volume>177</volume>
          {
          <fpage>191</fpage>
          (
          <year>2013</year>
          )
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          8.
          <string-name>
            <surname>Redziejowski</surname>
            ,
            <given-names>R.R.</given-names>
          </string-name>
          :
          <article-title>More about converting BNF to PEG</article-title>
          . Fundamenta
          <string-name>
            <surname>Informaticae</surname>
          </string-name>
          (
          <year>2014</year>
          ), to appear, http://www.romanredz.se/papers/FI2014.pdf
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>