PEGルールを記述する際には、それが貪欲であることに留意する必要があります。可変量のテキストを消費し得るルールは、たとえそれを行うことによって通常であればマッチするような後続のルールが失敗することになろうとも、可能なかぎり最大の量のテキストを常に消費します。たとえば以下のルールが成功することは決してあり得ません:
(forest (+ "tree" (* [blank])) "tree" (eol))
(+ "tree" (* [blank]))
というPEXは、最後にマッチさせる‘tree’を残さず、単語‘tree’の繰り返しすべてを消費します。
このような状況においては述語とguard
(すなわち式not
、if
、guard
)を用いて挙動を制限することによって望ましい結果を得ることができます。たとえば:
(forest (+ "tree" (* [blank])) (not (eol)) "tree" (eol))
if
およびnot
はポイントを移動せずにパース式を受け取って、ブーリアンとして解釈できる演算子です。guard
演算子の内容は通常のLisp(PEXではない)として評価されてブーリアン値をリターンされるはずです。nil
値の場合にはマッチは失敗です。
他の期待していない振る舞いとしては、たとえ最終的に失敗するパースであってもパースによって可能なかぎり遠くにポイントが移動してしまう可能性があることです。以下のルール:
(end-game "game" (eob))
このルールをポイント後にテキスト“game
over”を含んだバッファーで実行すると、ポイントを“game”の直後に移動してからパースを中止してnil
をリターンするでしょう。パースが成功した場合には常にt
、あるいはパーススタックのコンテキストをリターンします。