%%% 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('http://www.example.com/PO1':purchaseOrder, [xmlns:apo='http://www.example.com/PO1', orderDate='1999-10-20'], [element(shipTo, [country='US'], [element(name, [], ['Alice Smith']), element(street, [], ['123 Maple Street']), element(city, [], ['Mill Valley']), element(state, [], ['CA']), element(zip, [], ['90952']) ]), element(billTo, [country='US'], [element(name, [], ['Robert Smith']), element(street, [], ['8 Oak Avenue']), element(city, [], ['Old Town']), element(state, [], ['PA']), element(zip, [], ['95819']) ]), element('http://www.example.com/PO1':comment, [], ['Hurry, my lawn is going wild!'] ), element(items, [], [element(item, [partNum='872-AA'], [element(productName, [], ['Lawnmower']), element(quantity, [], ['1']), element('USPrice', [], ['148.95']), element('http://www.example.com/PO1':comment, [], ['Confirm this is electric'] ) ]), element(item, [partNum='926-AA'], [element(productName, [], ['Baby Monitor']), element(quantity, [], ['1']), element('USPrice', [], ['39.98']), element(shipDate, [], ['1999-05-21']) ]) ]) ]) ]
/* Definite-clause grammar for the XML Schema represented in po.xsd. * * This DCG was generated by a literate programming system; if * maintenance is necessary, make changes to the source (dctgnotes.xml), * not to this output file. */ purchaseOrder --> [element('http://www.example.com/PO1':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('http://www.example.com/PO1':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('http://www.example.com/PO1':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. See note 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 --> [this_will_never_match]. /* 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) }.
<xsd:simpleType name="SKU"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{3}-[A-Z]{2}"/> </xsd:restriction> </xsd:simpleType>The pattern can be translated readily into the following grammar operating on the character sequence of the lexical form:
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).
purchaseOrderType_att --> magic_att. usAddress_att --> magic_att. t_items_att --> magic_att. t_item_att --> magic_att. magic_att --> [xmlns=NS]. magic_att --> [xmlns:Pre=NS]. magic_att --> ['http://www.w3.org/2001/XMLSchema-instance':Localname=Value].
<apo:comment>Hurry, my lawn is going wild!</apo:comment> <apo:comment>I don't know how much longer I can hold out.</apo:comment>This is an error in the grammar above, which has been retained to illustrate the risks of hand-translation. Instead of
opt_comment --> []. opt_comment --> comment, opt_comment.(which allows arbitrarily many comments), the rule for the optional comment element should read
opt_comment --> []. opt_comment --> comment.
<apo:purchaseOrder xmlns:apo="http://www.example.com/PO1" orderDate="1999-10-19" orderDate="1999-10-20">(this can be blamed on the upstream processor, which should probably have rejected the document without producing an infoset, since single occurrence of attribute names is a well-formedness constraint)
<item partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>100</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item>
<item> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item>
<zip>OX2 6NN</zip>
<quantity>one</quantity>
<USPrice>USD 39.98</USPrice>
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.[11]
?- 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))])
nt ::= [element(n:gi,Attributes,Content)], { ct_atts(A,NA,Attributes), ct_cont(C,Content,[]) } <:> attributes(A) && namespaceAttributes(NA) && children(C) && localName(gi) && namespacename(n) && type_definition_anonymous(Boolean) && type_definition_namespace(URI) && type_definition_name(NCName) && type_definition_type(complex) && validation_attempted(full) && validity(valid) .Later, we will add further grammatical attributes, and use values other than full and valid for invalid elements.
/* e_purchaseOrder: grammatical rule for purchaseOrder element. e_purchaseOrder(ParsedNode,L1,L2): holds if the difference between L1 and L2 (difference lists) is a purchase order element in SWI Prolog notation. And so on for the other element types. */ e_purchaseOrder ::= [element('http://www.example.com/PO1':purchaseOrder, Attributes,Content)], { t_PurchaseOrderType_atts(A,NA,Attributes), t_PurchaseOrderType_cont(C,Content,[]) } <:> localname(purchaseOrder) && type_definition_anonymous('false') && type_definition_namespace('http://www.example.com/PO1') && type_definition_name('PurchaseOrderType') && type_definition_type(complex) {Common infoset properties for elements in po namespace 32} . e_shipTo ::= [element(shipTo,Attributes,Content)], { t_USAddress_atts(A,NA,Attributes), t_USAddress_cont(C,Content,[]) } <:> localname(shipTo) && type_definition_anonymous('false') && type_definition_namespace('http://www.example.com/PO1') && type_definition_name('USAddress') && type_definition_type(complex) {Common infoset properties for elements in po namespace 32} . e_billTo ::= [element(billTo,Attributes,Content)], { t_USAddress_atts(A,NA,Attributes), t_USAddress_cont(C,Content,[]) } <:> localname(billTo) && type_definition_anonymous('false') && type_definition_namespace('http://www.example.com/PO1') && type_definition_name('USAddress') && type_definition_type(complex) {Common infoset properties for elements in po namespace 32} . e_items ::= [element(items,Attributes,Content)], { t_Items_atts(A,NA,Attributes), t_Items_cont(C,Content,[]) } <:> localname(items) && type_definition_anonymous('false') && type_definition_namespace('http://www.example.com/PO1') && type_definition_name('Items') && type_definition_type(complex) {Common infoset properties for elements in po namespace 32} . e_item ::= [element(item,Attributes,Content)], { t_item_atts(A,NA,Attributes), t_item_cont(C,Content,[]) } <:> localname(item) && type_definition_anonymous('true') && type_definition_namespace('http://www.example.com/PO1') && type_definition_name('t_item') && type_definition_type(complex) {Common infoset properties for elements in po namespace 32} .
&& attributes(A) && namespaceattributes(NA) && children(C) && namespacename('http://www.example.com/PO1') && validationattempted(full) && validity(valid)
e_comment ::= [element('http://www.example.com/PO1':comment,Attributes,Content)], {Guard to check attributes and content of strings 34} <:> localname(comment) {Common infoset properties for elements in po namespace 32} {PSVI properties for strings 35} . e_name ::= [element(name,Attributes,Content)], {Guard to check attributes and content of strings 34} <:> localname(name) {Common infoset properties for elements in po namespace 32} {PSVI properties for strings 35} . e_street ::= [element(street,Attributes,Content)], {Guard to check attributes and content of strings 34} <:> localname(street) {Common infoset properties for elements in po namespace 32} {PSVI properties for strings 35} . e_city ::= [element(city,Attributes,Content)], {Guard to check attributes and content of strings 34} <:> localname(city) {Common infoset properties for elements in po namespace 32} {PSVI properties for strings 35} . e_state ::= [element(state,Attributes,Content)], {Guard to check attributes and content of strings 34} <:> localname(state) {Common infoset properties for elements in po namespace 32} {PSVI properties for strings 35} . e_zip ::= [element(zip,Attributes,Content)], { sT_atts(A,Attributes,[]), xsd_decimal_cont(C,Content,[]) } <:> localname(zip) {Common infoset properties for elements in po namespace 32} {PSVI properties for decimals 36} . e_productName ::= [element(productName, Attributes,Content)], {Guard to check attributes and content of strings 34} <:> localname(productName) {Common infoset properties for elements in po namespace 32} {PSVI properties for strings 35} . e_quantity ::= [element(quantity, Attributes,Content)], { sT_atts(A,Attributes,[]), t_quantity_cont(C,Content,[]) } <:> localname(quantity) {Common infoset properties for elements in po namespace 32} && type_definition_anonymous('true') && type_definition_namespace('http://www.example.com/PO1') && type_definition_name('t_quantity') && type_definition_type(simple) . e_USPrice ::= [element('USPrice',Attributes,Content)], { sT_atts(A,Attributes,[]), xsd_decimal_cont(C,Content,[]) } <:> localname('USPrice') {Common infoset properties for elements in po namespace 32} {PSVI properties for decimals 36} . e_shipDate ::= [element(shipDate,Attributes,Content)], { sT_atts(A,Attributes,[]), xsd_date_cont(C,Content,[]) } <:> localname(shipDate) {Common infoset properties for elements in po namespace 32} && type_definition_anonymous('false') && type_definition_namespace('http://www.w3.org/2001/XMLSchema') && type_definition_name('date') && type_definition_type(simple) .
{ sT_atts(A,Attributes,[]), xsd_string_cont(C,Content,[]) }
&& type_definition_anonymous('false') && type_definition_namespace('http://www.w3.org/2001/XMLSchema') && type_definition_name('string') && type_definition_type(simple)
&& type_definition_anonymous('false') && type_definition_namespace('http://www.w3.org/2001/XMLSchema') && type_definition_name('decimal') && type_definition_type(simple)
dt_atts(Lpa,Lpna,Lavs) :- lavs_dt(LpaAll,Lavs,[]), /* parse against grammar of attributes */ partition(LpaAll,LpaPresent,Lpna), /* partition the result */ attocc_dt(LpaPresent,Lpa). /* check min, max occurrence rules */The logical variables have the following meanings:
lavs_dt ::= []. lavs_dt ::= avs_dt, lavs_dt. /* declared attributes */ lavs_dt ::= avs_nsd, lavs_dt. /* namespace declarations */ lavs_dt ::= avs_xsi, lavs_dt. /* XSI attributes */ avs_dt ::= [an1=Av], { st1_value(Av) }. avs_dt ::= [an2=Av], { st2_value(Av) }.Simple types will, of course, have no declared attributes, and the rules for declared attributes and occurrence-checking (together with the rules for individual attributes) will be omitted. Wildcard support can also be added here when needed.
/* avs_nsd: grammatical rule for namespace-attribute specifications */ avs_nsd ::= [xmlns=DefaultNS] <:> localname(xmlns) && namespacename('http://www.w3.org/2000/xmlns/') && normalizedvalue(DefaultNS). avs_nsd ::= [xmlns:Prefix=NSName] <:> localname(Prefix) && namespacename('http://www.w3.org/2000/xmlns/') && normalizedvalue(NSName). /* avs_nsd: grammatical rule for XSI attribute specifications */ avs_xsi ::= ['http://www.w3.org/2001/XMLSchema-instance':Localname=Value] <:> localname(Localname) && namespacename('http://www.w3.org/2001/XMLSchema-instance') && normalizedvalue(Value).
attocc_dt(LpaPres,LpaAll) :- atts_present(LpaPres,Lreq), atts_absent(LpaPres,Lnot), atts_defaulted(LpaPres,Ldft,LpaAll).
/* atts_present(Lpa,Lreq): true if a parsed attribute node is present in Lpa for each attribute name in Lreq */ atts_present(LAVS,[]). atts_present(LAVS,[HRA|RequiredTail]) :- att_present(LAVS,HRA), atts_present(LAVS,RequiredTail). /* An attribute name matches if namespace and local part match */ /* att_present(Lpa,Attname): true if a parsed attribute node is present in Lpa which has name Attname */ att_present([Pa|Lpa],NS:Attname) :- Pa^^localname(Attname), Pa^^namespacename(NS). att_present([Pa|Lpa],Attname) :- att_present(Lpa,Attname). /* no base step: if we reach att_present([],Attname) we want to fail. */
/* atts_absent(Lpa,Ltabu): true if no attribute named in Ltabu is present in Lpa */ atts_absent(LAVS,[]). atts_absent(LAVS,[H|T]) :- not(att_present(LAVS,H)), atts_absent(LAVS,T).
/* atts_defaulted(L1,L2,L3): true if L3 has all the attributes in L1, plus all of the attributes in L2 which are not also in L1 */ atts_defaulted(Lpa,[],Lpa). atts_defaulted(Lpa,[Padft|Ldft],LpaAll) :- atts_defaulted(Lpa,Ldft,Lpa2), att_merge(Lpa2,Padft,LpaAll).Continued in <Utility for providing defaulted attributes 41>
/* att_merge(L1,Pa,L2): if Pa is present in L1, then L3 = L1, otherwise L3 = L1 + Pa. */ att_merge([],Padft,[Padft]). att_merge([Pa|Lpa],Padft,[Pa|Lpa]) :- nonvar(Pa), nonvar(Lpa), nonvar(Padft), Pa^^namespacename(NS), Padft^^namespacename(NS), Pa^^localname(Lnm), Padft^^localname(Lnm). att_merge([Pa|Lpa],Padft,Lpa2) :- nonvar(Pa), nonvar(Lpa), nonvar(Padft), not( {Pa^^namespacename(NS), Padft^^namespacename(NS), Pa^^localname(Lnm), Padft^^localname(Lnm) } ), att_merge(Lpa,Padft,Lpa2).
/* t_TYPENAME_atts(Lpa,Lpna,Lavs): true if Lavs contains an input-form list of attribute specifications which is legal for complex type TYPENAME, and which corresponds to the list of parsed attributes Lpa plus the list of parsed namespace attributes Lpna. */ t_PurchaseOrderType_atts(Lpa,Lpna,Lavs) :- lavs_t_PurchaseOrderType(LpaAll,Lavs,[]), partition(LpaAll,LpaPres,Lpna), attocc_t_PurchaseOrderType(LpaPres,Lpa). lavs_t_PurchaseOrderType ::= [] {Grammatical attributes for empty attribute list 48} . lavs_t_PurchaseOrderType ::= avs_t_PurchaseOrderType^^Pa, lavs_t_PurchaseOrderType^^Lpa {Grammatical attributes for attribute-list recursion 49} . lavs_t_PurchaseOrderType ::= avs_nsd^^Pa, lavs_t_PurchaseOrderType^^Lpa {Grammatical attributes for attribute-list recursion 49} . lavs_t_PurchaseOrderType ::= avs_xsi^^Pa, lavs_t_PurchaseOrderType^^Lpa {Grammatical attributes for attribute-list recursion 49} . avs_t_PurchaseOrderType ::= [orderDate=Value], { ws_normalize(collapse,Value,SNValue), xsd_date_value(SNValue) } {Properties for orderDate attribute 50} . /* Literally copying the pattern would give us this: attocc_t_PurchaseOrderType(LpaPres,LpaAll) :- atts_present(LpaPres,[]), atts_absent(LpaPres,[]), atts_defaulted(LpaPres,[],LpaAll). but that's pointless. Instead, we'll do the equivalent: */ attocc_t_PurchaseOrderType(L,L).
/* ws_normalize(Keyword,Input,Output): true if Output is an atom identical to the whitespace-normalized form of Input, with the whitespace mode indicated by Keyword. */ ws_normalize(preserve,Atom,Atom).Continued in <Utility for whitespace normalization 44>, <Utility for whitespace normalization 46>
ws_normalize(replace,In,Out) :- atom_codes(In,Lcin), ws_blanks(Lcin,Lcout), atom_codes(Out,Lcout).
/* ws_blanks(A,B): where A has any whitespace, B has a blank */ ws_blanks([],[]). ws_blanks([9|T1],[32|T2]) :- ws_blanks(T1,T2). ws_blanks([10|T1],[32|T2]) :- ws_blanks(T1,T2). ws_blanks([13|T1],[32|T2]) :- ws_blanks(T1,T2). ws_blanks([H|T1],[H|T2]) :- not(member(H,[9,10,13])), ws_blanks(T1,T2).
ws_normalize(collapse,In,Out) :- ws_normalize(replace,In,Temp), atom_codes(Temp,Lctemp), ws_collapse(Lctemp,Lcout), atom_codes(Out,Lcout).Continued in <Utility to change whitespace characters to blanks 45>, <Utility for collapsing whitespace 47>
/* ws_collapse(A,B): B is like A, with all strings of blanks collapsed * to single blanks, and leading and trailing blanks stripped. * ws_collapse/2 strips leading blanks, then calls ws_collapse/3 */ ws_collapse([],[]). ws_collapse([32|T1],T2) :- ws_collapse(T1,T2). ws_collapse([H|T1],[H|T2]) :- not(H=32), ws_collapse(internal,T1,T2). /* ws_collapse/3 walks past non-blanks, and when it hits a string * of blanks, it drops all but the last one before a non-blank. */ ws_collapse(internal,[],[]). ws_collapse(internal,[32],[]). ws_collapse(internal,[H|T1],[H|T2]) :- not(H=32), ws_collapse(internal,T1,T2). ws_collapse(internal,[32,32|T1],T2) :- ws_collapse(internal,[32|T1],T2). ws_collapse(internal,[32,H|T1],[32,H|T2]) :- not(H=32), ws_collapse(internal,T1,T2).
<:> attributes([])
<:> attributes([Pa|L]) ::- Lpa^^attributes(L)
<:> localname('orderDate') && namespacename('') && normalizedvalue(SNValue) && type_definition_anonymous('false') && type_definition_namespace('http://www.w3.org/2001/XMLSchema') && type_definition_name('date') && type_definition_type(simple) && schemaspecified(schema) && validationattempted(full) && validity(valid)
t_USAddress_atts(Lpa,Lpna,Lavs) :- lavs_t_USAddress(LpaAll,Lavs,[]), partition(LpaAll,LpaPres,Lpna), attocc_t_USAddress(LpaPres,Lpa). lavs_t_USAddress ::= [] {Grammatical attributes for empty attribute list 48} . lavs_t_USAddress ::= avs_t_USAddress^^Pa, lavs_t_USAddress^^Lpa {Grammatical attributes for attribute-list recursion 49} . lavs_t_USAddress ::= avs_nsd^^Pa, lavs_t_USAddress^^Lpa {Grammatical attributes for attribute-list recursion 49} . lavs_t_USAddress ::= avs_xsi^^Pa, lavs_t_USAddress^^Lpa {Grammatical attributes for attribute-list recursion 49} . avs_t_USAddress ::= [country='US'] <:> localname('country') && namespacename('') && normalizedvalue('US') && type_definition_anonymous('false') && type_definition_namespace('http://www.w3.org/2001/XMLSchema') && type_definition_name('NMTOKEN') && type_definition_type(simple) && schemaspecified(schema) && validationattempted(full) && validity(valid) .Continued in <Attribute occurrence checking for USAddress 52>
attocc_t_USAddress(LpaPresent,LpaAll) :- CountryAtt = node( attribute(country), [], [ (namespacename('')), (localname('country')), (normalizedvalue('US')), (type_definition_anonymous('false')), (type_definition_namespace('http://www.w3.org/2001/XMLSchema')), (type_definition_name('NMTOKEN')), (type_definition_type(simple)), (schemaspecified(schema)), (validationattempted(full)), (validity(valid)), ]), atts_defaulted(LpaPres,[CountryAtt],LpaAll).
t_Items_atts(Lpa,Lpna,Lavs) :- lavs_t_Items(LpaAll,Lavs,[]), partition(LpaAll,LpaPres,Lpna). lavs_t_Items ::= [] {Grammatical attributes for empty attribute list 48} . lavs_t_Items ::= avs_nsd^^Pa, lavs_t_Items^^Lpa {Grammatical attributes for attribute-list recursion 49} . lavs_t_Items ::= avs_xsi^^Pa, lavs_t_Items^^Lpa {Grammatical attributes for attribute-list recursion 49} .
t_item_atts(Lpa,Lpna,Lavs) :- lavs_t_item(LpaAll,Lavs,[]), partition(LpaAll,LpaPres,Lpna), attocc_t_item(LpaPres,Lpa). lavs_t_item ::= [] {Grammatical attributes for empty attribute list 48} . lavs_t_item ::= avs_t_item^^Pa, lavs_t_item^^Lpa {Grammatical attributes for attribute-list recursion 49} . lavs_t_item ::= avs_nsd^^Pa, lavs_t_item^^Lpa {Grammatical attributes for attribute-list recursion 49} . lavs_t_item ::= avs_xsi^^Pa, lavs_t_item^^Lpa {Grammatical attributes for attribute-list recursion 49} .Continued in <PartNum attribute 55>
avs_t_item ::= [partNum=Value], { t_SKU_value(Value) } <:> localname('partNum') && namespacename('') && normalizedvalue(Value) && type_definition_anonymous('false') && type_definition_namespace('http://www.example.com/PO1') && type_definition_name('SKU') && type_definition_type(simple) && schemaspecified(schema) && validationattempted(full) && validity(valid) . /* one required attribute: partNum */ attocc_t_item(LpaPres,LpaAll) :- atts_present(LpaPres,['':partNum]), atts_absent(LpaPres,[]), atts_defaulted(LpaPres,[],LpaAll).
sT_atts(Lpa,Lpna,Lavs) :- lavs_sT(LpaAll,Lavs,[]), partition(LpaAll,LpaPres,Lpna). lavs_sT ::= [] {Grammatical attributes for empty attribute list 48} . lavs_sT ::= avs_nsd^^Pa, lavs_t_Items^^Lpa {Grammatical attributes for attribute-list recursion 49} . lavs_sT ::= avs_xsi^^Pa, lavs_t_Items^^Lpa {Grammatical attributes for attribute-list recursion 49} .
partition(LpaAll,LpaPresent,Lpna) :- LpaAll^^attributes(L), partition2(L,LpaPresent,Lpna). partition2([],[],[]). partition2([Pa|Lpa],LpaPres,[Pa|Lpna]) :- Pa^^localname(xmlns), partition2(Lpa,LpaPres,Lpna). partition2([Pa|Lpa],LpaPres,[Pa|Lpna]) :- Pa^^namespacename('http://www.w3.org/2000/xmlns/'), partition2(Lpa,LpaPres,Lpna). partition2([Pa|Lpa],[Pa|LpaPres],Lpna) :- not(Pa^^localname(xmlns)), not(Pa^^namespacename('http://www.w3.org/2000/xmlns/')), partition2(Lpa,LpaPres,Lpna).
t_PurchaseOrderType_cont ::= e_shipTo^^S, e_billTo^^B, opt_e_comment^^C, e_items^^I {Children attribute of t_PurchaseOrder 62} . opt_e_comment ::= [] {Empty list of children for opt_e_comment nonterminal 60} . opt_e_comment ::= e_comment^^Comm {Children for opt_e_comment nonterminal 61} . t_USAddress_cont ::= e_name^^N, e_street^^S, e_city^^C, e_state^^ST, e_zip^^Z {Children attribute of t_USAddress 59} . t_Items_cont ::= star_e_item^^L {Children attribute of t_Items_cont 66} . star_e_item ::= [] {Empty list of children for star_e_item nonterminal 67} . star_e_item ::= e_item^^I, star_e_item^^L {Children for star_e_item nonterminal 68} . t_item_cont ::= e_productName^^PN, e_quantity^^Q, e_USPrice^^USP, opt_e_comment^^C, opt_e_shipDate^^S {Children attribute of t_item 63} . opt_e_shipDate ::= [] {Empty list of children for opt_e_shipdate nonterminal 64} . opt_e_shipDate ::= e_shipDate^^S {Children for opt_e_shipdate nonterminal 65} .
<:> children([N,S,C,ST,Z])
<:> children([])
<:> children([Comm])
<:> children(Lpe) ::- C^^children(CC), flatten([S,B,CC,I],Lpe)
<:> children(Lpe) ::- C^^children(CC), S^^children(SC), flatten([PN,Q,USP,CC,SC],Lpe)
<:> children([])
<:> children([S])
<:> children(List) ::- L^^children(List)
<:> children([])
<:> children([I|T]) ::- L^^children(T)
xsd_string_cont ::= [Atom], { xsd_string_value(Atom) }. xsd_decimal_cont ::= [Atom], { xsd_decimal_value(Atom) }. xsd_integer_cont ::= [Atom], { xsd_integer_value(Atom) }. xsd_date_cont ::= [Atom], { xsd_date_value(Atom) }.
/* In our representation of XML, character data is represented * as atoms. Handling of non-ASCII characters is OK if they are * in UTF8, but the SWI parser currently has trouble with * some named entity references to non-ASCII characters */ xsd_string_value(LF) :- atom(LF).Continued in <Checking decimal and integer values 71>, <Checking date values 72>, <Lexical form for year 73>, <Lexical form for month 76>, <Lexical form for day of month 77>, <Checking date values 78>, <Checking date values 79>
xsd_decimal_value(LF) :- atom_chars(LF,L), lexform_decimal(_,L,[]). xsd_integer_value(LF) :- atom_chars(LF,L), lexform_integer(_,L,[]). lexform_decimal ::= lexform_integer, fractionalpart. lexform_integer ::= opt_sign, digits. fractionalpart ::= []. fractionalpart ::= decimalpoint. fractionalpart ::= decimalpoint, opt_digits. opt_sign ::= []. opt_sign ::= ['+']. opt_sign ::= ['-']. decimalpoint ::= ['.']. opt_digits ::= []. opt_digits ::= digits. /* We supply a 'lexval' property on digits, for use in date checking */ digits ::= digit^^D <:> lexval([Dv]) ::- D^^lexval(Dv). digits ::= digit^^D1, digits^^Dd <:> lexval([D1val|Ddval]) ::- D1^^lexval(D1val), Dd^^lexval(Ddval). digit ::= [Ch], { char_type(Ch,digit) } <:> lexval(Ch).
xsd_date_value(LF) :- atom_chars(LF,LC), lexform_date(_,LC,[]). lexform_date ::= year^^Y, hyphen, month^^M, hyphen, day^^D, { Y^^val(Yv), M^^val(Mv), D^^val(Dv), dateok(Yv,Mv,Dv) }.
/* Years must have at least four digits */ yearnum ::= digit^^D1, digit^^D2, digit^^D3, digits^^Dd <:> val(Num) ::- D1^^lexval(Dv1), D2^^lexval(Dv2), D3^^lexval(Dv3), Dd^^lexval(Dv4), flatten([Dv1,Dv2,Dv3,Dv4],LF), number_chars(Num,LF). year ::= yearnum^^Y <:> val(Num) ::- Y^^val(Num). year ::= ['-'], yearnum^^Y <:> val(Num) ::- Y^^val(N), Num is 0 - N. hyphen ::= ['-'].
month ::= ['0'], ['1']. month ::= ['0'], ['2']. ... month ::= ['0'], ['9']. month ::= ['1'], ['0']. month ::= ['1'], ['1']. month ::= ['1'], ['2'].
month ::= ['0'], digit^^D { D^^lexval(Dv), number_chars(V,Dv), V > 0 } <:> val(V). month ::= ['1'], digit^^D { D^^lexval(Dv), number_chars(V,Dv), V < 3 } <:> val(Val) ::- Val is 10 + V.
month ::= digit^^D1, digit^^D2, { D1^^lexval(Dv1), D2^^lexval(Dv2), number_chars(Num,[Dv1,Dv2]), Num > 0, Num < 13 } <:> val(Num).
day ::= digit^^D1, digit^^D2, { D1^^lexval(Dv1), D2^^lexval(Dv2), number_chars(Num,[Dv1,Dv2]), Num > 0, Num < 32 } <:> val(Num).
dateok(_Y,_M,D) :- D < 29. dateok(_Y,M,29) :- M =\= 2. dateok(_Y,M,30) :- M =\= 2. dateok(_Y,M,31) :- member(M,[1,3,5,7,8,10,12]). dateok(Y,2,29) :- (Y >= 0 -> Yx = Y ; Yx is Y + 1), /* adjust for BC */ 0 is Yx mod 4, Lc is Yx mod 100, L4c is Yx mod 400, leapyearcheck(Lc,L4c).
leapyearcheck(C,_Q) :- C =\= 0. /* it's not a century year, so leapyear */ leapyearcheck(0,0). /* it's a quad-century year, so leapyear */
t_SKU_cont ::= [Atom], { t_SKU_value(Atom) }. t_quantity_cont ::= [Atom], { t_quantity_value(Atom) }.
t_SKU_value(LF) :- atom_chars(LF,Charseq), lexform_sku(_Structure,Charseq,[]). lexform_sku ::= sku_decimal_part, hyphen, sku_alpha_part. sku_decimal_part ::= digit, digit, digit. sku_alpha_part ::= cap_a_z, cap_a_z. cap_a_z ::= [Char], { char_type(Char,upper) }.Continued in <Value-checking rules for quantities 82>
t_quantity_value(LF) :- atom_chars(LF,Lchars), lexform_integer(_,Lchars,[]), number_chars(Num,Lchars), Num < 100.
/* podctg.pl: a definite-clause translation grammar representation * of the sample purchase-order schema from the XML Schema tutorial. * * This DCTG was generated by a literate programming system; if * maintenance is necessary, make changes to the source (dctgnotes.xml), * not to this output file. */ {Predicates for purchase-order material 84} {Generic utilities for DCTG-encoded schemas 85}
{Rules for elements with complex types 31} {Rules for elements with simple types 33} {Attribute handling for purchaseOrderType 42} {Attribute handling for USAddress 51} {Attribute handling for Items type 53} {Attribute handling for t_item 54} {Attribute handling for simple types 56} {Rules for purchase-order content models 58} {Simple-type content rules for purchase-order types 80} {Value-checking rules for SKU 81}
{Grammar rules for namespace and XSI attributes 37} {Utilities for checking attribute occurrences 38} {Utility for checking absent attributes 39} {Utility for providing defaulted attributes 40} {Utility for whitespace normalization 43} {partition predicate 57} {xsd_Typename_cont rules 69} {xsd_Typename_value rules 70}
t_USAddress_cont ::= e_name^^N, e_street^^S, e_city^^C, e_state^^ST, e_zip^^Z <:> children([N,S,C,ST,Z]).In some cases, the grammar will have several rules, to cover repetitions and choices.
TN_atts(Lpa,Lpna,Lavs) :- lavs_TN(LpaAll,Lavs,[]), /* parse against grammar of attributes */ partition(LpaAll,LpaPresent,Lpna), /* partition the result */ attocc_TN(LpaPresent,Lpa). /* check min, max occurrence rules */
e_NCName ::= [element(NS:GI,Attributes,Content)], { t_TN_atts(A,NA,Attributes), t_TN_cont(C,Content,[]) } <:> attributes(A) && namespaceAttributes(NA) /* etc. */ .When the element has a simple type, the pattern is identical except that it uses a standard sT_atts predicate instead of t_TN_atts.
t_TN_cont ::= [Atom], { t_TN_value(Atom) }.
t_TN_value(LF) :- atom_chars(LF,Charseq), lexform_TN(_Structure,Charseq,[]) /* additional value checks */ .
lexform_sku ::= sku_decimal_part, hyphen, sku_alpha_part. sku_decimal_part ::= digit, digit, digit. sku_alpha_part ::= cap_a_z, cap_a_z. cap_a_z ::= [Char], { char_type(Char,upper) }.
nt ::= [element(n:gi,Attributes,Content)], { ct_atts(A,NA,Attributes), ct_cont(C,Content,[]) } <:> attributes(A) && namespaceAttributes(NA) && children(C) && localname(gi) && namespacename(n).the rule pattern should read
nt ::= [element(n:gi,Attributes,Content)], { ct_atts(A,NA,Attributes), ct_cont(C,Content,[]), C^^children(Ch) } <:> attributes(A) && namespaceAttributes(NA) && children(Ch) && localname(gi) && namespacename(n).or else the attribute-value assignment should read differently: not
&& children(C)but
&& children(Ch) ::- C^^children(Ch)
sva_purchaseOrder_children(Children,Parsed,valid) :- t_PurchaseOrderType_cont(Parsed,Content,[]). sva_purchaseOrder_children(Children,Parsed, invalid(cvc-complex-type.2.4)) :- not(t_PurchaseOrderType_cont(C,Content,[])), sva_lax(Parsed,Children,[]).where the predicate sva_lax(-Result,+Input,+-Remainder) performs lax validation on Input, returning a Result node.
elemdecl(e_purchaseOrder, '/element(purchaseOrder)', purchaseOrder, 'http://www.example.com/PO1', global, [ (id(e_purchaseOrder)), (scd('/element(po:purchaseOrder)')), (name(purchaseOrder)), (target_namespace('http://www.example.com/PO1')), (type_definition(t_PurchaseOrderType)), (scope(keyword(global))), (value_constraint(keyword(absent))), (nillable(false)), (identity_constraint_definitions([])), (substitution_group_affiliation(keyword(absent))), (disallowed_substitutions([])), (substitution_group_exclusions([])), (abstract(false)), (annotation(keyword(absent))) ]).
(target_namespace('http://www.example.com/PO1')), (value_constraint(keyword(absent))), (nillable(false)), (identity_constraint_definitions([])), (substitution_group_affiliation(keyword(absent))), (disallowed_substitutions([])), (substitution_group_exclusions([])), (abstract(false)), (annotation(keyword(absent)))
elemdecl(e_comment, '/element(comment)', comment, 'http://www.example.com/PO1', global, [ (id(e_comment)), (scd('/element(po:comment)')), (name(comment)), (type_definition(t_string)), (scope(keyword(global))), {Common properties 87} ]).
elemdecl(e_shipTo, '/complexType(po:PurchaseOrderType)/sequence()/element(shipTo)', shipTo, 'http://www.example.com/PO1', local, [ (id(e_shipTo)), (scd('/complexType(po:PurchaseOrderType)/sequence()/element(shipTo)')), (name(shipTo)), (type_definition(t_USAddress)), (scope(t_PurchaseOrderType)), {Common properties 87} ]).
elemdecl(e_billTo, '/complexType(po:PurchaseOrderType)/sequence()/element(billTo)', billTo, 'http://www.example.com/PO1', local, [ (id(e_billTo)), (scd('/complexType(po:PurchaseOrderType)/sequence()/element(billTo)')), (name(billTo)), (type_definition(t_USAddress)), (scope(t_PurchaseOrderType)), {Common properties 87} ]).
elemdecl(e_items, '/complexType(po:PurchaseOrderType)/sequence()/element(items)', e_items, 'http://www.example.com/PO1', local, [ (id(e_items)), (scd('/complexType(po:PurchaseOrderType)/sequence()/element(items)')), (name(items)), (type_definition(t_Items)), (scope(t_PurchaseOrderType)), {Common properties 87} ]).
elemdecl(e_name, '/complexType(po:USAddress)/sequence()/element(name)', name, 'http://www.example.com/PO1', local, [ (id(e_name)), (scd('/complexType(po:USAddress)/sequence()/element(name)')), (name(name)), (type_definition(t_string)), (scope(t_USAddress)), {Common properties 87} ]).
elemdecl(e_street, '/complexType(po:USAddress)/sequence()/element(street)', street, 'http://www.example.com/PO1', local, [ (id(e_street)), (scd('/complexType(po:USAddress)/sequence()/element(street)')), (name(street)), (type_definition(t_string)), (scope(t_USAddress)), {Common properties 87} ]).
elemdecl(e_city, '/complexType(po:USAddress)/sequence()/element(city)', city, 'http://www.example.com/PO1', local, [ (id(e_city)), (scd('/complexType(po:USAddress)/sequence()/element(city)')), (name(city)), (type_definition(t_string)), (scope(t_USAddress)), {Common properties 87} ]).
elemdecl(e_state, '/complexType(po:USAddress)/sequence()/element(state)', state, 'http://www.example.com/PO1', local, [ (id(e_state)), (scd('/complexType(po:USAddress)/sequence()/element(state)')), (name(state)), (type_definition(t_string)), (scope(t_USAddress)), {Common properties 87} ]).
elemdecl(e_zip, '/complexType(po:USAddress)/sequence()/element(zip)', zip, 'http://www.example.com/PO1', local, [ (id(e_zip)), (scd('/complexType(po:USAddress)/sequence()/element(zip)')), (name(zip)), (type_definition(t_decimal)), (scope(t_USAddress)), {Common properties 87} ]).
elemdecl(e_item, '/complexType(po:Items)/sequence()/element(item)', item, 'http://www.example.com/PO1', local, [ (id(e_item)), (scd('/complexType(po:Items)/sequence()/element(item)')), (name(item)), (type_definition(t_item)), (scope(t_Items)), {Common properties 87} ]).
elemdecl(e_productName, '/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(productName)', productName, 'http://www.example.com/PO1', local, [ (id(e_productName)), (scd('/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(productName)')), (name(productName)), (type_definition(t_string)), (scope(t_item)), {Common properties 87} ]).
elemdecl(e_quantity, '/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(quantity)', quantity, 'http://www.example.com/PO1', local, [ (id(e_quantity)), (scd('/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(quantity)')), (name(quantity)), (type_definition(t_quantity)), (scope(t_item)), {Common properties 87} ]).
elemdecl(e_USPrice, '/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(USPrice)', 'USPrice', 'http://www.example.com/PO1', local, [ (id(e_USPrice)), (scd('/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(USPrice)')), (name('USPrice')), (type_definition(t_decimal)), (scope(t_item)), {Common properties 87} ]).
elemdecl(e_shipDate, '/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(shipDate)', shipDate, 'http://www.example.com/PO1', local, [ (id(e_shipDate)), (scd('/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(shipDate)')), (name(shipDate)), (type_definition(t_date)), (scope(t_item)), {Common properties 87} ]).
complextype(t_PurchaseOrderType, '/complexType(po:PurchaseOrderType)', 'PurchaseOrderType', 'http://www.example.com/PO1', global, [ (id(t_PurchaseOrderType)), (scd('/complexType(po:PurchaseOrderType)')), (anonymous(false)), (name('PurchaseOrderType')), (target_namespace('http://www.example.com/PO1')), (base_type_definition(t_urtype)), (derivation_method(restriction)), (final([])), (abstract(false)), (attribute_uses([ au(required(false), attdecl(a_purchaseOrder_orderDate), value_constraint(keyword(absent))) ])), (attribute_wildcard(keyword(absent))), (content_type(c(t_PurchaseOrderType_cont,element-only))), (prohibited_substitutions([])), (annotations(keyword(absent))) ]).
attdecl(a_PurchaseOrderType_orderDate, '/complexType(po:PurchaseOrderType)/attribute(orderDate)', orderDate, 'http://www.example.com/PO1', local, [ (name(orderDate)), (target_namespace('http://www.example.com/PO1')), (type_definition(t_date)), (scope(t_PurchaseOrderType)), (value_constraint(keyword(absent))), (annotation(keyword(absent))) ]).
complextype(t_USAddress,'/complexType(po:USAddress)', 'USAddress', 'http://www.example.com/PO1', global, [ (id(t_USAddress)), (scd('/complexType(po:USAddress)')), (anonymous(false)), (name('USAddress')), (target_namespace('http://www.example.com/PO1')), (base_type_definition(t_urtype)), (derivation_method(restriction)), (final([])), (abstract(false)), (attribute_uses([ au(required(false), attdecl(a_USAddress_country), value_constraint(keyword(absent))) ])), (attribute_wildcard(keyword(absent))), (content_type(c(t_USAddress_cont,element-only))), (prohibited_substitutions([])), (annotations(keyword(absent))) ]).
attdecl(a_USAddress_country, '/complexType(po:USAddress)/attribute(country)', country, 'http://www.example.com/PO1', local, [ (name(country)), (target_namespace('http://www.example.com/PO1')), (type_definition(t_NMTOKEN)), (scope(t_USAddress)), (value_constraint(fixed('US'))), (annotation(keyword(absent))) ]).
complextype(t_Items,'/complexType(po:Items)', 'Items', 'http://www.example.com/PO1', global, [ (id(t_Items)), (scd('/complexType(po:Items)')), (name('Items')), (target_namespace('http://www.example.com/PO1')), (base_type_definition(t_urtype)), (derivation_method(restriction)), (final([])), (abstract(false)), (attribute_uses([])), (attribute_wildcard(keyword(absent))), (content_type(c(t_Items_cont,element-only))), (prohibited_substitutions([])), (annotations(keyword(absent))) ]).
complextype(t_item, '/complexType(po:Items)/sequence()/element(item)/complexType() ', t_item, 'http://www.example.com/PO1', [ (id(t_item)), (scd('/complexType(po:PurchaseOrderType)')), (anonymous(true)), (name('PurchaseOrderType')), (target_namespace('http://www.example.com/PO1')), (base_type_definition(t_urtype)), (derivation_method(restriction)), (final([])), (abstract(false)), (attribute_uses([ au(required(true), attdecl(a_item_partNum), value_constraint(keyword(absent))) ])), (attribute_wildcard(keyword(absent))), (content_type(c(t_item_cont,element-only))), (prohibited_substitutions([])), (annotations(keyword(absent))) ]).
attdecl(a_item_partNum, '/complexType(po:Items)/sequence()/element(item)/complexType()/attribute(partNum)', partNum, 'http://www.example.com/PO1', local, [ (name(partNum)), (target_namespace('http://www.example.com/PO1')), (type_definition(t_sku)), (scope(t_item)), (value_constraint(keyword(absent))), (annotation(keyword(absent))) ]).
simpletype(TypeID, SCD, TypeName, TargetNS, LocalGlobal [ (id(TypeID)), (scd(SCD)), (anonymous(true|false)), (name(TypeName)), (target_namespace(TargetNS)), (variety( atomic|list|union )), (primitive_type_definition( TypeID_P )), (item_type_definition( TypeID_I )), (member_type_definitions([ TypeID_M, TypeID_M2, ... ])), (facets(ListOfFacets)), (fundamental_facets(ListOfFundamentals)), (base_type_definition(t_simpleurtype)), (final([restriction, list, union])), (annotation(keyword(absent))) ]).
length(value(V), fixed(Bool), annotation()), minLength(value(V), fixed(Bool), annotation()), maxLength(value(V), fixed(Bool), annotation()), pattern(value(V), annotation(), dctg_rule()), enumeration(value([Vs]), annotation()), whiteSpace( value(preserve|replace|collapse), fixed(Bool), annotation()), maxInclusive(value(V), fixed(Bool), annotation()), maxExclusive(value(V), fixed(Bool), annotation()), minInclusive(value(V), fixed(Bool), annotation()), minExclusive(value(V), fixed(Bool), annotation()), totalDigits(value(V), fixed(Bool), annotation()), fractionDigits(value(V), fixed(Bool), annotation())
ordered(false|partial|total), bounded(true|false), cardinality(finite|countable), numeric(true|false)
simpletype(t_simpleurtype, 'simpleType(anySimpleType)', anySimpleType, 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_simpleurtype)), (scd('simpleType(xsd:anySimpleType)')), (anonymous(true)), (name(anySimpleType)), (target_namespace('http://www.w3.org/2001/XMLSchema')), (base_type_definition(t_urtype)), (facets([])), (final([])), (variety(keyword(absent))), (primitive_type_definition(keyword(absent))), (item_type_definition(keyword(absent))), (member_type_definitions(keyword(absent))), (annotation(keyword(absent))) ]).
complextype(t_urtype, '/complexType(xsd:anyType)', 'anyType', 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_urtype)), (scd('/complexType(xsd:anyType)')), (anonymous(false)), (name('anyType')), (target_namespace('http://www.w3.org/2001/XMLSchema')), (base_type_definition(keyword(absent))), /* perhaps the base type definition should be t_urtype */ (derivation_method(keyword(absent))), (final([])), (abstract(false)), (attribute_uses([ au(required(false), attdecl(a_urtype_), value_constraint(keyword(absent))) ])), (attribute_wildcard(keyword(absent))), (content_type(c(t_urtype_cont,mixed))), (prohibited_substitutions([])), (annotations(keyword(absent))) ]).
attdecl(a_urtype_, '/complexType(xsd:anyType)/anyAttribute()', 'keyword(any)', 'http://www.w3.org/2001/XMLSchema', local, [ (name(partNum)), (target_namespace('http://www.example.com/PO1')), (type_definition(t_sku)), (scope(t_item)), (value_constraint(keyword(absent))), (annotation(keyword(absent))) ]).
simpletype(t_string, '/simpleType(xsd:string)', string, 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_string)), (scd('/simpleType(xsd:string)')), (anonymous(false)), (name(string)), (target_namespace('http://www.w3.org/2001/XMLSchema')), (variety(atomic)), (primitive_type_definition( t_string )), (item_type_definition( keyword(absent) )), (member_type_definitions([])), (facets([ whiteSpace(value(preserve), fixed(false), annotation(keyword(absent))) ])), (fundamental_facets([ ordered(false), bounded(false), cardinality(countable), numeric(false) ])), (base_type_definition(t_simpleurtype)), (final([])), (annotation(keyword(absent))) /* This is not true: like all builtins, string does have * annotation in the schema for schemas. But I don't have * any particular use for it, so I'm omitting it for now. */ ]).
simpletype(t_normalizedString, '/simpleType(xsd:normalizedString)', normalizedString, 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_normalizedString)), (scd('/simpleType(xsd:normalizedString)')), (anonymous(false)), (name(normalizedString)), (target_namespace('http://www.w3.org/2001/XMLSchema')), (variety(atomic)), (primitive_type_definition( t_string )), (item_type_definition( keyword(absent) )), (member_type_definitions([])), (facets([ whiteSpace(value(replace), fixed(false), annotation(keyword(absent))) ])), (fundamental_facets([ ordered(false), bounded(false), cardinality(countable), numeric(false) ])), (base_type_definition(t_string)), (final([])), (annotation(keyword(absent))) ]).
simpletype(t_token, '/simpleType(xsd:token)', token, 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_token)), (scd('/simpleType(xsd:token)')), (anonymous(false)), (name(token)), (target_namespace('http://www.w3.org/2001/XMLSchema')), (variety(atomic)), (primitive_type_definition( t_string )), (item_type_definition( keyword(absent) )), (member_type_definitions([])), (facets([ whiteSpace(value(collapse), fixed(false), annotation(keyword(absent))) ])), (fundamental_facets([ ordered(false), bounded(false), cardinality(countable), numeric(false) ])), (base_type_definition(t_normalizedString)), (final([])), (annotation(keyword(absent))) ]).
simpletype(t_NMTOKEN, '/simpleType(xsd:NMTOKEN)', 'NMTOKEN', 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_NMTOKEN)), (scd('/simpleType(xsd:NMTOKEN)')), (anonymous(false)), (name('NMTOKEN')), (target_namespace('http://www.w3.org/2001/XMLSchema')), (variety(atomic)), (primitive_type_definition( t_string )), (item_type_definition( keyword(absent) )), (member_type_definitions([])), (facets([ whiteSpace(value(collapse), fixed(false), annotation(keyword(absent))), pattern(value('\c+'), annotation(keyword(absent)), dctg_rule(t_string)) /* actually, the pattern does have annotation, but I have * no use for it at the moment */ ])), (fundamental_facets([ ordered(false), bounded(false), cardinality(countable), numeric(false) ])), (base_type_definition(t_token)), (final([])), (annotation(keyword(absent))) ]).
simpletype(t_SKU, 'simpleType(po:SKU)', 'SKU', 'http://www.example.com/PO1', global, [ (id(t_SKU)), (scd('simpleType(po:SKU)')), (anonymous(false)), (name('SKU')), (target_namespace('http://www.example.com/PO1')), (variety(atomic)), (primitive_type_definition(t_string)), (item_type_definition(keyword(absent))), (member_type_definitions([])), (facets([ whiteSpace(value(preserve), fixed(false), annotation(keyword(absent))) pattern(value('\d{3}-[A-Z]{2}'), annotation(keyword(absent)), dctg_rule(t_SKU)) ])), (fundamental_facets([ ordered(false), bounded(false), cardinality(countable), numeric(false) ])), (base_type_definition(t_string)), (final([])), (annotation(keyword(absent))) ]).
simpletype(t_decimal, 'simpleType(xsd:decimal)', decimal, 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_decimal)), (scd('simpleType(xsd:decimal)')), (anonymous(false)), (name(decimal)), (target_namespace('http://www.w3.org/2001/XMLSchema')), (variety(atomic)), (primitive_type_definition(t_decimal)), (item_type_definition(keyword(absent))), (member_type_definitions([])), (facets([ whiteSpace(value(collapse), fixed(true), annotation(keyword(absent))) ])), (fundamental_facets([ ordered(total), bounded(false), cardinality(countable), numeric(true) ])), (base_type_definition(t_simpleurtype)), (final([])), (annotation(keyword(absent))) ]).
simpletype(t_integer, 'simpleType(xsd:integer)', integer, 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_integer)), (scd('simpleType(xsd:integer)')), (anonymous(false)), (name(integer)), (target_namespace('http://www.w3.org/2001/XMLSchema')), (variety(atomic)), (primitive_type_definition(t_decimal)), (item_type_definition(keyword(absent))), (member_type_definitions([])), (facets([ whiteSpace(value(collapse), fixed(true), annotation(keyword(absent))), fractionDigits(value(0), fixed(true), annotation(keyword(absent))) ])), (fundamental_facets([ ordered(total), bounded(false), cardinality(countable), numeric(true) ])), (base_type_definition(t_decimal)), (final([])), (annotation(keyword(absent))) ]).
simpletype(t_nonNegativeInteger, 'simpleType(xsd:nonNegativeInteger)', nonNegativeInteger, 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_nonNegativeInteger)), (scd('simpleType(xsd:nonNegativeInteger)')), (anonymous(false)), (name(nonNegativeInteger)), (target_namespace('http://www.w3.org/2001/XMLSchema')), (variety(atomic)), (primitive_type_definition(t_decimal)), (item_type_definition(keyword(absent))), (member_type_definitions([])), (facets([ whiteSpace(value(collapse), fixed(true), annotation(keyword(absent))), fractionDigits(value(0), fixed(true), annotation(keyword(absent))) minInclusive(value(0), fixed(false), annotation(keyword(absent))) ])), (fundamental_facets([ ordered(total), bounded(false), cardinality(countable), numeric(true) ])), (base_type_definition(t_integer)), (final([])), (annotation(keyword(absent))) ]).
simpletype(t_positiveInteger, 'simpleType(xsd:positiveInteger)', positiveInteger, 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_positiveInteger)), (scd('simpleType(xsd:positiveInteger)')), (anonymous(false)), (name(positiveInteger)), (target_namespace('http://www.w3.org/2001/XMLSchema')), (variety(atomic)), (primitive_type_definition(t_decimal)), (item_type_definition(keyword(absent))), (member_type_definitions([])), (facets([ whiteSpace(value(collapse), fixed(true), annotation(keyword(absent))), fractionDigits(value(0), fixed(true), annotation(keyword(absent))) minInclusive(value(1), fixed(false), annotation(keyword(absent))) ])), (fundamental_facets([ ordered(total), bounded(false), cardinality(countable), numeric(true) ])), (base_type_definition(t_nonNegativeInteger)), (final([])), (annotation(keyword(absent))) ]).
simpletype(t_quantity, '/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(quantity)/simpleType()', t_quantity, 'http://www.example.com/PO1', local, [ (id(t_quantity)), (scd('/complexType(po:Items)/sequence()/element(item)/complexType()/sequence()/element(quantity)/simpleType()')), (anonymous(true)), (name(t_quantity)), (target_namespace('http://www.example.com/PO1')), (variety(atomic)), (primitive_type_definition(t_decimal)), (item_type_definition(keyword(absent))), (member_type_definitions(keyword(absent))), (facets([ /* from decimal */ whiteSpace( value(collapse), fixed(true), annotation(keyword(absent))), /* from integer */ fractionDigits(value(0), fixed(true), annotation(keyword(absent))), /* from nonnegativeInteger, later overridden */ /* minInclusive(value(0), fixed(false), annotation(keyword(absent))), */ /* from positiveInteger */ minInclusive(value(1), fixed(false), annotation(keyword(absent))), /* from final derivation step for quantity */ maxExclusive(value(100), fixed(false), annotation(keyword(absent))), ])), (fundamental_facets([ ordered(total), bounded(true), cardinality(finite), numeric(true) ])), (base_type_definition(t_positiveInteger)), (final([])), (annotation(keyword(absent))) ]).
simpletype(t_date, 'simpleType(xsd:date)', date, 'http://www.w3.org/2001/XMLSchema', global, [ (id(t_date)), (scd('simpleType(xsd:date)')), (anonymous(true)), (name(date)), (target_namespace('http://www.w3.org/2001/XMLSchema')), (variety(atomic)), (primitive_type_definition(t_date)), (item_type_definition(keyword(absent))), (member_type_definitions([])), (facets([ whiteSpace(value(collapse), fixed(true), annotation(keyword(absent))) ])), (fundamental_facets([ ordered(partial), bounded(false), cardinality(countable), numeric(false) ])), (base_type_definition(t_simpleurtype)), (final([])), (annotation(keyword(absent))) ]).
sva_content_st_TN(Gi,Lin,Lpn,[]) :- sva_st_lf_TN(TN,Lin,[]). sva_content_st_TN(Gi,Lin,Lpn,[ElemError,LfError|Errors]) :- sva_st_lf_TN(TN,Lin,[LfError|Errors]), ElemError = error(cvc-type.3.1.3).
sva_content_st(Tn,Gi,[Atom],Lpn,Lerr) :- sva_st_lf(Tn,Atom,Le), ( Le = [] -> Lerr = [] ; append([error(cvc-type.3.1.3,'Bad content')],Le,Lerr) ).This is an improvement on the corresponding predicates of layer 3, but it's not finished: (1) this predicate should also handle empty elements, (2) it should check for elements among the children, and (3) the error reporting should have something more than a keyword. The full definition of sva_content_st is found below (Validation of elements).
/* xsd_errorcode(+Sym,+String,+Typename,-Desc): Desc is the string describing the error whose error code is Sym, when it occurs with respect to the string String being validated against type Typename. */ xsd_errorcode(cvc-simple-type,String,Typename,Desc) :- concat_atom(['The string "',String, '" is not locally valid w.r.t. the given simple type ', Typename,'.'], Desc). xsd_errorcode(cvc-datatype-valid.1,S,T,Desc) :- concat_atom(['The lexical form "',S, '" is not datatype-valid w.r.t. the given simple type ', T,': it matches no literal in the lexical space.'], Desc). xsd_errorcode(cvc-datatype-valid.2,S,T,Desc) :- concat_atom(['The lexical form "',S, '" is not datatype-valid w.r.t. the given simple type ', T,': it denotes a value not in the value space.'], Desc).Continued in <Error code for pattern failures 130>, <Error code for pattern failures 137>, <Error code for pattern failures 139>, <Error code for enumeration failures 141>, <Error codes for elements with simple types 152>
/* sva_st_lf(Tn,PreLF,Lerr): true iff validating pre-lexical form PreLF against simple type Tn produces list of errors Lerr. */ sva_st_lf(Tid,LF,Lerr) :- {Get type information about simple type Tid 125} {Normalize white space to create lexical form 126} {Check lexical form against grammar for primitive type 127} {Check lexical form against patterns for type Tid 128} {Check value against all facets of type Tid 131}
simpletype(Tid,Tscd,Tname,Ttargetns,Tglobal,Tprops),
Tprops^^facets(Tfacets), Tfacets^^whiteSpace(value(Tws),fixed(_),annotation(_)), ws_normalize(Tws,PreLF,LF),
Tprops^^primitive_type_definition(Prim), atom_chars(LF,Lc), ( call(Prim,ParsedNode,Lc,[]) -> LParseErrors = [] ; ( xsd_errorcode(cvc-simple-type,LF,Prim,Desc-st), xsd_errorcode(cvc-datatype-valid.1,LF,Prim,Desc-lf), LParseErrors = [error(cvc-simple-type,Desc-st), error(cvc-datatype-valid.1,Desc-lf)] ) ),
match_patterns(Tid,LF,Tfacets,LPatternErrors),
/* match_patterns(Tid,LF,Tfacets,LPatternErrors): true iff matching lexical form LF against all the pattern facets in the list Tfacets yields LPatternErrors as the resulting error list. */ /* If there are no facets, there are no errors. */ match_patterns(Tid,LF,[],[]). /* If the next facet is not a pattern, skip it and recur. */ match_patterns(Tid,LF,[F|Lfacets],Lerr) :- not(F = pattern(_Value,_Annotation,_DCTG)), match_patterns(Tid,LF,Lfacets,Lerr). /* If the next facet is a pattern, test it and recur. */ match_patterns(Tid,LF, [pattern(value(PVal),annotation(PAnn),dctg_rule(PRule))|Lfacets], Lerr) :- atom_chars(LF,Lc), ( call(PRule,_ParsedNode,Lc,[]) -> Lerr = Lerr2 ; ( atom_codes(PreLF,LF), xsd_errorcode(cvc-datatype-valid.1,PreLF,Tid,Desc-dv), xsd_errorcode(cvc-pattern-valid.1,PreLF,Tid,PVal,Desc-pv), Lerr = [error(cvc-datatype-valid.1,Desc-dv), error(cvc-pattern-valid.1,Desc-pv), | Lerr2] ) ), match_patterns(Tid,LF,Lfacets,Lerr2).
xsd_errorcode(cvc-pattern-valid.1,S,T,P,Desc) :- concat_atom(['The lexical form "',S, '" is not datatype-valid w.r.t. the given simple type ', T,': it does not match the required pattern "', P, '".'], Desc).
check_facets(Tid,LF,Tfacets,LFacetErrors).
/* check_facets(Tid,LF,Tfacets,Lerr): true iff checking the value associated with lexical form LF against all the non-pattern facets in the list Tfacets yields Lerr as the resulting error list. */ /* If there are no facets, there are no errors. */ check_facets(Tid,LF,[],[]). /* If the next facet is a pattern or whitespace facet, then skip it and recur. */ check_facets(Tid,LF,[pattern(_,_,_)|Lfacets],Lerr) :- check_facets(Tid,LF,Lfacets,Lerr). check_facets(Tid,LF,[whiteSpace(_,_,_)|Lfacets],Lerr) :- check_facets(Tid,LF,Lfacets,Lerr).Continued in <Checking length facet 133>, <Checking min and max length facets 138>, <Checking enumeraton facets 140>, <Checking minima and maxima 144>, <Checking total- and fractionDigits facets 145>
/* Check lengths */ check_facets(Tid,LF, [length(value(Val),fixed(_Fixed),annotation(_Ann)) | Lfacets], Lerr) :- type_val_length(Tid,LF,Length), ( Length is Val -> Lerr = Lerr2 ; ( xsd_errorcode(cvc-datatype-valid.1,LF,Tid,Desc-dv), xsd_errorcode(cvc-length-valid,LF,Tid,Val,Length,EC,Desc-lv), Lerr = [error(cvc-datatype-valid.1,Desc-dv), error(EC,Desc-lv) | Lerr2] ) ) check_facets(Tid,LF,Lfacets,Lerr2).
type_val_length(Tid,LF,Length) :- simpletype(Tid,_Tscd,_Tname,_Ttargetns,_Tglobal,Tprops), Tprops ^^ variety(atomic), Tprops ^^ primitive_type_definition(PTid), prim_val_length(PTid,LF,Length). type_val_length(Tid,LF,Length) :- simpletype(Tid,_Tscd,_Tname,_Ttargetns,_Tglobal,Tprops), Tprops ^^ variety(list), tokens_count(L2,Length). prim_val_length(t_string,LF,Length) :- atom_chars(LF,Lc), length(Lc,Length). prim_val_length(t_anyURI,LF,Length) :- atom_chars(LF,Lc), length(Lc,Length). prim_val_length(t_hexBinary,LF,Length) :- atom_chars(LF,Lc), ws_delete(Lc,Lc2), length(Lc2,LenLc2), Length is LenLc2 / 2. prim_val_length(t_base64Binary,LF,Length) :- atom_codes(LF,Lc), wscodes_delete(Lc,Lc2), length(Lc2,LenLc2), LenCeil is ((LenLc2 / 4) * 3), ( append(_L,[61,61],Lc2) /* LF ends with == */ -> Length is LenCeil - 2 ; (append(_L,[61],Lc2) /* LF ends with = */ -> Length is LenCeil - 1 ; Length is LenCeil)). prim_val_length(t_QName,LF,Length). prim_val_length(t_NOTATION,LF,Length).
/* wscodes_delete(L1,L2): true iff L2 = L1, with all whitespace codes (numeric codes!) deleted. */ wscodes_delete([],[]). wscodes_delete([32|Lin],Lout) :- wscodes_delete(Lin,Lout). wscodes_delete([09|Lin],Lout) :- wscodes_delete(Lin,Lout). wscodes_delete([10|Lin],Lout) :- wscodes_delete(Lin,Lout). wscodes_delete([13|Lin],Lout) :- wscodes_delete(Lin,Lout). wscodes_delete([C|Lin],Lout) :- not(member(C,[9,10,13,32])), wscodes_delete([C|Lin],Lout).
tokens_count(LF,N) :- ws_normalize(collapse,LF,L2), atom_codes(L2,Lc), count_codes(Lc,32,Blanks), N is Blanks + 1. count_codes(L,C,N) :- count_codes(L,C,0,N). count_codes([],_C,N,N). count_codes([C|L],C,Acc,Total) :- N is Acc + 1, count_codes(L,C,N,Total). count_codes([X|L],C,Acc,Total) :- not(X = C), count_codes(L,C,Acc,Total).
xsd_errorcode(cvc-length-valid,S,T,Lf,La,EC,Desc) :- concat_atom(['The lexical form "',S, '" is not datatype-valid w.r.t. the given simple type ', T,': its length is ',La,' instead of the required ', Lf, '.'], Desc), simpletype(T,_Tscd,_Tname,_Ttargetns,_Tglobal,Tprops), Tprops ^^ variety(V), Tprops ^^ primitive_type_definition(P), ( V = list -> EC = cvc-length-valid.2 ; member(P,[t_string,t_anyURI]) -> EC = cvc-length-valid.1.1 ; member(P,[t_hex_binary,t_base64Binary]) -> EC = cvc-length-valid.1.2 ; member(P,[t_QName,t_NOTATION]) -> EC = 'cvc-length-valid.1.3 (wow! this should not happen)' ; EC = 'cvc-length-valid (this cannot happen)' )
check_facets(Tid,LF, [minLength(value(Val),fixed(_Fixed),annotation(_Ann)) | Lfacets], Lerr) :- type_val_length(Tid,LF,Length), ( Length >= Val -> Lerr = Lerr2 ; ( xsd_errorcode(cvc-datatype-valid.1,LF,Tid,Desc-dv), xsd_errorcode(cvc-minLength-valid,LF,Tid,Val,Length,EC,Desc-lv), Lerr = [error(cvc-datatype-valid.1,Desc-dv), error(EC,Desc-lv) | Lerr2] ) ) check_facets(Tid,LF,Lfacets,Lerr2). check_facets(Tid,LF, [maxLength(value(Val),fixed(_Fixed),annotation(_Ann)) | Lfacets], Lerr) :- type_val_length(Tid,LF,Length), ( Length => Val -> Lerr = Lerr2 ; ( xsd_errorcode(cvc-datatype-valid.1,LF,Tid,Desc-dv), xsd_errorcode(cvc-maxLength-valid,LF,Tid,Val,Length,EC,Desc-lv), Lerr = [error(cvc-datatype-valid.1,Desc-dv), error(EC,Desc-lv) | Lerr2] ) ) check_facets(Tid,LF,Lfacets,Lerr2).
xsd_errorcode(cvc-minLength-valid,S,T,Lf,La,EC,Desc) :- concat_atom(['The lexical form "',S, '" is not datatype-valid w.r.t. the given simple type ', T,': its length is ',La,' instead of being at least ', Lf, '.'], Desc), simpletype(T,_Tscd,_Tname,_Ttargetns,_Tglobal,Tprops), Tprops ^^ variety(V), Tprops ^^ primitive_type_definition(P), ( V = list -> EC = cvc-minLength-valid.2 ; member(P,[t_string,t_anyURI]) -> EC = cvc-minLength-valid.1.1 ; member(P,[t_hex_binary,t_base64Binary]) -> EC = cvc-minLength-valid.1.2 ; member(P,[t_QName,t_NOTATION]) -> EC = 'cvc-minLength-valid.1.3 (wow! this should not happen)' ; EC = 'cvc-minLength-valid (this cannot happen)' ) xsd_errorcode(cvc-maxLength-valid,S,T,Lf,La,EC,Desc) :- concat_atom(['The lexical form "',S, '" is not datatype-valid w.r.t. the given simple type ', T,': its length is ',La,' instead of being at most ', Lf, '.'], Desc), simpletype(T,_Tscd,_Tname,_Ttargetns,_Tglobal,Tprops), Tprops ^^ variety(V), Tprops ^^ primitive_type_definition(P), ( V = list -> EC = cvc-maxLength-valid.2 ; member(P,[t_string,t_anyURI]) -> EC = cvc-maxLength-valid.1.1 ; member(P,[t_hex_binary,t_base64Binary]) -> EC = cvc-maxLength-valid.1.2 ; member(P,[t_QName,t_NOTATION]) -> EC = 'cvc-maxLength-valid.1.3 (wow! this should not happen)' ; EC = 'cvc-maxLength-valid (this cannot happen)' )
/* Check enumerations */ check_facets(Tid, LF, [enumeration(value([Vs]),annotation(Ann)) | Lfacets], Lerr) :- lf_st_canonicalform(LF,Tid,CF), ( member(CF,Vs) -> Lerr = Lerr2 ; ( xsd_errorcode(cvc-datatype-valid.1,LF,Tid,Desc-dv), xsd_errorcode(cvc-enumeration-valid,LF,Tid,Desc-ev), Lerr = [error(cvc-datatype-valid.1,Desc-dv), error(EC,Desc-ev) | Lerr2] ) ) check_facets(Tid,LF,Lfacets,Lerr2).
xsd_errorcode(cvc-enumeration-valid,S,T,Vs,Desc) :- concat_atom(Vs, '", "', Va), concat_atom(['The lexical form "',S, '" is not datatype-valid w.r.t. the given simple type ', T,': it does not match any of the enumerated values ("', Va, '").'], Desc).
/* Calculate canonical form. lf_st_canonicalform(LF,Tid,CF): true iff lexical form LF of simple type Tid maps to canonical form CF. */ lf_st_canonicalform(LF,Tid,LF) :- simpletype(T,_Tscd,_Tname,_Ttargetns,_Tglobal,Tprops), Tprops ^^ primitive_type_definition(P), member(P,[t_string,t_anyURI,t_gMonthDay,t_gDay,t_gMonth, keyword(absent)]). /* if primitive type is 'absent', then it's the simple urtype, and there is nothing to be done */Continued in <Canonical forms 143>
lf_st_canonicalform(LF,Tid,CF) :- simpletype(T,_Tscd,_Tname,_Ttargetns,_Tglobal,Tprops), Tprops ^^ primitive_type_definition(t_integer), atom_chars(LF,Lc), lf_integer_cf(Lc,Cc), atom_chars(CF,Cc). /* We assume the lexical form is legal, and we don't * need to check for signs in the wrong place, etc. */ /* Retain leading minus sign */ lf_integer_cf(['-'|Lexcodes],['-'|Cancodes]) :- lf_integer_cf(Lexcodes,Cancodes). /* Strip leading + or blank */ lf_integer_cf(['+'|Lexcodes],[Cancodes]) :- lf_integer_cf(Lexcodes,Cancodes). lf_integer_cf(['0'|Lexcodes],[Cancodes]) :- lf_integer_cf(Lexcodes,Cancodes). /* base cases: if you are down to [], you've stripped off all the zeroes. If you find a non-zero, you are done. */ lf_integer_cf([D|Lexcodes],[D|Lexcodes]) :- char_type(D,digit), not(D = '0'). lf_integer_cf([],['0']).
/* Check maxima and minima */ check_facets(Tid,LF, [maxInclusive(value(Val),fixed(Fixed),annotation(Ann)) | Lfacets], Lerr) :- check_facets(Tid,LF, [maxExclusive(value(Val),fixed(Fixed),annotation(Ann)) | Lfacets], Lerr) :- check_facets(Tid,LF, [minInclusive(value(Val),fixed(Fixed),annotation(Ann)) | Lfacets], Lerr) :- check_facets(Tid,LF, [minExclusive(value(Val),fixed(Fixed),annotation(Ann)) | Lfacets], Lerr) :-
/* Check totalDigits and fractionDigits */ check_facets(Tid,LF, [pattern(value(PVal),annotation(PAnn),dctg_rule(PRule))|Lfacets], Lerr) :- ( call(PRule,ParsedNode,LF,[]) -> Lerr = Lerr2 ; ( atom_codes(PreLF,LF), xsd_errorcode(cvc-datatype-valid.1,PreLF,Tid,Desc-dv), xsd_errorcode(cvc-pattern-valid.1,PreLF,Tid,PVal,Desc-pv), Lerr = [error(cvc-datatype-valid.1,Desc-dv), error(cvc-pattern-valid.1,Desc-pv), | Lerr2] ) ), check_facets(Tid,LF,Lfacets,Lerr2).
/* xsd_string_value(+TN,+LF,-Errors): Validating the lexical form LF against the simple type xs:string (with type name TN) results in the errors listed in Errors. (Each error is a structure with functor 'error' and two arguments: an error code and a description. Each argument is an atom.) If Errors is the empty list, then the lexical form is a legal string. */ xsd_string_value('xsd:string',LF,[]) :- atom(LF). xsd_string_value('xsd:string',LF,[Err]) :- not(atom(LF)), xsd_errorcode(cvc-simple-type,LF,'xsd:string',DescTemp), concat_atom( [DescTemp,' N.B. This error was thought to be impossible.'], Desc), Err = error(cvc-simple-type,Desc).
/* xsd_string_cont(+Gi,+LIn,-LPn,-LErr): Validating an element named Gi, with children LIn, against the simple type xs:string, results in the errors listed in LErr. If Errors is empty, the element is a legal instance of xs:string. If the list of input children LIn contains elements, the result of validating them in lax mode is LPn. */ xsd_string_cont(Gi,LIn,LPn,LErr) :- memberchk(element(GiChild,_Atts,_Content),LIn), xsd_errorcode(cvc-type.3.1.2,Gi,'xsd:string',GiChild,Desc), LErr = [error(cvc-type.3.1.2,Desc)], sva_lax_seq(LIn,LPn). /* This assumes that even though having any element children * makes the element we are checking illegal, we should strictly * speaking validate all of the element children in lax mode * anyway (cvc-assess-elt clause 2). */ xsd_string_cont(_Gi,LIn,LPn,LErr) :- not(memberchk(element(_GiChild,_Atts,_Content),LIn)), gr_xsd_string(LErr,Pn,LIn,[]), Pn^^children(LPn). gr_xsd_string(LErr) ::= [Atom], { xsd_string_value('xsd:string',Atom,LErr) } <:> children([Atom]).
xsd_integer_value('xsd:integer',LF,[]) :- atom(LF), atom_chars(LF,L), gr_xsd_integer(LErr) ... xsd_integer_value('xsd:integer',LF,[]) :- ...
sva_lax_seq(LIn,LPn) :- gr_lax_sequence(Node,LIn,[]), Node^^children(LPn). gr_lax_sequence ::= [] <:> children([]). gr_lax_sequence ::= gr_lax_item^^Item, gr_lax_sequence^^Seq <:> children([CI|CS]) ::- Item^^child(CI), Seq^^children(CS). gr_lax_item ::= [PCDATA], { atom(PCDATA) }, <:> child([PCDATA]). gr_lax_item ::= [element(Gi,Atts,Cont)], { schema_lookup(element,Gi,Rule), call(Rule(Node,[element(Gi,Atts,Cont)],[])) } <:> child(Node).
/* Define the mapping from generic identifiers to grammar rules. */ schema_lookup(element,'...':purchaseOrder,e_purchaseOrder). schema_lookup(element, 'http://www.example.com/PO1':purchaseOrder, e_purchaseOrder). schema_lookup(element,shipTo,e_shipTo). schema_lookup(element,billTo,e_billTo). schema_lookup(element,items,e_items). schema_lookup(element,item,e_item). schema_lookup(element,'http://www.example.com/PO1':comment,e_comment). schema_lookup(element,name,e_name). schema_lookup(element,street,e_street). schema_lookup(element,city,e_city). schema_lookup(element,state,e_state). schema_lookup(element,zip,e_zip). schema_lookup(element,productName,e_productName). schema_lookup(element,quantity,e_quantity). schema_lookup(element,'USPrice',e_USPrice). schema_lookup(element,shipDate,e_shipDate).
gr_lax_item ::= e_purchaseOrder^^E <:> child(E). gr_lax_item ::= e_shipTo^^E <:> child(E). /* ... */ gr_lax_item ::= e_shipDate^^E <:> child(E). gr_lax_item ::= unknown_element^^E <:> child(E). unknown_element ::= [element(Ns:Ln,Attributes,Content)], { check_unknown_atts(A,NA,Attributes), sva_lax_seq(Content,LPn) } <:> localname(Ln) && namespacename(Ns) && attributes(A) && namespaceattributes(NA) && children(LPn) && schemaerrorcode(error(cvc-assess-elt.1.1.1,Desc)) ::- xsd_errorcode(cvc-assess-elt.1.1.1,Desc) && validationattempted(ValidationCode) ::- find_validationcode(lax,LPn) /* ... */ . unknown_element ::= [Gi,Attributes,Content)], { check_unknown_atts(A,NA,Attributes), sva_lax_seq(Content,LPn) } <:> localname(Gi) && namespacename(Ns) && attributes(A) && namespaceattributes(NA) && children(LPn) && schemaerrorcode(error(cvc-assess-elt.1.1.1,Desc)) ::- xsd_errorcode(cvc-assess-elt.1.1.1,Desc) && validationattempted(ValidationCode) ::- find_validationcode(lax,LPn) /* ... */ .
rule(Arg,Arg2,Errors) :- check_constraint_1(Arg,Arg2,E1), check_constraint_2(Arg,Arg2,E2), check_constraint_3(Arg,Arg2,E3), ... check_constraint_n(Arg,Arg2,En), flatten([E1,E2,E3, ..., En],Errors). check_constraint_1(Arg,Arg2,[]) :- constraint_1(Arg,Arg2). check_constraint_1(Arg,Arg2,[error(err-c1,desc)]) :- not(constraint_1(Arg,Arg2)).
/* xsd_errorcode(+Sym,+Gi,+Typename,+Attname,-Desc): Desc is the string describing the error whose error code is Sym, when it occurs with respect to an element with name Gi, being validated against type Typename, on account of a bad attribute named Attname. */ xsd_errorcode(cvc-type.3.1.1,Gi,Tn,Anbad,Desc) :- concat_atom(['The ',Gi,' element is not locally valid: ', 'its type definition (', Tn, ') is simple, but it has attributes other than ', 'xsi:type, xsi:nil, xsi:schemaLocation, and ' 'xsi:noNamespaceSchemaLocation (specifically ' Anbad, ').'], Desc). /* xsd_errorcode(+Sym,+Gip,+Typename,+Gic,-Desc): Desc is the string describing the error whose error code is Sym, when it occurs with respect to an element with name Gip, being validated against type Typename, on account of a bad child element named Attname. */ xsd_errorcode(cvc-type.3.1.2,Gi,Tn,GiChild,Desc) :- concat_atom(['The ',Gi,' element is not locally valid: ', 'its type definition (',Tn,') is simple, but it has ' 'element children (',GiChild,').'], Desc). /* xsd_errorcode(+Sym,+Gi,+Typename,-Desc): Desc is the string describing the error whose error code is Sym, when it occurs with respect to an element with name Gi, being validated against type Typename. */ xsd_errorcode(cvc-type.3.1.3,Gi,Tn,Desc) :- concat_atom(['The ',Gi,' element is not locally valid: ', 'its content is not a legal lexical form for its ' 'simple type ',Tn,'.'], Desc).
/* po4.pl: a definite-clause translation grammar representation * of the sample purchase-order schema from the XML Schema tutorial. * * This DCTG was generated by a literate programming system; if * maintenance is necessary, make changes to the source (dctgnotes.xml), * not to this output file. */ {Predicates for purchase-order material 84} {Generic utilities for DCTG-encoded schemas 85}
{Rules for elements with complex types 31} {Rules for elements with simple types 33} {Attribute handling for purchaseOrderType 42} {Attribute handling for USAddress 51} {Attribute handling for Items type 53} {Attribute handling for t_item 54} {Attribute handling for simple types 56} {Rules for purchase-order content models 58} {Simple-type content rules for purchase-order types 80} {Value-checking rules for SKU 81} {Element declarations 155} {Layer 4 attribute declarations 157} {Layer 4 type definitions 156}
{Element declaration: purchaseOrder 86} {Element declaration: comment 88} {Element declaration: shipTo 89} {Element declaration: billTo 90} {Element declaration: items 91} {Element declaration: name 92} {Element declaration: street 93} {Element declaration: city 94} {Element declaration: state 95} {Element declaration: zip 96} {Element declaration: item 97} {Element declaration: productName 98} {Element declaration: quantity 99} {Element declaration: USPrice 100} {Element declaration: shipDate 101}
{Complex type: t_PurchaseOrderType 102} {Complex type: t_USAddress 104} {Complex type: t_Items 106} {Complex type: t_item 107} {The urtype 110} {Simple type: simple urtype 109} {Simple type: string 112} {Simple type: normalizedString 113} {Simple type: token 114} {Simple type: NMTOKEN 115} {Simple type: decimal 117} {Simple type: integer 118} {Simple type: non-negative integer 119} {Simple type: positive integer 120} { !! BAD REFERENCE! No scrap called L4_st_quanityType!} {Simple type: date 122} {Simple type: SKU 116}
{Grammar rules for namespace and XSI attributes 37} {Utilities for checking attribute occurrences 38} {Utility for checking absent attributes 39} {Utility for providing defaulted attributes 40} {Utility for whitespace normalization 43} {partition predicate 57} {Content-checking rules for simple types 147} {Value checking rules for simple types 146} {Error codes for simple types 123}
t_PurchaseOrderType_cont ::= e_shipTo, e_billTo, opt_e_comment, e_items. opt_e_comment ::= []. opt_e_comment ::= e_comment.to
t_PurchaseOrderType_cont ::= opt_ws, t_PurchaseOrderType_cont2. t_PurchaseOrderType_cont2 ::= e_shipTo, opt_ws, e_billTo, opt_ws, opt_e_comment, e_items, opt_ws. opt_e_comment ::= []. opt_e_comment ::= e_comment, opt_ws.
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, Matthew Fuchs, Jonathan Robie, and Philip Wadler. 1991. “XML Schema: Formal Description”. W3C Working Draft, 25 September 2001. [Cambridge, Sophia-Antipolis, and Tokyo]: World Wide Web Consortium. http://www.w3.org/TR/xmlschema-formal/
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
Holstege, Mary, and Asir S. Vedamuthu, ed. 2003. XML Schema: Component Designators. W3C Working Draft 09 January 2003. [Cambridge, Sophia-Antipolis, and Tokyo]: World Wide Web Consortium. http://www.w3.org/TR/xmlschema-ref/
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]
Pereira, Fernando C. N., and Stuart M. Shieber, Prolog and natural-language analysis. CSLI lecture notes 10. Stanford: Center for the study of language and information, 1987.
Sperberg-McQueen, C. M. 2003a. “A logic grammar representation for XML Schema”. Working paper prepared for the W3C XML Schema Working Group. [Incomplete; incomplete outline is at lgrxs.html. Attempt at a systematic demonstration that DCTGs (can be made to) correctly implement the validation rules, provide the schema-infoset contributions, and obey the constraints on schemas defined in the specification.]
Sperberg-McQueen, C. M. 2003b. “An XML Schema validator in logic-grammar form”. Working paper prepared for the W3C XML Schema Working Group. [Incomplete; incomplete outline is at xsvlgf.html. Will provide a DCTG representation of the schema for schemas, with actions to perform the XML-to-component transformation and code to check the constraints on schemas.]
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.
Sterling, Leon, and Ehud Shapiro. 1994. The Art of Prolog: Advanced Programming Techniques. Cambridge, Mass.: MIT Press.
W3C (World Wide Web Consortium). 2001a. “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 (World Wide Web Consortium). 2001b. 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 (World Wide Web Consortium). 2001c. 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/
Wadler, Philip. “A formal semantics of patterns in XSLT and XPath.” Markup Languages: Theory & Practice 2.2 (2000): 183-202.
Wielemaker, Jan. “SWI-Prolog SGML/XML parser: Version 1.0.14, March 2001”. http://www.swi-prolog.org/packages/sgml2pl.html
/* potest: simple one-item test routine for SWI Prolog * * This DCG was generated by a literate programming system; if * maintenance is necessary, make changes to the source (dctgnotes.xml), * not to this output file. */ grammar_version(current,dctg,'d:/home/cmsmcq/2003/schema/dctg/po4.pl'). grammar_version(old,dctg,'d:/home/cmsmcq/2003/schema/dctg/podctg.pl'). grammar_version(dcg,dcg,'d:/home/cmsmcq/2003/schema/dctg/podcg3.pl'). potest(Grammar,dcg,XMLDocument) :- write('Loading grammar '), write(Grammar), write('...'), nl, consult(Grammar), write('Loading document '), write(XMLDocument), write('...'), nl, load_structure(XMLDocument,Infoset,[dialect(xmlns),space(remove)]), (purchaseOrder(Infoset,[]) -> writeq('yes') ; writeq('no')), nl. potest(Grammar,dctg,XMLDocument) :- write('Loading grammar '), write(Grammar), write('...'), nl, consult('d:/usr/lib/prolog/msmdctg.pl'), dctg_reconsult(Grammar), write('Loading document '), write(XMLDocument), write('...'), nl, load_structure(XMLDocument,Infoset,[dialect(xmlns),space(remove)]), (e_purchaseOrder(_Structure,Infoset,[]) -> writeq('yes') ; writeq('no')), nl. potest2(XMLDocument,dcg) :- write('Loading document '), write(XMLDocument), write('...'), nl, load_structure(XMLDocument,Infoset,[dialect(xmlns),space(remove)]), (purchaseOrder(Infoset,[]) -> writeq('yes') ; writeq('no')), nl. potest2(XMLDocument,dctg) :- write('Loading document '), write(XMLDocument), write('...'), nl, load_structure(XMLDocument,Infoset,[dialect(xmlns),space(remove)]), (e_purchaseOrder(_Structure,Infoset,[]) -> writeq('yes') ; writeq('no')), nl. one(V) :- grammar_version(V,Syn,File), potest(File,Syn,'d:/usr/lib/xmlschema/po/tests/po1.xml'). two(V) :- grammar_version(V,Syn,File), potest(File,Syn,'d:/usr/lib/xmlschema/po/tests/po1.xml'), potest2('d:/usr/lib/xmlschema/po/tests/po1v10a.xml',Syn). /* Each of the following should be valid */ good(V) :- grammar_version(V,Syn,File), potest(File,Syn,'d:/usr/lib/xmlschema/po/tests/po1.xml'), potest2('d:/usr/lib/xmlschema/po/tests/po1v10a.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v25.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v33.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v38.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v62d.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v65.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v79.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v80.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v100a.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v100b.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1v121.xml',Syn). /* Each of the following should raise an error */ bad(V) :- grammar_version(V,Syn,File), potest(File,Syn,'d:/usr/lib/xmlschema/po/tests/po1.xml'), potest2('d:/usr/lib/xmlschema/po/tests/po1e04.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e13.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e14.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e15.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e15a.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e15b.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e15c.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e16.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e16b.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e18.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e19.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e20.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e27.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e28.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e28b.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e30.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e31.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e32.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e35.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e36.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e41.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e42.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e43.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e44.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e46.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e47.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e48.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e50.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e51.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e52.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e55.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e56.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e62.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e62b.xml',Syn), /* potest2('d:/usr/lib/xmlschema/po/tests/po1e62c.xml',Syn), */ potest2('d:/usr/lib/xmlschema/po/tests/po1e63.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e64.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e68.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e70.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e70b.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e78.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e81.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e86.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e87.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e88.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e89.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e91.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e92.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e101a.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e101b.xml',Syn), /* potest2('d:/usr/lib/xmlschema/po/tests/po1e101c.xml',Syn), */ potest2('d:/usr/lib/xmlschema/po/tests/po1e101d.xml',Syn), /* potest2('d:/usr/lib/xmlschema/po/tests/po1e105bisa.xml',Syn), */ potest2('d:/usr/lib/xmlschema/po/tests/po1e105bisb.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e106.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e109.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e113.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e114.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e116.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e122a.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e122b.xml',Syn), potest2('d:/usr/lib/xmlschema/po/tests/po1e122c.xml',Syn). /* 62c, 101c, 105bisa are commented out because they blow up * number_chars/2. Need a more robust approach to checking * numbers, apparently. */ ugly(V) :- good(V), bad(V).
cd ~/2003/schema/dctg $ /cygdrive/d/usr/src/pl/bin/plcon.exe -f potests.pl -g 'one(current)' -t haltor
$ /cygdrive/d/usr/src/pl/bin/plcon.exe \ > -f d:/home/cmsmcq/2002/Prolog/potest.pl \ > -g 'good(current)' -t haltThe command line might be simpler if Prolog has a good search path, but I haven't gotten around to that yet.
['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).
attdecl(a_orderDate, '/complexType(po:PurchaseOrderType)/attribute(orderDate)', orderDate,keyword(absent), local, [ (id(a_orderDate)), (scd()), (name(orderDate)), (target_namespace('http://www.example.com/PO1')), (type_definition(t_date)), (scope(t_PurchaseOrderType)), (value_constraint(keyword(absent))), (annotation(keyword(absent))) ]).in which case the {attribute uses} property might read
(attribute_uses([ au(required(false), attdecl(a_orderDate), value_constraint(keyword(absent))) ])),or (if we want to ensure that we can use the ^^ operator with attribute uses):
(attribute_uses([ au([(required(false)), (attdecl(a_orderDate)), (value_constraint(keyword(absent)))]) ])),
att_merge([],Padft,[Padft]). att_merge([Pa|Lpa],Padft,[Pa|Lpa]) :- Pa^^namespacename(NS), Padft^^namespacename(NS), Pa^^localname(Lnm), Padft^^localname(Lnm), !. att_merge([Pa|Lpa],Padft,Lpa2) :- att_merge(Lpa,Padft,Lpa2).The if-then-else construct may also be used with the same effect:
att_merge([],Padft,[Padft]). att_merge([Pa|Lpa],Padft,Lpa2) :- ( { Pa^^namespacename(NS), Padft^^namespacename(NS), Pa^^localname(Lnm), Padft^^localname(Lnm) } -> Lpa2 = [Pa|Lpa] ; att_merge(Lpa,Padft,Lpa2) ).