Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.2 9/18/84; site ucla-cs.ARPA
Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxt!houxm!vax135!cornell!uw-beaver!tektronix!hplabs!sdcrdcf!ucla-cs!dimare
From: dimare@ucla-cs.UUCP
Newsgroups: net.lang.prolog
Subject: DCGs + Left Recursion = (:-[) !
Message-ID: <6884@ucla-cs.ARPA>
Date: Thu, 19-Sep-85 19:38:57 EDT
Article-I.D.: ucla-cs.6884
Posted: Thu Sep 19 19:38:57 1985
Date-Received: Mon, 23-Sep-85 00:43:44 EDT
Organization: UCLA Computer Science Department
Lines: 93

I'm writing a little parser for a Pascal like language.
I was going to copy Wirth's grammar into a DCG Prolog
program, but I noticed that left recursion can't be used.
If you have a rule like:

a --> a, [+], b.      a --> b.      b --> [b].

it translates into:
a(A, B) :- a(A, C), 'C'(C, +, D), b(D, B).      'C'([H|T],H,T).

Any goal of the form a(Sentence,[]) would make the above
rule recurse until end_of_stack.
(Yes, a([b,+,b],[]) doesn't work either: try it!).

My problem is that the grammars I know for parsing expressions
are left recursive. The example in most Prolog manuals uses left
recursion. I ran it, and I got the following result (I include
the code at the end of the message):

| ?- expr(Z,"2-3-4",[]).

Z = 3 ;

no
| ?- Z is 2-3-4.

Z = -5 ;

no
| ?- halt.

Obviously, the 'standard' example is wrong. My question is: Does
any body know a way to do expressions using DCGs that doesn't make
the grammar look like a plate of spaghetti? I know I could translate
my grammar into Griebach Normal Form (or $%#!"%#$" Normal Form, for
that mater), but I could also as well write the whole parser in
8080 assembly language. Here's the grammar:

Script started on Thu Sep 19 15:16:07 1985
h[2:101] c dcg0
% File   : /usr/lib/prolog/teach/dcg0
% Author : lost in the mists of time
% Updated: 23 Nov 1983
% Purpose: the standard example of using Prolog grammar rules

% This is a simple grammar which parses an arithmetic expression (of digits and
% operators) and computes its value.

expr(Z) --> term(X), "+", expr(Y), {Z is X+Y}.
expr(Z) --> term(X), "-", expr(Y), {Z is X-Y}.
expr(Z) --> term(Z).

term(Z) --> number(X), "*", term(Y), {Z is X*Y}.
term(Z) --> number(X), "/", term(Y), {Z is X/Y}.
term(Z) --> number(Z).

number(C) --> "+", number(C).
number(C) --> "-", number(X), {C is -X}.
number(X) --> [C], {48=