The defgrammar
macro can be used to define a definite clause grammar (DCG), which is a relation that determines whether the start of a list of tokens (a sentence) matches a particular grammar. The remaining tokens in the list become the sentence tail.
The relation has the form:
(<grammar name> <sentence> <sentence tail> <extra argument>*)
where the <extra argument>
items are terms defined below.
The syntax of the defgrammar macro is:
(defgrammar <grammar name> <rule>*) <rule> ::= (<lhs> <rhs>*) <lhs> ::= <grammar name> | (<grammar name> <term>*) | ((<grammar name> <term>*) <newterm>*) <rhs> ::= <atom> | <var> | (<other grammar name> <term>*) | <lisp clause> | (call <term>) | (cut) <lisp clause> ::= (<non-atomic lisp form> <term>*) <non-atomic lisp form> ::= (<lisp function name> <lisp arg>*)
<grammar name>
is the same symbol as the one naming the defgrammar.
<other grammar name>
is a symbol naming another defgrammar.
<atom>
is an atom, which forms the words of the sentence to be matched.
<var>
is a variable reference.
<term>
and <newterm>
are any Common Prolog logic expression, including a variable.
<lisp function name>
is a symbol naming a Lisp function.
<lisp arg>
is any Lisp form, which is evaluated and passed to the function.
Within the <lhs>
, extra arguments can be added by specifying <term>
s. Every <rule>
must specify the same <grammar name>
as the defgrammar
form and have the same number of extra arguments.
If the <lhs>
specifies <newterm>
forms, then they are pushed onto start of the sentence tail if the rule matches. This corresponds to the "pushback lists" or "right-hand context" in traditional Prolog DCG syntax.
The meaning of the various <rhs
> items is as follows:
<atom>
matches that atom in the sentence.<var>
is unified with the next item in the sentence.(<other grammar name> <term>*)
calls the grammar relation <other grammar name>
on the rest of the sentence. The optional <term>
arguments are passed to the relation as its extra arguments.<lisp clause>
evaluates the <non-atomic lisp form>
as a Lisp form and unifies the values that it returns with the <term>
s that follow it.(call <term>)
calls <term>
as a normal Prolog relation.(cut)
calls the normal Prolog cut relation.
The phrase
predicate can be used to call a DCG.
Here are some examples of using defgrammar
.
This example shows the Common Prolog translation of the grammar shown at the top of http://cs.union.edu/~striegnk/learn-prolog-now/html/node59.html
.
(defgrammar gram-det (gram-det the) (gram-det a)) (defgrammar gram-n (gram-n woman) (gram-n man)) (defgrammar gram-v (gram-v shoots)) (defgrammar gram-np (gram-np (gram-det) (gram-n))) (defgrammar gram-vp (gram-vp (gram-v) (gram-np)) (gram-vp (gram-v))) (defgrammar gram-s (gram-s (gram-np) (gram-vp)))
Note the use of symbols for terminals and lists for non-terminals. They all use the first form of the <lhs>
and have no extra terms on the <rhs>
, so all of the relations are binary.
The following will both succeed and bind ?x
to the list (foo bar)
:
(clog:any '?x '(gram-s (a woman shoots foo bar) ?x)) (clog:any '?x '(gram-s (a woman shoots the man foo bar) ?x))
(defgrammar one-of ((one-of ?word) ?word)) (defgrammar two-of ((two-of ?word) (one-of ?word) (one-of ?word)))
Each of these defines a 3-ary relation, whose extra argument is the word to match. When the relations are called, the word will typically be bound to a symbol from the sentence to match.
The following will succeed and bind ?x
to the list (foo bar)
:
(clog:any '?x '(two-of (start start foo bar) ?x start))
The following will both fail because the sentences do not begin with two start
symbols:
(clog:any '?x '(two-of (not-start start foo bar) ?x start)) (clog:any '?x '(two-of (start not-start foo bar) ?x start))
KnowledgeWorks and Prolog User Guide (Macintosh version) - 01 Dec 2021 19:35:39