I have the following context free grammar in a text file 'grammar.txt'
S ::= a S b
S ::= []
I'm opening this file and able to read each line in prolog.
Now i want to tokenize each line and generate a list such as
L=[['S','::=','a','S','b'],['S','::=','#']] ('#' represents empty)
How can i do this?
Write the specification in a DCG. I give you the basic (untested), you'll need to refine it.
parse_grammar([Rule|Rules]) -->
parse_rule(Rule),
parse_grammar(Rules).
parse_grammar([]) --> [].
parse_rule([NT, '::=' | Body]) -->
parse_symbol(NT),
skip_space,
"::=",
skip_space,
parse_symbols(Body),
skip_space, !. % the cut is required if you use findall/3 (see below)
parse_symbols([S|Rest]) -->
parse_symbol(S),
skip_space,
parse_symbols(Rest).
parse_symbols([]) --> [].
parse_symbol(S) -->
[C], {code_type(C, alpha), atom_codes(S, [C])}.
skip_space -->
[C], {code_type(C, space)}, skip_space.
skip_space --> [].
This parse the whole file, using this toplevel:
...,
read_file_to_codes('grammar.txt', Codes),
phrase(parse_grammar(Grammar), Codes, [])).
You say you read the file 1 line at time: then use
...
findall(R, (get_line(L), phrase(parse_rule(R), L, [])), Grammar).
HTH
Related
I am having some difficulties understanding how to parse some text from stdin to the desired variables using DCG.
Players: player1 & player2
Board : 3 moves
1A : player1
5D : player2
8Z : player1
So a game has two player variable names and then some moves by each player, I would like to have predicate that unifies Players = [player1,player2] , turn1 = [1A,8A] , turn2 = [5D].
How Would I do this using DCG ?
I have tried the following:
main :-
read_string(user_input,"\n","\r",_,FirstLine),
phrase(readPlayers(Players),FirstLine),
write(Players).
parsePlayers --> [Players].
parseColon --> [:].
parseSpace --> [ ].
readPlayers([P1,P2]) --> parsePlayers,parseColon,parseSpace,P1,parseSpace,[&], parseSpace,P2.
However this doesn't work in SWI-Prolog, how can I achieve this?
I would use library(dcg/basics), that offers some relatively low level utilities. It can be coupled with library(dcg/high_order), to further enhance your parser.
:- use_module(library(dcg/basics)).
:- use_module(library(dcg/high_order)).
player(P) -->
code(csymf,C),
codes(csym,Cs),
{atom_codes(P,[C|Cs])}.
players(Ps) -->
"Players",
sep(":"),
sequence(player,sep("&"),Ps),
blanks.
% my utilities
sep(S) --> whites, S, whites.
code(T,C) --> [C], {code_type(C,T)}.
codes(T,Cs) --> sequence(code(T),Cs).
To test the grammar you can call directly the nonterminal. Note the grammar accepts more that 2 players and correctly skips white spaces, in a flexible way.
?- phrase(players(Ps),`Players: player1 & player2& player3`).
Ps = [player1, player2, player3] ;
false.
I have defined a DFG grammar in Prolog which is something like this:
start --> subject, verb, object.
subject --> ([i]; [you]).
verb --> ([like]; [need]).
object --> article, noun.
article --> ([my];[your]).
noun --> ([car] ; [bike]).
Now, I would like to have a predicate that returned me the object part of a phrase accepted by this DFG.
For example, objectPart([i, like, my, car], X) should return X = [my, car].
How can I do this?
This can be done:
start(O) --> subject, verb, my_object(O).
subject --> ([i]; [you]).
verb --> ([like]; [need]).
my_object(L) --> article(A), noun(N), {L = [A,N]}.
article(A) --> ([my],{A=my};[your],{A=your}).
noun(N) --> ([car],{N=car} ; [bike],{N=bike}).
objectPart(Lst, R) :-
phrase(start(R), Lst).
Result :
?- objectPart([i, like, your, car], Z).
Z = [your, car] .
EDIT I change object in my_object because SWI-Prolog use object for XPCE.
I have written the DCG (Adjective phrase and prepositional phrase) in prolog, when I tried to run it, by entering ip([every,boy,loved,some,girl]), it shows out of local stack. I realised there is something wrong with the nbar. Can someone help me out? Many thanks.
%tree
treeP(Term):-
% Print the tree assuming indentation 0
treeP(0,Term),
% Tidy up with linefeed
nl.
treeP(_N,Tree):-
% Tree is just a variable
var(Tree),!,
write(Tree).
treeP(N,[Tree|Trees]):-
proper_list([Tree|Trees]),!,
write('['),
N1 is N+1,
treePNEL(N1,[Tree|Trees]),
write(']').
treeP(N,Tree):-
% Nonatomic case
Tree=..[Functor,Argument|Arguments],
!,
% Write the functor and opening parenthesis
write(Functor),write('('),
% Set N1 to new indentation for arguments
atom_length(Functor,M), N1 is N+M+1,
% Pretty-print the arguments
treePNEL(N1,[Argument|Arguments]),
% Write right parenthesis
write(')').
treeP(_N,Tree):-
% Noncompound case
write(Tree).
treePNEL(N,[Tree1,Tree2|Trees]):-
treeP(N,Tree1),
% Go to correct position for further printing
nl, tab(N),
treePNEL(N,[Tree2|Trees]).
treePNEL(N,[Tree]):-
treeP(N,Tree).
ip(Sentence):-
setof(IP,
ip(IP,Sentence,[]),
IP),
treeP(IP).
ip(SSem) --> np(NPSem), ibar(IbarSem),
{var_replace(NPSem,NPSem1),
beta(NPSem1#IbarSem,SSem)}.
ibar(VPSem) --> i(MvdVbL),vp(VPSem,MvdVbL).
i([]) --> [].
i([]) --> [Aux],{isAux(Aux)}.
i([Verb]) --> [InflVerb],{pastInfl(Verb,InflVerb),isVerb(Verb)}.
pastInfl(see,saw).
pastInfl(love,loved).
vp(VbarSem,MvdVbL) --> vbar(VbarSem,MvdVbL).
vbar(VbarSem,MvdVbL) --> v(VSem,MvdVbL), np(NPSem),
{var_replace(VSem,VSem1),
beta(VSem1#NPSem,VbarSem)}.
v(lbd(s, lbd(x,s#lbd(y,Fla))),[]) --> [Verb],
{isVerb(Verb),Fla=..[Verb,x,y]}.
v(lbd(s,lbd(x,s#lbd(y,Fla))),[MvdVb])--> [],
{Fla=..[MvdVb,x,y]}.
np(NbarSem) --> nbar(NbarSem).
nbar(NbarSem) --> adj(AdjSem),nbar(NbarSem1),
{var_replace(AdjSem,AdjSem1),beta(AdjSem1#NbarSem1,NbarSem)}.
nbar(NbarSem) --> det(DetSem),nbar(NbarSem1),
{var_replace(DetSem,DetSem1),beta(DetSem1#NbarSem1,NbarSem)}.
nbar(NSem) --> n(NSem).
nbar(NbarSem) --> nbar(NbarSem1),pp(PPSem),
{var_replace(PPSem,PPSem1),beta(PPSem1#NbarSem1,NbarSem)}.
nbar(NSem) --> n(NSem).
pp(PPSem) --> pbar(PPSem).
pbar(NbarSem) --> po(PPSem),np(NbarSem1),
{var_replace(PPSem,PPSem1),beta(PPSem1#NbarSem1,NbarSem)}.
isVerb(love).
n(lbd(x,boy(x))) --> [boy].
n(lbd(x,girl(x))) --> [girl].
det(lbd(q,lbd(p,exists(x,(q#x & p#x))))) --> [some].
det(lbd(q,lbd(p,forall(x,(q#x -> p#x))))) --> [every].
nbar(NbarSem) --> adj(AdjSem),nbar(NbarSem1)
nbar(NbarSem) --> det(DetSem),nbar(NbarSem1)
nbar(NbarSem) --> nbar(NbarSem1),pp(PPSem)
Tabling is implemented in recent versions of SWI-Prolog. By declaring the predicates (or non-terminals) using left-recursion as tabled predicates (or non-terminals), you can keep their definitions. For details, consult:
http://www.swi-prolog.org/pldoc/man?section=tabling
I was going through this example on DCG
integer(I) -->
digit(D0),
digits(D),
{ number_codes(I, [D0|D])
}.
digits([D|T]) -->
digit(D), !,
digits(T).
digits([]) -->
[].
digit(D) -->
[D],
{ code_type(D, digit)
}.
But this example parses an integer only if it's in the beginning of the string (because digit(D0) fails is D0 is not a number code).
How do I go about parsing an integer anywhere in the string, e.g. "abc123def"?
You might add something like this:
non_digits--> [D], {not(code_type(D, digit))}, !, non_digits.
non_digits-->[].
and then add a call to non_digits to skip non digits, e.g.:
integer_skip(I) -->
non_digits,
digit(D0),
digits(D),
{
number_codes(I, [D0|D])
},
non_digits.
I have a problem, while creating a question answer Prolog file. I have a database with locations and I can already get the question and write the answer out. But there are different types of objects, that require different prefixes. So I defined DCG for prefixes.
answer(P,A) :- location(P, Str, Nr),A = [there, is, article(G,K,N,P), noun(G,K,N,P), pre(P),Str,Nr].
question(A) --> questionsentence(P),{answer(P,A)}.
pre(P) --> [in, P], {member(P, [road66])}.
pre(P) --> [at, P], {member(P, [trafalgarsquare])}.
but what i get is something like this:
?-question(A, [where,is,a,kentuckys],[]).
A = [there, is, article(_G2791, _G2792, _G2793, kentuckys), noun(_G2791, _G2792, _G2793, kentuckys), prep(kentuckys), road66, 123]
This works for verifying the input properly, but it seems to be useless for the output. How can I take just the variable and not the clause?
OK, I tried to translate the whole program to a more or less usefull and working example.
location(kentuckys, road66, 121).
location(soliver, trafalgarsquare, 15).
location(marcopolo, trafalgarsquare, 15).
location(internist, jumpstreet, 21).
questionsentence(P,G) --> [where],[is], article(G), noun(G,P).
answer(P,A,G) :- location(P, Str, Nr), prep(W,Str), article(G,Art,[]), flatten([there, is, Art, P, W, Str,Nr], A).
question(A) --> questionsentence(P,G),{answer(P,A,G)}.
article(m) --> [a].
article(f) --> [an].
noun(m, P) --> [P], {member(P, [kentuckys, soliver, marcopolo])}.
noun(f, P) --> [P], {member(P, [internist])}.
prep([at],Str) :- member(Str, [trafalgarsquare, road66]).
prep([in],Str) :- member(Str, [jumpstreet]).
Result:
?- question(A, [where,is,a,kentuckys],[]).
A = [there, is, a, kentuckys, at, road66, 121] .
I think, what I looked for was a construction like: article(G,Art,[]) to determine the depending DCG variable... actually I do not fathom yet how the two last arguments are working...