writing context free grammar in prolog
Asked Answered
E

2

5

let's say I had the following context free grammar.

S -> A
A -> mAn
A -> o

How would this look in prolog? This is what I tried but it doesn't work. The second line seems to be the issue.

S(Z) :- A(Z).
A(Z) :- append([m],X,Z2), A(X), append(Z2,[n],Z).
A([o]).
Ecospecies answered 30/11, 2015 at 19:26 Comment(1)
Dont write A(Z), but a(Z). Similarly with all predicate names...Orsa
T
4

since the grammar is not left recursive, we can use a DCG:

s --> a.
a --> [m], a, [n].
a --> [o].

then we can parse or generate all accepted sequences. For instance, generating:

?- length(L, _), phrase(s, L).
L = [o] 
L = [m, o, n] 
L = [m, m, o, n, n] 
...

to inspect the Prolog code:

?- listing(s).
s(A, B) :-
    a(A, B).

?- listing(a).
a([m|A], C) :-
    a(A, B),
    B=[n|C].
a([o|A], A).

no append/3 required, thanks to difference lists

edit using append/3

s(Z) :- a(Z).
a(Z) :- append([m|X],[n],Z), a(X).
a([o]).

SWI-Prolog has append/2 (simply based on append/3 properly chained), that give a more readable alternative

a(Z) :- append([[m],X,[n]], Z), a(X).

anyway, we must call a/1 recursively after the list has been built/split

Tullusus answered 30/11, 2015 at 19:39 Comment(3)
Cool. How would it be like if append/3 were used?Ecospecies
Why do you put a([o]). last?Steiger
@false: I was attempting to keep the code most similar to the originalTullusus
O
3

In this answer, we use the commonly available predicate append/3.

s(Xs) :-
   a(Xs).

a([o]).
a([m|Xs]) :-
   append(Xs0,[n],Xs),
   a(Xs0).

Sample query:

?- length(Xs,_), s(Xs).
   Xs = [o]
;  Xs = [m,o,n]
;  Xs = [m,m,o,n,n]
;  Xs = [m,m,m,o,n,n,n] 
...

NOTE: Using append/3 instead of is, in general, a bad choice and can contribute to both lower runtime performance and code readability. Whenever possible, use instead!

Orsa answered 1/12, 2015 at 3:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.