Question

I've inserted the given context free grammar into the database using assert(....) If the grammar is something like

S-->a,S,b
S-->c

This grammar is inserted into the database. I have to write a dcg to generate sentences for the cfg in the database. For example if i define the dcg in this way myDcg('S',str), the 'S'(non terminal) should be called or substituted by aSb or c|d or so.

The problem is how can i call/substitute 'S' by facts from the database each time a non terminal('S') is encountered to generate sentences.

Hope you understood my question, if not i will try to edit the question.


Below(Sample code) is what i wanted to do exactly This is not dcg.

myGrammar([], []):-!.

myGrammar([T|Rest], [T|Sentence]):-
          myGrammar(Rest, Sentence).

myGrammar([NT|Rest], Sentence):-
          grammar(NT, Rest1),
          append(Rest1,Rest, NewRest),
          myGrammar(NewRest, Sentence). 

Whenever a terminal is encountered it should be printed out and when a non terminal is encountered it will backtrack.

Was it helpful?

Solution

In your predicate mygrammar/2 there is a list of non-terminals and terminals in the first argument and a list of terminals in the second. It should probably succeed if the second argument is of the form of the first. So what you have here essentially is a meta interpreter for DCGs. A few suggestions:

Your tokenizer produces currently [grammar('S',[a,'S',b]),grammar('S',[....]),..]. Let it produce [grammar('S',[t(a),nt('S'),t(b)]),grammar('S',[....]),..] instead. In this manner it's evident what is a terminal and what is a non-terminal. And, oh, remove that !.

myGrammar([], []).
myGrammar([t(T)|Rest], [T|Sentence]):-
   myGrammar(Rest, Sentence).
myGrammar([nt(NT)|Rest], Sentence):-
   grammar(NT, Rest1),
   append(Rest1,Rest, NewRest),
   myGrammar(NewRest, Sentence).

DCGs, btw are a bit more general than this interpreter.

The actual classification between non-terminals and terminals has to be done by the tokenizer.

uppercasecode(C) :-
   between(0'A,0'Z,C).

lowercasecode(C) :-
   between(0'a,0'z,C).

If you are using chars (one-character atoms), you will use char_code(Char, Code) to convert between them.

Full Unicode support is still in its infancy. Its very tricky because of all those special cases for characters like Ⓐ which is upper case but still cannot be part of an identifier. But here is how you can do it in SWI currently.

uppercasecode(C) :-
   '$code_class'(C,upper),
   '$code_class'(C,id_start).

lowercasecode(C) :-
   '$code_class'(C,id_start),
   '$code_class'(C,id_continue),
   \+ '$code_class'(C,upper).

Update: In the meantime, there is char_type/2 and code_type/2 for this purpose.

uppercasecode(C) :-
   code_class(C, upper),
   code_class(C, prolog_var_start).

OTHER TIPS

I assume that you started with Prolog recently. Yes, you can assert things into the database, but this isn't the common thing you do in the first place. You will want to use that feature much later when you feel safe with the base language.

What you typically do is to write a grammar into a file like myfirstgrammar.pl and then load that file into your Prolog system.

Please refer to this recent thread for details concerning the grammar.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top