[comp.lang.prolog] Parsers in prolog

roberto@cernvax.cern.ch (roberto bagnara) (12/14/90)

Hi,

    I'm struggling with the following problem and, perhaps, somebody out
there could help me. I haven't found anything useful in my prolog books.
Thank you in advance for your attention

                                          Roberto Bagnara

Problem
-------

    Is it possible the write a DCG parser for a simple language that
requires some operators to be LEFT ASSOCIATIVE?
If DCG is not adequate (as I strongly suspect), what's the fastest way to
write a suitable parser (i.e. with left associative operators) in prolog?

Short explanation
-----------------

    The following DCG results in an endless loop (I'm not surprised about
that, knowing how DCGs are translated and how prolog works), while it implies
left associativity of the operators (the one I want):

expr(plus(X,Y)) --> expr(X), [+], term(Y).
expr(minus(X,Y)) --> expr(X), [-], term(Y).
expr(X) --> term(X).

term(prod(X,Y)) --> term(X), [*], factor(Y).
term(div(X,Y)) --> term(X), [/], factor(Y).
term(X) --> factor(X).

factor(N) --> [N].
factor(X) --> ['('], expr(X), [')'].

Swapping expr with term in the first 2 clauses for expr, and term with factor
in the first 2 clauses for term gives a working parser, but operators, as
expected, are right associative.

pazzani@pan.ics.uci.edu (Michael Pazzani) (12/14/90)

>    Is it possible the write a DCG parser for a simple language that
>requires some operators to be LEFT ASSOCIATIVE?
>If DCG is not adequate (as I strongly suspect), what's the fastest way to
>write a suitable parser (i.e. with left associative operators) in prolog?

You are confusing left associative with left recursive.  It's most
natural to write a left associative grammar as a left recursive one,
but it's not necessary.  It is possible to remove left recursion from
a grammar.  See a good compiler book for more info, but the general
idea is that

A-> x
A-> Ab

can be replaced with

A->xD
D->bD
D-> empty string.

Applying this to your grammar is a bit messy (because of the binding)
but here's a start. (Please note that term(x) and term(X,Y) are
two different predicates corresponding to A and D in the above template).

term(Y) --> factor(X), term(X,Y).
term(X,Z) -->  [*], factor(Y), term(prod(X,Y),Z).
term(X,X) -->[].

factor(N) --> [N].

Now the math is left associative:
term(R,[x,*,y,*,z],[]).
R = prod(prod(x,y),z)

Just to persuade you that there needn't be a relationship
between left recursion and left association, a simple change
to the arguments (but not the "grammar") yields right association:

term(Y) --> factor(X), term(X,Y).
term(X,prod(X,Z)) -->  [*], factor(Y), term(Y,Z).
term(X,X) -->[].

factor(N) --> [N].

now:
term(R,[x,*,y,*,z],[]).
R = prod(x,prod(y,z))


Actually, I can never really remember which is left
associative, but one of these should work for you.  Why not
just use parentheses anyway (spoken like a true lisp hacker).

Mike

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (12/14/90)

In article <3581@cernvax.cern.ch>,
roberto@cernvax.cern.ch (roberto bagnara) writes:

>     Is it possible the write a DCG parser for a simple language that
> requires some operators to be LEFT ASSOCIATIVE?

Yes.  It is easy.  Prolog syntax itself includes left-associative
operators (I can never remember whether that means xfy or yfx, but
Prolog syntax has both), and the public-domain parser _could_ have
been written as a DCG (although it happened not to be).  Techniques
for eliminating left recursion are described in all good compiler
books.  Consider

	expr(Expr) --> term(Term), rest_expr(Term, Expr).

	rest_expr(Expr0, Expr) --> [+],
		term(Term), rest_expr(Expr0+Term, Expr).
	rest_expr(Expr0, Expr) --> [-],
		term(Term), rest_expr(Expr0-Term, Expr).
	rest_expr(Expr, Expr) --> [].

Book 1, Lesson 3.
-- 
The Marxists have merely _interpreted_ Marxism in various ways;
the point, however, is to _change_ it.		-- R. Hochhuth.