Detection of ambiguous grammar

19 views
Skip to first unread message

maxime-esa

unread,
May 30, 2012, 8:49:25 AM5/30/12
to lepl
Dear LEPL experts,

In trying to find a good parser for Python to implement a rather
complex grammar. I already know that Pyparsing will dot detect the
ambiguities of my grammar, and so far only ANTLR does. But as I am
trying to avoid having to compile the grammar before I can use it, I
am now looking at LEPL, which seems quite powerful.

However, on my first tests, I am facing the same issue as with
Pyparsing - I hope someone can tell me if I am doing things wrong or
if LEPL will ever be able to detect my grammar error.

Here is what I wrote:

from def build():
stmt = Delayed()
with DroppedSpace():
expr = Literal('EXPR')
end = Literal ('endif')
cond = stmt | end
stmt += 'if' & expr & 'then' & cond & Optional('else' & cond)
line = Trace(stmt) & Eos()

return line.get_parse()

parser = build()
print parser('if EXPR then if EXPR then endif else endif')
['if', 'EXPR', 'then', 'if', 'EXPR', 'then', 'endif', 'else', 'endif']

Basically, this result is wrong. According to the grammar, the "else"
can belong either to the first "if" statement or to the second one. I
would expect the parser to detect this ambiguity and reject the
grammar.

The following is the equivalent grammar I wrote in ANTLR:

cond : stmt | END;

stmt : 'if' EXPR 'then' cond ('else' cond)* ;

EXPR : 'EXPR';
END : 'endif';

And when I compile it I get the following error:

warning(200): test.g:18:42: Decision can match input such as "'else'"
using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
error(201): test.g:18:42: The following alternatives can never be
matched: 2


I hope this is clear and makes sense - so my question: is my grammar
badly specified? How would I need to write it so that LEPL would raise
an error ?

Thanks

andrew cooke

unread,
Jun 2, 2012, 2:20:29 PM6/2/12
to le...@googlegroups.com

Hi,

[Sorry seems this was waiting a few days in the Google groups spam filter]

Lepl is a recursive descent parser (like pyparsing, I think) and, as such, has
a well defined ordering when parsing grammar. So it will resolve ambiguities
according to the order implicit in the way the matchers are defined. The only
errors it will flag are left recursion and, by default, the failure to match
the entire input.

You ask how Lepl can be made to reject the grammar. It cannot.

However, you can, with care, define the grammar so that the ordering resolves
ambiguities in the way you feel most appropriate. For example,

Python 2.7.2 (default, Aug 19 2011, 20:41:43) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from lepl import *
>>> def build():
... stmt = Delayed()
... with DroppedSpace():
... expr = Literal('EXPR')
... end = Literal ('endif')
... cond = stmt | end
... stmt += ('if' & expr & 'then' & cond & Optional('else' & cond) > list)
... line = Trace(stmt) & Eos()
... return line.get_parse()
...
>>> parser = build()
>>> print parser('if EXPR then if EXPR then endif else endif')
[['if', 'EXPR', 'then', ['if', 'EXPR', 'then', 'endif', 'else', 'endif']]]

where the nesting shows how the ambiguity was resolved.

Andrew
> --
> You received this message because you are subscribed to the Google Groups "lepl" group.
> To post to this group, send email to le...@googlegroups.com.
> To unsubscribe from this group, send email to lepl+uns...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/lepl?hl=en.
>
Reply all
Reply to author
Forward
0 new messages