%%% Grammar E1, a trivial fragment of English s --> np, vp. % A sentence (s) is a noun phrase (np) plus a verb phrase np --> det, n. % A noun phrase is a determiner plus a noun np --> n. % ... or just a noun. vp --> v, np. % A verb phrase is a verb and its direct object, an np vp --> v. % ... or just the verb (for intransitives). n --> [mary]. % 'mary', 'john', 'woman, 'man', 'apple' are nouns. n --> [john]. n --> [woman]. n --> [man]. n --> [apple]. det --> [the]. % 'the' is a determiner v --> [loves]. % 'loves', 'eats', and 'sings' are verbs. v --> [eats]. v --> [sings].This grammar generates sentences like "John loves Mary" and "The man sings" and "The woman eats the apple", as well as the somewhat less plausible "The apple sings the Mary."
?- listing([s,np,vp,n,det,v]).
s(A, B) :-
np(A, C),
vp(C, B).
np(A, B) :-
det(A, C),
n(C, B).
np(A, B) :-
n(A, B).
vp(A, B) :-
v(A, C),
np(C, B).
vp(A, B) :-
v(A, B).
n([mary|A], A).
n([john|A], A).
n([woman|A], A).
n([man|A], A).
n([apple|A], A).
det([the|A], A).
v([loves|A], A).
v([eats|A], A).
v([sings|A], A).
Yes
?-
?- s([john,loves,mary],[]). Yes ?- s([the,woman,eats,the,apple],[]). Yes ?- s([the,man,sings],[]). Yes ?- s([apple,eats,woman,the],[]). No ?- s([apple,sings,the,mary],[]). Yes ?-
?- s([the,woman,eats,the,apple],Remainder). Remainder = [] ; Remainder = [the, apple] ; No ?-In one parse, the entire input is parsed as a sentence, and the remainder is the empty list. An alternative parse, however, is just to take [the,woman,eats] as a sentence, leaving [the,apple] as the remainder.
s(
np(
pn(john)
),
vp(
v(loves),
np(
pn(mary)
)
)
)
On some productions, a second parameter is used to enforce
agreement in number between subject and verb and between
determiner and noun.
%%% E2: a trivial attribute grammar for a fragment of
%%% English, with a synthesized attribute for structural description
%%% and enforcement of number agreement.
s(s(S,P)) --> np(S,Num), vp(P,Num).
np(np(D,N),Num) --> det(D,Num), n(N,Num).
np(np(N),pl) --> n(N,pl).
np(np(N),sg) --> pn(N,sg).
vp(vp(V,O),Num) --> v(V,Num), np(O,_).
vp(vp(V),Num) --> v(V,Num).
n(n(L),Num) --> [L], { lex(L,n,Num) }.
pn(pn(L),Num) --> [L], { lex(L,pn,Num) }.
v(v(L),Num) --> [L], { lex(L,v,Num) }.
det(det(L),Num) --> [L], { lex(L,det,Num) }.
lex(mary,pn,sg).
lex(john,pn,sg).
lex(woman,n,sg).
lex(women,n,pl).
lex(man,n,sg).
lex(men,n,pl).
lex(apple,n,sg).
lex(apples,n,pl).
lex(the,det,_).
lex(some,det,pl).
lex(one,det,sg).
lex(loves,v,sg).
lex(love,v,pl).
lex(eats,v,sg).
lex(eat,v,pl).
lex(sings,v,sg).
lex(sing,v,pl).
n(n(L),Num) --> [L], { lex(L,n,Num)}.
These Prolog clauses express constraints on the grammatical
construction which are not themselves grammatical constituents. They
are sometimes called `guards' (e.g. by [Brown/Blair 1990]); they correspond directly to
the `semantic conditions' which are a constituent
part of attribute grammars as described by [Alblas 1991]. With the guard, this rule can be paraphrased as
saying "A noun (an n), has the structure
n(L) and the grammatical number Num,
if (a) L (for `lexical
form') is a single item in the input list [L],
and (b) the relation lex contains the triple
(L,n,Num)."?- s(Struc,[john,loves,mary],[]). Struc = s(np(pn(john)), vp(v(loves), np(pn(mary)))) Yes ?- s(S,[the,woman,eats,the,apple],[]). S = s(np(det(the), n(woman)), vp(v(eats), np(det(the), n(apple)))) Yes ?- s(S,[the,man,sings],[]). S = s(np(det(the), n(man)), vp(v(sings))) Yes ?- s(S,[apple,sings,the,mary],[]). No ?- s(S,[the,apple,sings,mary],[]). S = s(np(det(the), n(apple)), vp(v(sings), np(pn(mary)))) Yes ?-
[element(purchaseOrder,
[orderDate='1999-10-20'],
['\n ',
element(shipTo,
[country='US'],
['\n ',
element(name, [], ['Alice Smith']),
'\n ',
element(street, [], ['123 Maple Street']),
'\n ',
element(city, [], ['Mill Valley']),
'\n ',
element(state, [], ['CA']),
'\n ',
element(zip, [], ['90952']),
'\n '
]),
'\n ',
element(billTo,
[country='US'],
['\n ',
element(name, [], ['Robert Smith']),
'\n ',
element(street, [], ['8 Oak Avenue']),
'\n ',
element(city, [], ['Old Town']),
'\n ',
element(state, [], ['PA']),
'\n ',
element(zip, [], ['95819']),
'\n '
]),
'\n ',
element(comment, [], ['Hurry, my lawn is going wild!']),
'\n ',
element(items,
[],
['\n ',
element(item,
[partNum='872-AA'],
['\n ',
element(productName, [], ['Lawnmower']),
'\n ',
element(quantity, [], ['1']),
'\n ',
element('USPrice', [], ['148.95']),
'\n ',
element(comment,
[],
['Confirm this is electric']),
'\n ']),
'\n ',
element(item,
[partNum='926-AA'],
['\n ',
element(productName, [], ['Baby Monitor']),
'\n ',
element(quantity, [], ['1']),
'\n ',
element('USPrice', [], ['39.98']),
'\n ',
element(shipDate, [], ['1999-05-21']),
'\n '
]),
'\n '
]),
'\n'
])
]
purchaseOrder --> [element(purchaseOrder,Attributes,Content)],
{
purchaseOrderType_atts(Attributes,[]),
purchaseOrderType_cont(Content,[])
}.
shipTo --> [element(shipTo,Attributes,Content)],
{
usAddress_atts(Attributes,[]),
usAddress_cont(Content,[])
}.
billTo --> [element(billTo,Attributes,Content)],
{
usAddress_atts(Attributes,[]),
usAddress_cont(Content,[])
}.
items --> [element(items,Attributes,Content)],
{
t_items_atts(Attributes,[]),
t_items_cont(Content,[])
}.
item --> [element(item,Attributes,Content)],
{
t_item_atts(Attributes,[]),
t_item_cont(Content,[])
}.
comment --> [element(comment,Attributes,Content)],
{
xsd_string_atts(Attributes,[]),
xsd_string_cont(Content,[])
}.
But we know that the xsd:string type does not have
any attributes declared, so Attributes must be the
empty list. We can therefore define these elements this way
instead:
comment --> [element(comment,[],Content)],
{
xsd_string_cont(Content,[])
}.
poname --> [element(name,[],Content)], { xsd_string_cont(Content,[]) }.
street --> [element(street,[],Content)], { xsd_string_cont(Content,[]) }.
city --> [element(city,[],Content)], { xsd_string_cont(Content,[]) }.
state --> [element(state,[],Content)], { xsd_string_cont(Content,[]) }.
zip --> [element(zip,[],Content)], { xsd_decimal_cont(Content,[]) }.
productName --> [element(productName,[],Content)],
{ xsd_string_cont(Content,[]) }.
quantity --> [element(quantity,[],Content)],
{ xsd_integer_cont(Content,[]) }.
'USPrice' --> [element('USPrice',[],Content)],
{ xsd_decimal_cont(Content,[]) }.
shipDate --> [element(shipDate,[],Content)],
{ xsd_date_cont(Content,[]) }.
purchaseOrderType_atts --> []. purchaseOrderType_atts --> purchaseOrderType_att, purchaseOrderType_atts. purchaseOrderType_att --> [orderDate=Date]. usAddress_atts --> []. usAddress_atts --> usAddress_att, usAddress_atts. usAddress_att --> [country='US']. /* note: fixed value! */ t_items_atts --> []. t_items_atts --> t_items_att, t_items_atts. t_items_att --> no_such_attribute. /* note that t_items_att is undefined, since there * are no attributes for the Items type */ t_item_atts --> []. t_item_atts --> t_item_att, t_item_atts. t_item_att --> [partNum=SKU].
purchaseOrderType_cont --> shipTo, billTo, opt_comment, items.
opt_comment --> [].
opt_comment --> comment, opt_comment.
usAddress_cont --> poname, street, city, state, zip.
t_items_cont --> star_item.
star_item --> [].
star_item --> item, star_item.
t_item_cont --> productName, quantity, 'USPrice',
opt_comment, opt_shipDate.
opt_shipDate --> [].
opt_shipDate --> shipDate.
/* In our representation of XML, character data is represented * as atoms. Need to check on handling of non-ASCII characters */ xsd_string_cont([H|T],T) :- xsd_string_value(H). xsd_string_value(LF) :- atom(LF).
/* We'll accept anything as a decimal number if we can convert * the atom to a list of character codes which can in turn be * converted to a number. */ xsd_decimal_cont([H|T],T) :- xsd_decimal_value(H). xsd_decimal_value(LF) :- atom_codes(LF,L), number_codes(N,L). xsd_integer_cont([H|T],T) :- xsd_integer_value(H). xsd_integer_value(LF) :- atom_codes(LF,L), number_codes(N,L), integer(N).
xsd_date_cont([H|T],T) :- xsd_date_value(H). xsd_date_value(LF) :- atom(LF). /* well, we really need to check this ... */
purchaseOrderType_atts --> [].
purchaseOrderType_atts --> purchaseOrderType_att, purchaseOrderType_atts.
purchaseOrderType_att --> [orderDate=Date],
{ xsd_date_value(Date) }.
usAddress_atts --> [].
usAddress_atts --> usAddress_att, usAddress_atts.
usAddress_att --> [country='US']. /* note: fixed value! */
t_items_atts --> [].
t_items_atts --> t_items_att, t_items_atts.
t_items_att --> [no_such_attribute].
/* Since it has no equal sign or value, the rule for
* t_items_att will never match anything.
* Alternatively we could leave t_items_att undefined, since there
* are no attributes for the Items type.
*/
t_item_atts --> [].
t_item_atts --> t_item_att, t_item_atts.
t_item_att --> [partNum=SKU],
{ po_sku_value(SKU) }.
po_sku_value(LF) :- atom_chars(LF,Charseq), sku_value(Charseq,[]). sku_value --> sku_decimal_part, hyphen, sku_alpha_part. sku_decimal_part --> digit, digit, digit. sku_alpha_part --> cap_a_z, cap_a_z.
digit --> [Char], { char_type(Char,digit) }.
hyphen --> ['-'].
cap_a_z --> [Char], { char_type(Char,upper) }.
t_item_atts --> [partNum=SKU], { po_sku_value(SKU) }.
Or we could even put the constraint into the top-level rule for
the item element:
item --> [element(item,[partNum=SKU],Content)],
{
po_sku_value(SKU),
t_item_cont(Content,[])
}.
In the general case, however, it is going to be simpler to
put checking for required, forbidden, and defaulted attributes
into a separate rule, which we will here call
t_item_att_check:t_item_att_check(LAVS) :- atts_present(LAVS,[partNum]).
t_item_att_check(LAVS,AugmentedLAVS) :- atts_present(LAVS,[partNum]), atts_absent(LAVS,[]), atts_defaulted(LAVS,[],AugmentedLAVS).
atts_present(LAVS,[]).Continued in < Utilities for checking required attributes 14 > , < Utilities for checking required attributes 15 > , < Utilities for checking forbidden attributes 16 > , < Utilities for checking forbidden attributes 17 > , < Utilities for checking defaulted attributes 18 >
atts_present(LAVS,[HRA|RequiredTail]) :- att_present(LAVS,HRA), atts_present(LAVS,RequiredTail).
att_present([Attname=Attval|Tail],Attname). att_present([AVS|Tail],Attname) :- att_present(Tail,Attname).
att_present([],Attname) :- ...We don't have a rule for the empty list, though, because if we have run through the list of attribute-value specifications without finding one for the attribute name we are seeking, we want the predicate to fail. If necessary to prevent later maintenance programmers, or ourselves, from supplying the `missing' induction basis by mistake, we could write:
att_present([],Attname) :- !, fail.
atts_absent(LAVS,[]).
atts_absent(LAVS,[HFA|ForbiddenTail]) :- not(att_present(LAVS,HFA)), atts_absent(LAVS,ForbiddenTail).
atts_defaulted(LAVS,[],LAVS). atts_defaulted(LAVS,[AN=AV|Tail],AugmentedLAVS) :- att_present(LAVS,AN), atts_defaulted(LAVS,Tail,AugmentedLAVS). atts_defaulted(LAVS,[AN=AV|Tail],[AN=AV|AugmentedLAVS]) :- not(att_present(LAVS,AN)), atts_defaulted(LAVS,Tail,AugmentedLAVS).
bit ::= '0'. bit ::= '1'. bitstring ::= '' /* nothing */. bitstring ::= bit, bitstring. number ::= bitstring, fraction. fraction ::= '.', bitstring. fraction ::= ''.We might wish to calculate the length and the (unsigned base-two) value of the bitstring as attributes. Using a yacc-like notation that might look like this. Notice that scale is a top-down attribute and value and fractionalvalue are bottom-up attributes.
bit ::= '0' { $0.bitvalue = 0; }.
bit ::= '1' { $0.bitvalue = power(2,$0.scale); }.
bitstring ::= '' {
$0.value = 0;
$0.length = 0;
/* scale doesn't matter here */
}.
bitstring ::= bit, bitstring {
$0.length = $2.length + 1;
$1.scale = $0.scale;
$2.scale = $0.scale - 1;
$0.value = $1.value + $2.value;
}.
number ::= bitstring, fraction {
$1.scale = $1.length - 1;
$0.value = $1.value + $2.fractionalvalue;
}.
fraction ::= '.', bitstring {
$2.scale = -1;
$0.fractionalvalue = $2.value;
}.
fraction ::= '' {
$0.fractionalvalue = 0;
}.
bit ::= [0]
<:>
bitval(0,_).
bit ::= [1]
<:>
bitval(V,Scale) ::- V is **(2,Scale).
bitstring ::= []
<:>
length(0)
&&
value(0,_).
bitstring ::= bit^^B, bitstring^^B1
<:>
length(Length) ::-
B1 ^^ length(Length1),
Length is Length1 + 1
&&
value(Value,ScaleB) ::-
B ^^ bitval(VB,ScaleB),
S1 is ScaleB - 1,
B1 ^^ value(V1,S1),
Value is VB + V1.
number ::= bitstring ^^ B, fraction ^^ F
<:>
value(V) ::-
B ^^ length(Length),
S is Length-1,
B ^^ value(VB,S),
F ^^ fractional_value(VF),
V is VB + VF.
fraction ::= ['.'], bitstring ^^ B
<:>
fractional_value(V) ::-
S is -1,
B ^^ value(V,S).
fraction ::= []
<:>
fractional_value(0).
grammar ::= rule*
rule ::= lhs '::=' rhs ('<:>' att-spec ('&&' att-spec)*)?
lhs ::= term
rhs ::= term (',' term)*
attspec ::= compound-term ('::-' goal (',' goal)*)?
compound-term ::= ATOM '(' term (',' term)* ')'
%%% E1 (trivial context-free grammar for a fragment of English) %%% in DCTG notation. s ::= np, vp. np ::= det, n. np ::= n. vp ::= v, np. vp ::= v. n ::= [mary]. n ::= [john]. n ::= [woman]. n ::= [man]. n ::= [apple]. det ::= [the]. v ::= [loves]. v ::= [eats]. v ::= [sings].
?- dctg_reconsult('ks81dctg.pl').
Yes
?- listing([s,np,vp,n,det,v]).
:- dynamic s/3.
s(node(s, [A, B], []), C, D) :-
np(A, C, E),
vp(B, E, D).
:- dynamic np/3.
np(node(np, [A, B], []), C, D) :-
det(A, C, E),
n(B, E, D).
np(node(np, [A], []), B, C) :-
n(A, B, C).
:- dynamic vp/3.
vp(node(vp, [A, B], []), C, D) :-
v(A, C, E),
np(B, E, D).
vp(node(vp, [A], []), B, C) :-
v(A, B, C).
:- dynamic n/3.
n(node(n, [[mary]], []), A, B) :-
c(A, mary, B).
n(node(n, [[john]], []), A, B) :-
c(A, john, B).
n(node(n, [[woman]], []), A, B) :-
c(A, woman, B).
n(node(n, [[man]], []), A, B) :-
c(A, man, B).
n(node(n, [[apple]], []), A, B) :-
c(A, apple, B).
:- dynamic det/3.
det(node(det, [[the]], []), A, B) :-
c(A, the, B).
:- dynamic v/3.
v(node(v, [[loves]], []), A, B) :-
c(A, loves, B).
v(node(v, [[eats]], []), A, B) :-
c(A, eats, B).
v(node(v, [[sings]], []), A, B) :-
c(A, sings, B).
Yes
?-
The predicate dctg_reconsult(File) is used to
translate a DCTG grammar into Prolog clauses and load them;
it is provided by [Abramson/Dahl/Paine 1990] and
is available from a variety of sources on the net.[8]?- s(S,[john,loves,mary],[]), write(S).
node(s,
[node(np,
[node(n, [[john]], [])],
[]),
node(vp,
[node(v, [[loves]], []),
node(np,
[node(n, [[mary]], [])],
[])],
[])],
[])
S = node(s, [node(np, [node(n, [[john]], [])], []),
node(vp, [node(v, [[loves]], []), node(np, [node(n,
[...], [])], [])], [])], [])
Yes
?- s(S,[the,woman,eats,the,apple],[]), write(S).
node(s,
[node(np,
[node(det, [[the]], []),
node(n, [[woman]], [])],
[]),
node(vp,
[node(v, [[eats]], []),
node(np,
[node(det, [[the]], []),
node(n, [[apple]], [])],
[])],
[])],
[])
S = node(s, [node(np, [node(det, [[the]], []), node(n,
[[woman]], [])], []), node(vp, [node(v, [[eats]], []),
node(np, [node(det, [...], []), node(..., ..., ...)],
[])], [])], [])
Yes
?- s(S,[the,man,sings],[]), write(S).
node(s,
[node(np,
[node(det, [[the]], []),
node(n, [[man]], [])],
[]),
node(vp,
[node(v, [[sings]], [])],
[])],
[])
S = node(s, [node(np, [node(det, [[the]], []),
node(n, [[man]], [])], []), node(vp, [node(v,
[[sings]], [])], [])], [])
Yes
?-
s ::= np^^S, vp^^P,
{ S^^number(Num), P^^number(Num) }
<:>
{Attributes for non-terminal s 20}
Continued in < NP rules 21 > , < VP rules 26 > , < Pre-terminal rules 29 > , < Lexicon 30 >
structure(s(Sstr,Pstr)) ::-
S^^structure(Sstr),
P^^structure(Pstr).
np ::= det^^D, n^^N,
{ D^^number(Num), N^^number(Num) }
<:>
{NP structure attribute (for DET+N) 22}
&&
{NP number attribute (for DET+N) 23}
Continued in < NP rules, cont'd 24 > , < NP rules, cont'd 25 >
structure(np(Dstr,Nstr)) ::-
D^^structure(Dstr),
N^^structure(Nstr)
np ::= n^^N, { N^^number(pl) }
<:>
structure(np(Nstr)) ::-
N^^structure(Nstr)
&&
number(pl).
np ::= pn^^N, { N^^number(sg) }
<:>
structure(np(Nstr)) ::-
N^^structure(Nstr)
&&
number(sg).
vp ::= v^^V, np^^O
<:>
structure(vp(Vs,Os)) ::-
V^^structure(Vs),
O^^structure(Os)
&&
{Number attribute for VP 28}
Continued in < VP rules, cont'd 27 >
vp ::= v^^V
<:>
structure(vp(Vs)) ::-
V^^structure(Vs)
&&
{Number attribute for VP 28}
number(Num) ::- V^^number(Num).
n ::= [L], { lex(L,n,Num) }
<:>
structure(n(L))
&&
number(Num).
pn ::= [L], { lex(L,pn,Num) }
<:>
structure(pn(L))
&&
number(Num).
v ::= [L], { lex(L,v,Num) }
<:>
structure(v(L))
&&
number(Num).
det ::= [L], { lex(L,det,Num) }
<:>
structure(det(L))
&&
number(Num).
lex(mary,pn,sg). lex(john,pn,sg). lex(woman,n,sg). lex(women,n,pl). lex(man,n,sg). lex(men,n,pl). lex(apple,n,sg). lex(apples,n,pl). lex(the,det,_). lex(some,det,pl). lex(one,det,sg). lex(loves,v,sg). lex(love,v,pl). lex(eats,v,sg). lex(eat,v,pl). lex(sings,v,sg). lex(sing,v,pl).
?- s(S,[john,loves,mary],[]), write(S).
node(s,
[node(np,
[node(pn,
[[john]],
[structure(pn(john)),
(number(sg)::-lex(john, pn, sg))])],
[ (structure(np(_G292))::-
node(pn,
[[john]],
[structure(pn(john)),
(number(sg)::-lex(john, pn, sg))])^^structure(_G292)),
number(sg)]),
node(vp,
[node(v,
[[loves]],
[structure(v(loves)),
(number(sg)::-lex(loves, v, sg))]),
node(np,
[node(pn,
[[mary]],
[structure(pn(mary)),
(number(sg)::-lex(mary, pn, sg))])],
[(structure(np(_G424))::-
node(pn, [[mary]],
[structure(pn(mary)),
(number(sg)::-lex(mary, pn, sg))])
^^structure(_G424)),
number(sg)])],
[ (structure(vp(_G351, _G352))::-
node(v, [[loves]],
[structure(v(loves)),
(number(sg)::-lex(loves, v, sg))])^^structure(_G351),
node(np,
[node(pn, [[mary]],
[structure(pn(mary)),
(number(sg)::-lex(mary, pn, sg))])],
[(structure(np(_G424))::-
node(pn, [[mary]],
[structure(pn(mary)),
(number(sg)::-lex(mary, pn, sg))])
^^structure(_G424)),
number(sg)])^^structure(_G352)),
(number(_G373)::-
node(v, [[loves]],
[structure(v(loves)),
(number(sg)::-lex(loves, v, sg))])^^number(_G373))])],
[(structure(s(_G261, _G262))::-
node(np,
[node(pn, [[john]],
[structure(pn(john)),
(number(sg)::-lex(john, pn, sg))])],
[(structure(np(_G292))::-
node(pn, [[john]],
[structure(pn(john)),
(number(sg)::-lex(john, pn, sg))])^^structure(_G292)),
number(sg)])^^structure(_G261),
node(vp, [node(v, [[loves]],
[structure(v(loves)),
(number(sg)::-lex(loves, v, sg))]),
node(np,
[node(pn, [[mary]],
[structure(pn(mary)),
(number(sg)::-lex(mary, pn, sg))])],
[(structure(np(_G424))::-
node(pn, [[mary]],
[structure(pn(mary)),
(number(sg)::-lex(mary, pn, sg))])
^^structure(_G424)),
number(sg)])],
[(structure(vp(_G351, _G352))::-
node(v, [[loves]],
[structure(v(loves)),
(number(sg)::-lex(loves, v, sg))])
^^structure(_G351),
node(np, [node(pn, [[mary]],
[structure(pn(mary)),
(number(sg)::-lex(mary, pn, sg))])],
[(structure(np(_G424))::-
node(pn, [[mary]],
[structure(pn(mary)),
(number(sg)::-lex(mary, pn, sg))])
^^structure(_G424)),
number(sg)])^^structure(_G352)),
(number(_G373)::-
node(v, [[loves]],
[structure(v(loves)),
(number(sg)::-lex(loves, v, sg))])
^^number(_G373))])
^^structure(_G262))])
b --> [element(b,Attributes,Content)],
{
b_atts(Attributes,[]),
b_cont(Content,[])
}.
a --> [element(a,Attributes,Content)],
{
a_atts(Attributes,[]),
a_cont(Content,[])
}.
and also
b --> [element(a,Attributes,Content)],
{
a_atts(Attributes,[]),
a_cont(Content,[])
}.
Abramson, Harvey. 1984. "Definite Clause Translation Grammars". Proceedings of the 1984 International Symposium on Logic Programming, Atlantic City, New Jersey, February 6-9, 1984, pp. 233-240. (IEEE-CS 1984, ISBN 0-8186-0522-7)
Abramson, Harvey, and Veronica Dahl. 1989. Logic Grammars. Symbolic Computation AI Series. Springer-Verlag, 1989.
Abramson, Harvey, and Veronica Dahl, rev. Jocelyn Paine. 1990. DCTG: Prolog definite clause translation grammar translator. (Prolog code for translating from DCTG notation to standard Prolog. Note says syntax extended slightly by Jocelyn Paine to accept && between specifications of grammatical attributes, to minimize need for parentheses. Available from numerous AI/NLP software repositotries, including http://www-2.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/prolog/code/syntax/dctg/0.html, http://www.ims.uni-stuttgart.de/ftp/pub/languages/prolog/libraries/imperial_college/dctg.tar.gz, and http://www.ifs.org.uk/~popx/prolog/dctg/.)
Alblas, Henk. 1991. "Introduction to attribute grammars". Attribute grammars, applications and systems: International Summer School SAGA, Prague, Czechoslovakia, June 4-13, 1991, Proceedings, pp. 1-15. Berlin: Springer, 1991. Lecture Notes in Computer Science, 545.
Bratko, Ivan. 1990. Prolog programming for artificial intelligence. Second edition. Wokingham: Addison-Wesley. xxi, 597 pp.
Brown, Allen L., Jr., and Howard A. Blair. 1990. "A logic grammar foundation for document representation and layout". In EP90: Proceedings of the International Conference on Electronic Publishing, Document Manipulation and Typography, ed. Richard Furuta. Cambridge: Cambridge University Press, 1990, pp. 47-64.
Brown, Allen L., Jr., Toshiro Wakayama, and Howard A. Blair. 1992. "A reconstruction of context-dependent document processing in SGML". In EP92: Proceedings of Electronic Publishing, 1992, ed. C. Vanoirbeek and G. Coray. Cambridge: Cambridge University Press, 1992. Pages 1-25.
Brüggemann-Klein, Anne. 1993. Formal models in document processing. Habilitationsschrift, Freiburg i.Br., 1993. 110 pp. Available at ftp://ftp.informatik.uni-freiburg.de/documents/papers/brueggem/habil.ps (Cover pages archival copy also at http://www.oasis-open.org/cover/bruggDissert-ps.gz).
Clocksin, W. F., and C. S. Mellish. Programming in Prolog. Second edition. Berlin: Springer, 1984.
Gal, Annie, Guy Lapalme, Patrick Saint-Dizier, and Harold Somers. 1991. Prolog for natural language processing. Chichester: Wiley, 1991. xiii, 306 pp.
Gazdar, Gerald, and Chris Mellish. 1989. Natural language processing in PROLOG: An introduction to computational linguistics. Wokingham: Addison-Wesley, 1989. xv, 504 pp.
Grune, Dick, and Ceriel J. H. Jacobs. 1990. Parsing techniques: a practical guide. New York, London: Ellis Horwood, 1990. Postscript of the book is available from the first author's Web site at http://www.cs.vu.nl/~dick/PTAPG.html
Knuth, D. E. 1968. "Semantics of context-free languages". Mathematical Systems Theory 2: 127-145.
König, Esther, and Roland Seiffert. Grundkurs PROLOG für Linguisten. Tübingen: Francke, 1989. [= Uni-Taschenbücher 1525]
Stepney, Susan. High-integrity compilation. Prentice-Hall. Available from http://www-users.cs.york.ac.uk/~susan/bib/ss/hic/index.htm. Chapter 3 (Using Prolog) provides a terse introduction to DCTG notation and use.
[W3C 2001] "XML Schema Part 0: Primer", ed. David Fallside. W3C Recommendation, 2 May 2001. [Cambridge, Sophia-Antipolis, Tokyo: W3C] http://www.w3.org/TR/xmlschema-0/.
[W3C 2001] 2001. XML Schema Part 1: Structures, ed. Henry S. Thompson, David Beech, Murray Maloney, and Noah Mendelsohn. W3C Recommendation 2 May 2001. [Cambridge, Sophia-Antipolis, and Tokyo]: World Wide Web Consortium. http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/
[W3C 2001] W3C. 2001. XML Schema Part 2: Datatypes, ed. Biron, Paul V. and Ashok Malhotra. W3C Recommendation 2 May 2001. [Cambridge, Sophia-Antipolis, and Tokyo]: World Wide Web Consortium. http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/
Wielemaker, Jan. "SWI-Prolog SGML/XML parser: Version 1.0.14, March 2001". http://www.swi-prolog.org/packages/sgml2pl.html
['d:/usr/lib/prolog/http_open']. % load the library
http_open('http://www.w3.org/2001/XMLSchema.xsd',XSDStream),
load_xml_file(stream(XSDStream),XSD),
close(XSDStream).