/* Test of "DCG" in Picat. This is some ways of handling grammars in Picat, inspired by Prolog's DCG. Note: Picat v3.* supports DCGs. This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ % import util. % import cp. main => go. % From http://en.wikipedia.org/wiki/Definite_clause_grammar % """ % A basic example of DCGs helps to illustrate what they are and what they look like. % % sentence --> noun_phrase, verb_phrase. % noun_phrase --> det, noun. % verb_phrase --> verb, noun_phrase. % det --> [the]. % det --> [a]. % noun --> [cat]. % noun --> [bat]. % verb --> [eats]. % % This generates sentences such as "the cat eats the bat", "a bat eats the cat". % One can generate all of the valid expressions in the language generated by % this grammar at a Prolog interpreter by typing sentence(X,[]). Similarly, % one can test whether a sentence is valid in the language by typing something % like sentence([the,bat,eats,the,bat],[]). % % Translation into definite clauses % % DCG notation is just syntactic sugar for normal definite clauses in Prolog. % For example, the previous example could be translated into the following: % % sentence(S1,S3) :- noun_phrase(S1,S2), verb_phrase(S2,S3). % noun_phrase(S1,S3) :- det(S1,S2), noun(S2,S3). % verb_phrase(S1,S3) :- verb(S1,S2), noun_phrase(S2,S3). % det([the|X], X). % det([a|X], X). % noun([cat|X], X). % noun([bat|X], X). % verb([eats|X], X). % """ % Check a sentence go ?=> S1 = [the,cat,eats,the,bat], sentence(S1,S3), writeln([s1=S1,s3=S3]), fail, nl. go => true. % Check a sentence go2 => S1 = [a,cat,eats,the,cat], sentence(S1,S3), writeln([s1=S1,s3=S3]), nl. % Note: When using the grammar for generate sentences, one cannot use % pattern matching in the head, e.g. % as in det/2, noun/2, and verb/2. % If we split the parameter in the body, it works, see version 1 % go3 => All=findall(S1,$sentence1(S1,[])), writeln(All), writeln(len=All.length), nl. go4 => All=findall(S1,$sentence2(S1,[])), writeln(All), writeln(len=All.length), nl. go5 => All=findall(S1,$sentence3(S1,[])), writeln(All), writeln(len=All.length), nl. % % Note: This works only to check a sentence, % not for generate them. See below for variants to % do this % sentence(S1,S3) => noun_phrase(S1,S2), verb_phrase(S2,S3). noun_phrase(S1,S3) => det(S1,S2), noun(S2,S3). verb_phrase(S1,S3) => verb(S1,S2), noun_phrase(S2,S3). % Note: All but the last must be backtrackable (using ?=>) det([the|X], X2) ?=> X2 = X. det([a|X], X2) => X2 = X. noun([cat|X], X2) ?=> X2 = X. noun([bat|X], X2) => X2 = X. verb([eats|X], X2) => X2=X. % % Generate sentences, version 1, "DCG" % sentence1(S1,S3) => noun_phrase1(S1,S2), verb_phrase1(S2,S3). noun_phrase1(S1,S3) => det1(S1,S2), noun1(S2,S3). verb_phrase1(S1,S3) => verb1(S1,S2), noun_phrase1(S2,S3). % Note: All but the last must be backtrackable (using ?=>) det1(X1, X2) ?=> X1 = [the|X2]. det1(X1, X2) => X1 = [a|X2]. noun1(X1, X2) ?=> X1=[cat|X2]. noun1(X1, X2) => X1=[bat|X2]. verb1(X1, X2) ?=> X1=[eats|X2]. % % Generate sentences, version 2, using member % % Here we use member to generate the different alternatives % in det2/2, noun2/2, and verb2/2. sentence2(S1,S3) => noun_phrase2(S1,S2), verb_phrase2(S2,S3). noun_phrase2(S1,S3) => det2(S1,S2), noun2(S2,S3). verb_phrase2(S1,S3) => verb2(S1,S2), noun_phrase2(S2,S3). det2(X1, X2) => Dets = [the,a], member(Det,Dets), X1 = [Det|X2]. noun2(X1, X2) => Nouns = [cat,bat], member(Noun, Nouns), X1=[Noun|X2]. verb2(X1, X2) => Verbs = [eats,spots], member(Verb, Verbs), X1=[Verb|X2]. % % Generate sentences, version 3, using facts. % % Using facts, e.g. det3/1, noun3/1, and verb3/1 % for generating the alternatives sentence3(S1,S3) => noun_phrase3(S1,S2), verb_phrase3(S2,S3). noun_phrase3(S1,S3) => det3(S1,S2), noun3(S2,S3). verb_phrase3(S1,S3) => verb3(S1,S2), noun_phrase3(S2,S3). det3(X1, X2) => det3(Det), X1 = [Det|X2]. index(-) det3(the). det3(a). noun3(X1, X2) => noun3(Noun), X1=[Noun|X2]. index(-) noun3(cat). noun3(bat). noun3(dog). verb3(X1, X2) => verb3(Verb), X1=[Verb|X2]. index(-) verb3(eats). verb3(spots).