Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><em>Meta:</em> Why doesn't the FParsec tag work on this question?</p> <p>I'll quote myself from the comments on the page for the <a href="https://stackoverflow.com/q/9215975/162396">previous question</a>:</p> <p>The nested but not mutally recursive expression grammars make the parens parsing a bit nasty here. The problem is that when the parser sees an opening bracket at certain locations, it doesn't yet know whether the parenthesized expression needs to be parsed as a <code>scalarExpr</code>, <code>comparison</code> or <code>searchCondition</code>. To be able to parse such expressions, you have to introduce some limited backtracking for parser errors after opening brackets and before closing brackets, so that the parser can tentatively parse a parenthesized expression with one subgrammar and, if necessary, parse again with a different grammar. </p> <pre><code>let tryBetweenParens p = lparen &gt;&gt;? (p .&gt;&gt;? rparen) let opp = OperatorPrecedenceParser&lt;_,_,_&gt;() let scalarExpr = opp.ExpressionParser opp.TermParser &lt;- choice [constant; id; tryBetweenParens scalarExpr] // ... let comparison = // doesn't currently allow chained comparisons ( e.g. 1 = 2 = 3) let compareExpr = pipe3 scalarExpr compareOp scalarExpr (fun l op r -&gt; Comparison(op, l, r)) compareExpr &lt;|&gt; tryBetweenParens compareExpr // ... let searchCondition, searchConditionRef = createParserForwardedToRef() do searchConditionRef:= chainl1 (comparison &lt;|&gt; between lparen rparen searchCondition) (andTerm &lt;|&gt; orTerm) </code></pre> <p>The complete code is available at <a href="http://pastebin.com/i7JFJWJE" rel="nofollow noreferrer">http://pastebin.com/i7JFJWJE</a> </p> <p>With the usual expression grammars, where any parenthesized (top-level) expression is valid everywhere where a leaf term is valid, parsing is obviously simpler, because you just need to deal with parens at one place in the grammar. This is another argument for just using a single <code>OperatorPrecedenceParser</code>, as Stephen Swensen suggested. However, you'll have to annotate the AST with source locations if you want to be able to generate good error messages after parsing.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload