title: “Sprache” parser `Present` semantics
body: <p>I am writing a parser that conforms to <a href="https://www.rfc-editor.org/rfc/rfc7644#section-3.4.2.2" rel="nofollow noreferrer">System for Cross-domain Identity Management: Protocol Filtering</a> spec. I was able to parse almost any expression with Sprache, except &quot;pr&quot; operator. Can't wrap my head how to make it work properly.</p>
  <p>Here is main parsing stuff:</p>
  <pre><code>   {
          And = Operator(&quot;and&quot;, &quot;And&quot;);
          Or = Operator(&quot;or&quot;, &quot;Or&quot;);
      
          Le = Operator(&quot;le&quot;, &quot;LessThanOrEqual&quot;);
          Lt = Operator(&quot;lt&quot;, &quot;LessThan&quot;);
          Gt = Operator(&quot;gt&quot;, &quot;GreaterThan&quot;);
          Ge = Operator(&quot;ge&quot;, &quot;GreaterThanOrEqual&quot;);
          Eq = Operator(&quot;eq&quot;, &quot;Equal&quot;);
          Ne = Operator(&quot;ne&quot;, &quot;NotEqual&quot;);
          Co = Operator(&quot;co&quot;, &quot;Contains&quot;);
          Sw = Operator(&quot;sw&quot;, &quot;StartsWith&quot;);
          Ew = Operator(&quot;ew&quot;, &quot;EndsWith&quot;);
      
          Pr = Operator(&quot;pr&quot;, &quot;Present&quot;);
  
          ...
  
  
          Operand = (Parentheses
              .XOr(Literal.Or(AttrPath.Token()))
              .XOr(CaseInsensitiveString)).Token();
  
          //compareOp = &quot;eq&quot; / &quot;ne&quot; / &quot;co&quot; /
          //        &quot;sw&quot; / &quot;ew&quot; /
          //        &quot;gt&quot; / &quot;lt&quot; /
          //        &quot;ge&quot; / &quot;le&quot;
          CompareExpression = Parse.XChainOperator(Le.Or(Lt).XOr(Ge.Or(Gt)).XOr(Eq.Or(Ne)).XOr(Sw.Or(Ew)).XOr(Co).XOr(Pr), Operand, FilterExpression.Binary);
  
          PresentsExpression = Parse.XChainRightOperator(Pr, Operand, FilterExpression.Binary).Or(CompareExpression);
  
          // logExp    = FILTER SP (&quot;and&quot; / &quot;or&quot;) SP FILTER
          AndExpression = Parse.XChainOperator(And, CompareExpression, FilterExpression.Binary);
  
          // logExp    = FILTER SP (&quot;and&quot; / &quot;or&quot;) SP FILTER
          OrExpression = Parse.XChainOperator(Or, AndExpression, FilterExpression.Binary);
          Filter = OrExpression;
      }
      private static Parser&lt;string&gt; Operator(string op, string opName)
      {
          return Parse.String(op).Token().Return(opName);
      }
  </code></pre>
  <p>This is where I add &quot;pr&quot; parsing:</p>
  <pre><code> Parse.XChainRightOperator(Pr, Operand, FilterExpression.Binary).Or(CompareExpression);
  </code></pre>
  <p>This filter fails: <code>title pr and addresses[type eq \&quot;work\&quot;].streetAddress eq \&quot;workStreet\&quot;</code><br />
  And this is ok:</p>
  <pre><code>  addresses[type eq \&quot;work\&quot;].streetAddress eq \&quot;workStreet\&quot; 
  and (userType eq \&quot;Employee\&quot; or userType eq \&quot;ParttimeEmployee\&quot;)
  </code></pre>
  <p>Maybe someone can help me out with this.</p>
  <p>Edit:
  Maybe I should chain operators with XChainRightOperator at some point, because pr title works fine. But chain extensions are for binary expressions, and I need unary.</p>