On Thu, Apr 11, 2013 at 7:41 PM, Dmitry Kakurin <dmitry.kaku...@gmail.com>wrote:

> But your parser rules are somewhat new to me.
> Both variations are accepted:
>
>      add = add-sub <'+'> add-sub
>      add = mul-div <'+'> add-sub
>
> And in both cases some generated parsers are correct (arithmetically
> speaking :-) ), but I'd like to understand rules for the first/default
> parser.
> Could you clarify it a little please?
>

Let's start with a simpler example, a grammar that only involves + and
numbers (no handling for parens or whitespace).

(def addition
  (insta/parser
    "plus = plus <'+'> plus | num
     num = #'[0-9]'+"))

If you call (parses addition "1+2+3"), you'll see that that two parse
results are returned.  This grammar is ambiguous and you'll get one parse
result that corresponds to (1+2)+3 and another parse result that
corresponds to 1+(2+3).

I gather from your questions that you really want to know which of these
parse results will come first (i.e., which one will be returned if you only
ask for one parse result).  The answer is:  I make no guarantee as to which
will come first.  (I'm not just being ornery; this lack of guarantee is
important for my future plans for a concurrent version).

Now in this particular case, since addition is associative, maybe we're
perfectly happy to let the ambiguity stand and let instaparse just pick one
of the two possible results for us.  But if we don't want that ambiguity,
we must alter the grammar until we see that parses always returns one
result.  In the above grammar, there are a couple straightforward ways to
resolve the disambiguation:

(def addition-associate-right
  (insta/parser
    "plus = num <'+'> plus | num
     num = #'[0-9]'+"))

(def addition-associate-left
  (insta/parser
    "plus = plus <'+'> num | num
     num = #'[0-9]'+"))

You mentioned that you were familiar with LL grammars.  So this is similar
to LL in the sense that if you want a precise result, you need to make the
grammar precise -- you can't rely on external precedence or associativity
rules.  However, the resulting disambiguated grammars are much more natural.

Consider the above addition-associate-left grammar -- LL would choke on
this because it is left-recursive.  If you want to associate to the left in
LL, you have to transform the natural-looking left-recursive rule into
something much messier.  This is an unfortunate limitation of LL grammars.
For correct calculation, arithmetic operators of equal precedence really
need to associate to the left (i.e., 1-2-3 should evaluate as (1-2)-3, not
1-(2-3)), and left recursion is the easiest way to express that.

To better understand this point, take a look at:
http://www.csse.monash.edu.au/~lloyd/tildeProgLang/Grammar/Top-Down/

First, it shows the arithmetic grammar you'd *want* to write.  You'll see
it looks almost identical to the grammar I used in the tutorial (although I
added a root tag and broke out the operators individually for evaluation
purposes).

Then, it goes on to show that in LL, you can't actually write the grammar
the way you'd want to write it.  It demonstrates two transformations that
eventually turn the grammar into something LL can handle.

The beauty of the tutorial example is that it shows you can get a
completely unambiguous grammar, just by writing it down in the natural way
that expresses the precedence and associativity constraints.  Unlike LL,
the elegant way just works.

So, to summarize the main points here:

* As you develop your grammar, test your grammar with the parses function
to determine whether your grammar is ambiguous.
* If your grammar is ambiguous, but the ambiguity doesn't cause a problem,
then that's fine, just leave it ambiguous.
* If you need to disambiguate, you must do it by building more precision
into the grammar.
* Don't need to worry about limitations of LL, but the mindset of top-down
parsing is similar.

I hope this helps!

--Mark

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to