Module: @QName: MDOM|XMLParser @Namespace: http://suika.fam.cx/~wakaba/archive/2004/dom/xml-parser# @FullName: @@lang:en @@@: XML Parser @DISCore:author: DISCore|Wakaba @License: license|Perl+MPL @Date: $Date: 2006/02/08 08:18:29 $ @DefaultFor: ManakaiDOM|ManakaiDOMLatest @Require: @@Module: @@@QName: MDOM|DOMLS @@@WithFor: ManakaiDOM|ManakaiDOMLatest @@Module: @@@QName: MDOM|XDoctype @@@WithFor: ManakaiDOM|ManakaiDOMLatest Namespace: @c: http://suika.fam.cx/~wakaba/archive/2004/8/18/dom-core# @cfg: http://suika.fam.cx/www/2006/dom-config/ @d: http://suika.fam.cx/~wakaba/archive/2004/dom/xdt# @dis: http://suika.fam.cx/~wakaba/archive/2004/8/18/lang#dis-- @dtest: http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/DIS#Test/ @dx: http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/Error/DOMException# @ecore: http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/Error/Core/ @f: http://suika.fam.cx/~wakaba/archive/2004/dom/feature# @fe: http://suika.fam.cx/www/2006/feature/ @gls: http://suika.fam.cx/~wakaba/archive/2004/dom/gls# @idl: http://suika.fam.cx/~wakaba/archive/2004/dis/IDL# @infoset: http://www.w3.org/2001/04/infoset# @lang: http://suika.fam.cx/~wakaba/archive/2004/8/18/lang# @license: http://suika.fam.cx/~wakaba/archive/2004/8/18/license# @LSEV: http://www.w3.org/2002/DOMLS @ManakaiDOM: http://suika.fam.cx/~wakaba/archive/2004/8/18/manakai-dom# @ManakaiDOMLS: http://suika.fam.cx/~wakaba/archive/2004/mdom-ls# @MDOM: http://suika.fam.cx/~wakaba/archive/2004/8/18/manakai-dom#ManakaiDOM. @MDOMX: http://suika.fam.cx/~wakaba/archive/2004/8/4/manakai-dom-exception# @mn: http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/ManakaiNode# @rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# @rdfs: http://www.w3.org/2000/01/rdf-schema# @t: http://suika.fam.cx/~wakaba/archive/2004/dom/tree# @test: http://suika.fam.cx/~wakaba/archive/2004/dis/Test# @x: http://suika.fam.cx/~wakaba/archive/2004/dom/xml# @xml: http://www.w3.org/XML/1998/namespace @xml-dtd: http://www.w3.org/TR/REC-xml @xmlns: http://www.w3.org/2000/xmlns/ @xp: http://suika.fam.cx/~wakaba/archive/2004/dom/xml-parser# ## -- Features ElementTypeBinding: @Name: FeatureDef @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: f|Feature @@For: =ManakaiDOM|all ElementTypeBinding: @Name: FeatureVerDef @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: f|Feature ElementTypeBinding: @Name: featureQName @ElementType: f:name @ShadowContent: @@ContentType: DISCore|QName ResourceDef: @QName: DOMString @AliasFor: DOMMain|DOMString @For: ManakaiDOM|DOM ResourceDef: @QName: Node @AliasFor: t|Node @For: ManakaiDOM|DOM ResourceDef: @QName: Element @AliasFor: t|Element @For: ManakaiDOM|DOM ResourceDef: @QName: Document @AliasFor: t|Document @For: ManakaiDOM|DOM ResourceDef: @QName: DocumentXDoctype @AliasFor: d|DocumentXDoctype @For: ManakaiDOM|DOM ResourceDef: @QName: DTDef @AliasFor: d|DocumentTypeDefinition @For: ManakaiDOM|DOM ResourceDef: @QName: ETDef @AliasFor: d|ElementTypeDefinition @For: ManakaiDOM|DOM ResourceDef: @QName: ATDef @AliasFor: d|AttributeDefinition @For: ManakaiDOM|DOM ElementTypeBinding: @Name: ClsDef @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: @@@@: dis|MultipleResource @@@ForCheck: !ManakaiDOM|ForIF !ManakaiDOM|ForClass @@resourceFor: @@@@: ManakaiDOM|ForClass @@@ForCheck: ManakaiDOM|ManakaiDOM !=ManakaiDOM|ManakaiDOM @@For: ManakaiDOM|DOM3 @@For: =ManakaiDOM|ManakaiDOM @@rdf:type: @@@@: DISLang|Class @@@ForCheck: ManakaiDOM|ForClass ElementTypeBinding: @Name: ClsQName @ElementType: dis:QName @ShadowContent: @@ForCheck: ManakaiDOM|ForClass ElementTypeBinding: @Name: ClsISA @ElementType: dis:ISA @ShadowContent: @@ForCheck: ManakaiDOM|ForClass ElementTypeBinding: @Name: nullCase @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: ManakaiDOM|InCase @@Value: @@@is-null:1 ResourceDef: @QName: LSParser @AliasFor: DOMLS|LSParser @For: ManakaiDOM|DOM3 ClsDef: @ClsQName: ManakaiXMLParser @Implement: DOMLS|LSParser @f:implements: @@@: DOMLS|LSFeature30 @@For: ManakaiDOM|DOM3 @DISLang:role: gls|ParserRole @enDesc: Note that the reports any XML errors (syntax errors and / or well-formedness constraint errors) via the registered to the object. Each error has its , either or . However, their semantics are slight different from the ones of and in XML; in this implemenetation, implies that the parsing process can effectively be continued to detect more errors while implies that the error is serious so that the result document tree and any errors might be far from the ones obtained when the error would not be found. @Attr: @@Name: domConfig @@enDesc: The configuration of the parser. @@Get: @@@Type: DOMCore|DOMConfiguration @@@enDesc: The DOM configuration object. @@@PerlDef: __CODE{DOMCore|getConfigObject:: $target => $self, $targetHash => $self, $targetType => {}, $result => $r, }__; @Method: @@ManakaiDOM:isForInternal:1 @@ForCheck: ManakaiDOM|ForClass @@Operator: DISPerl|NewMethod @@enDesc: Creates a new instance of the object. @@Param: @@@Name: impl @@@Type: gls|GLSImplementation @@@enDesc: The implementation from which the parser is created. @@Param: @@@Name: features @@@Type: DOMString @@@dis:actualType: f|FeaturesString @@@enDesc: The set of features requested for the parser. @@Return: @@@Type: DOMMain|DOMObject @@@dis:actualType: LSParser @@@enDesc: The newly created parser. @@@PerlDef: $r = bless { => $impl, }, $self; @Method: @@Name: parseString @@enImplNote: Non-standard - to be removed @@Param: @@@Name: sourceText @@@Type: DOMString @@Return: @@@Type: Document @@@PerlDef: $self->{char} = []; $self->{token} = []; $self->{entity} = [{ reptxt => \$sourceText, line => 1, column => 1, pos => 0, }]; $self->{entity_char} = []; $self->{entity_token} = []; $self->{xml_version} = '1.0'; $self->{standalone} = false; $self->{general_entity} = { lt => {is_predefined => true}, gt => {is_predefined => true}, amp => {is_predefined => true}, quot => {is_predefined => true}, apos => {is_predefined => true}, }; $self->{param_entity} = {}; $self->{attr} = {}; # $self->{attr}->{$element_type_name}->{$attr_name} = $attr_def $self->{has_error} = false; ## Well-formedness constraint Entity Declared takes effect? __DEEP{ $r = $self->{}->; $r-> (false); $self->{doc} = $r; CORE::delete $self->{docx}; CORE::delete $self->{dtdef}; $self->{cfg} = $r->; local $r->{} ->{} = false; ## Document entity -> |Document| node $self->_parse_DocumentEntity; ## Replacement tree for general |Entity| nodes my @ent = values %{$self->{general_entities}}; if (@ent) { for my $ent (@ent) { if (exists $ent->{reptxt}) { my $ent_name = $ent->{name}; $self->{entity} = []; $self->{token} = []; $self->{char} = []; ## TODO: External entity support $self->_parse_InternalGeneralParsedEntity ($ent->{node}); $ent->{node}-> (true); } ## TODO: Read-only if configuration (for all entities) } } $r-> (true); }__; @Method: @@Name: shiftChar @@ManakaiDOM:isForInternal:1 @@ForCheck: ManakaiDOM|ForClass @@enDesc: Returns the next character. @@Return: @@@Type: idl|long||ManakaiDOM|all @@@enDesc: The code position number of the next character, if any, or . @@@PerlDef: if (@{$self->{char}}) { $r = shift @{$self->{char}}; } else { no warnings 'substr'; ## substr outside length warnings at the end of the string GETCHAR: { my $char = substr (${$self->{entity}->[-1]->{reptxt}}, $self->{entity}->[-1]->{pos}, 1); $self->{entity}->[-1]->{pos}++; if (defined $char and length $char) { $r = ord $char; if ($r == 0x000A) { $self->{entity}->[-1]->{line}++; $self->{entity}->[-1]->{column} = 1; } elsif ($r == 0x000D) { my $next_char = substr (${$self->{entity}->[-1]->{reptxt}}, $self->{entity}->[-1]->{pos}, 1); if ($next_char eq "\x0A") { $self->{entity}->[-1]->{pos}++; $self->{entity}->[-1]->{column} = 1; } elsif ($next_char eq "\x85") { if ($self->{xml_version} eq '1.1') { $self->{entity}->[-1]->{pos}++; $self->{entity}->[-1]->{column} = 1; } else { $self->{entity}->[-1]->{column} = 0; } } else { $self->{entity}->[-1]->{column} = 1; } $r = 0x000A; $self->{entity}->[-1]->{line}++; } elsif ( not ((0x0020 <= $r and $r <= 0x007E) or (0x00A0 <= $r and $r <= 0xD7FF) or (0xE000 <= $r and $r <= 0xFFFD) or (0x10000 <= $r and $r <= 0x10FFFF)) and $r != 0x0009 and $r != 0x0085 and not ($self->{xml_version} eq '1.0' and (0x007F <= $r and $r <= 0x009F)) ) { my $location = { utf32_offset => $self->{entity}->[-1]->{pos}, line_number => $self->{entity}->[-1]->{line}, column_number => $self->{entity}->[-1]->{column}, }; my $continue = __DOMCore:ERROR{xp|wf-legal-literal-character:: DOMCore|location => {$location}, xp|character-number => {$r}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; $self->{entity}->[-1]->{column}++; } elsif ($r == 0x0085 or $r == 0x2028) { $r = 0x000A if $self->{xml_version} eq '1.1'; $self->{entity}->[-1]->{line}++; $self->{entity}->[-1]->{column} = 1; } else { $self->{entity}->[-1]->{column}++; } # } elsif (@{$self->{entity}} > 1) { # pop @{$self->{entity}}; # redo GETCHAR; # ## ISSUE: How cope with delimiter scanning & # ## self-containedness constraints?? } else { $r = -1; } } # GETCHAR } @Method: @@ManakaiDOM:isForInternal: 1 @@Operator: ManakaiDOM|MUErrorHandler @@enDesc: When a is ed, then this method is invoked. The method calls the if the error is of . Otherwise, the error is re-thrown so that corresponding clause, if any, can catch the error. @@Param: @@@Name: err @@@Type: ecore|ErrorInterface||ManakaiDOM|Perl @@@enDesc: The reported error object. @@Return: @@@Type: DISPerl|Any @@@enDesc: If the is a , then the return value of the error handler. {NOTE:: If the error is thrown, the method never returns. } @@@nullCase: @@@@enDesc: No error handler. @@@PerlDef: if ($err->isa ()) { __DEEP{ A: { my $cfg = $self->; my $h = $cfg-> ('error-handler'); $r = $h-> ($err); } # A }__; } else { $err->; } @DISPerl:dpgDef: /* XML Document Entity document := prolog element *Misc - *Char RestrictedChar *Char ;; [1] */ rule DocumentEntity : standalone { /* prolog := XMLDecl? *Misc [doctypedecl *Misc] ;; [22] */ ?lexmode 'DocumentStart'; my $doc; lang:Perl { $doc = $self->{doc}; } ~? (XDO) { &_XMLDeclaration_ ($doc => $doc); ~ (PIC) { ?lexmode DocumentProlog; } else { ?lexmode DocumentProlog; } } else { ?lexmode 'DocumentProlog'; } // *Misc ~* (CDO) { &_CommentDeclaration_ ($doc => $doc, $parent => $doc); ~ (MDC) { ?lexmode DocumentProlog; } else { ?lexmode DocumentProlog; } } (PIO) { &_ProcessingInstruction_ ($doc => $doc, $parent => $doc); ~ (PIC) { ?lexmode 'DocumentProlog'; } else { ?lexmode DocumentProlog; } } (S) { // } // doctypedecl ~? (MDO) { &_DocumentTypeDeclaration_ ($doc => $doc); ~ (MDC) { ?lexmode DocumentMisc; } else { ?lexmode DocumentMisc; } } else { lang:Perl { $self->{standalone} = true; } ?lexmode DocumentMisc; } // *Misc ~* (CDO) { &_CommentDeclaration_ ($doc => $doc, $parent => $doc); ~ (MDC) { ?lexmode DocumentMisc; } else { ?lexmode DocumentMisc; } } (PIO) { &_ProcessingInstruction_ ($doc => $doc, $parent => $doc); ~ (PIC) { ?lexmode 'DocumentMisc'; } else { ?lexmode DocumentMisc; } } (S) { // } // Document element ~ (STAGO) { &Element_ ($doc => $doc, $parent => $doc) : unshift-current-token; ~ (TAGC) { ?lexmode DocumentEnd; } else { ?lexmode DocumentEnd; } } else { ?lexmode 'DocumentEnd'; } // *Misc ~* (CDO) { &_CommentDeclaration_ ($doc => $doc, $parent => $doc); ~ (MDC) { ?lexmode DocumentEnd; } else { ?lexmode DocumentEnd; } } (PIO) { &_ProcessingInstruction_ ($doc => $doc, $parent => $doc); ~ (PIC) { ?lexmode 'DocumentEnd'; } else { ?lexmode DocumentEnd; } } (S) { // } ~ (#EOF) { } lang:Perl { if ($self->{has_error}) { __EXCEPTION{DOMLS|PARSE_ERR:: }__; } } } // DocumentEntity /* Internal General Parsed Entity An internal general parsed entity is well-formed if its replacement text matches the production labeled |content|. */ rule InternalGeneralParsedEntity ($ent) : standalone { ?lexmode ElementContent; my $ns; lang:Perl { $ns = { xml => , xmlns => , }; } &content ($parent => $ent, $ns => $ns); ~ (#EOF) { } } // InternalGeneralParsedEntity /* XML Declaration XMLDecl := '' ;; [23] NOTE: XML declaration is optional in XML 1.0 while it is required in XML 1.1. */ rule _XMLDeclaration_ ($doc) { ?lexmode XMLDeclaration; ~ (S) { } ~ (Name == 'version') { ~? (S) { } ~ (VI) { } ~? (S) { } my $ver; my $bad_token; ~ (LIT) { ?lexmode AttributeValueLiteral; ~ (STRING) { lang:Perl ($version => $token.value) { $ver = $version; $bad_token = $token; } } ~ (LIT) { ?lexmode XMLDeclaration; } } (LITA) { ?lexmode AttributeValueLiteralA; ~ (STRING) { lang:Perl ($version => $token.value) { $ver = $version; $bad_token = $token; } } ~ (LITA) { ?lexmode XMLDeclaration; } } lang:Perl : has-error { unless ($ver eq '1.0' or $ver eq '1.1') { my $location; __CODE{xp|get-location-from-token:: $token => {$bad_token}, $result => {$location}, }__; my $continue = __DOMCore:ERROR{xp|wf-unsupported-xml-version:: DOMCore|location => {$location}, xp|parent => {$doc}, infoset|version => {$ver}, xp|error-token => {$bad_token}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } $doc-> ($ver); $self->{xml_version} = $ver; } ~? (S) { } } ~? (Name == 'encoding') { ~? (S) { } ~ (VI) { } ~? (S) { } my $ver; my $bad_token; ~ (LIT) { ?lexmode AttributeValueLiteral; ~ (STRING) { lang:Perl ($version => $token.value) { $ver = $version; $bad_token = $token; } } ~ (LIT) { ?lexmode XMLDeclaration; } } (LITA) { ?lexmode AttributeValueLiteralA; ~ (STRING) { lang:Perl ($version => $token.value) { $ver = $version; $bad_token = $token; } } ~ (LITA) { ?lexmode XMLDeclaration; } } lang:Perl : has-error { unless ($ver =~ /\A[A-Za-z][A-Za-z0-9._-]*\z/) { my $location; __CODE{xp|get-location-from-token:: $token => {$bad_token}, $result => {$location}, }__; my $continue = __DOMCore:ERROR{xp|wf-malformed-enc-name:: DOMCore|location => {$location}, xp|parent => {$doc}, xp|name => {$ver}, xp|error-token => {$bad_token}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } $doc-> ($ver); } ~? (S) { } } ~? (Name == 'standalone') { ~? (S) { } ~ (VI) { } ~? (S) { } my $ver; my $bad_token; ~ (LIT) { ?lexmode AttributeValueLiteral; ~ (STRING) { lang:Perl ($version => $token.value) { $ver = $version; $bad_token = $token; } } ~ (LIT) { ?lexmode XMLDeclaration; } } (LITA) { ?lexmode AttributeValueLiteralA; ~ (STRING) { lang:Perl ($version => $token.value) { $ver = $version; $bad_token = $token; } } ~ (LITA) { ?lexmode XMLDeclaration; } } lang:Perl : has-error { unless ($ver eq 'yes' or $ver eq 'no') { my $location; __CODE{xp|get-location-from-token:: $token => {$bad_token}, $result => {$location}, }__; my $continue = __DOMCore:ERROR{xp|wf-malformed-xml-standalone:: DOMCore|location => {$location}, xp|parent => {$doc}, xp|name => {$ver}, xp|error-token => {$bad_token}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } $doc-> ($ver); $self->{standalone} = true if $ver eq 'yes'; } ~? (S) { } } // ~ (PIC) { } } // _XMLDeclaration_ /* Comment Declaration Comment := '' ;; [15] */ rule _CommentDeclaration_ ($doc, $parent) { ?lexmode 'CommentDeclaration'; ~? (STRING) { lang:Perl ($data => $token.value) { my $com = $doc-> ($data); $parent-> ($com); } } else { lang:Perl { my $com = $doc-> (''); $parent-> ($com); } } ~ (COM) { ?lexmode MarkupDeclaration; } else { ?lexmode MarkupDeclaration; } // ~ (MDC) { } } // _CommentDeclaration _ rule _CommentDeclarationDTD ($doc) { ?lexmode 'CommentDeclaration'; ~? (STRING) { // } ~ (COM) { ?lexmode MarkupDeclaration; } else { ?lexmode MarkupDeclaration; } ~ (MDC) { ?lexmode DTD; } else { ?lexmode DTD; } } // _CommentDeclarationDTD /* Processing Instruction PI := '' *Char] '?>' ;; [16] */ rule _ProcessingInstruction_ ($doc, $parent) { ?lexmode 'PIName'; my $pi; ~ (Name) { lang:Perl ($name => $token.value) : has-error { if (lc $name eq 'xml') { my $location; __CODE{xp|get-location-from-token:: $token => {$token}, $result => {$location}, }__; my $continue = __DOMCore:ERROR{xp|wf-pi-target-is-xml:: xp|name => {$name}, DOMCore|location => {$location}, xp|parent => {$parent}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR:: }__; } $self->{has_error} = true; } ## TODO: Namespace well-formedness $pi = $doc-> ($name); } } ~ (S) { ?lexmode 'PIData'; my $tdata; ~? (DATA) { lang:Perl ($data => $token.value) { $tdata = $data; } } else { lang:Perl { $tdata = ''; } } lang:Perl { $pi-> ($tdata); } } lang:Perl { $parent-> ($pi); } // ~ (PIC) { } } // _ProcessingInstruction_ /* Processing instruction in DTD */ rule _ProcessingInstructionDTD ($doc, $doctype) { ?lexmode 'PIName'; my $pi; ~ (Name) { lang:Perl ($name => $token.value) : has-error { if (lc $name eq 'xml') { my $location; __CODE{xp|get-location-from-token:: $token => {$token}, $result => {$location}, }__; my $continue = __DOMCore:ERROR{xp|wf-pi-target-is-xml:: xp|name => {$name}, DOMCore|location => {$location}, xp|parent => {$doctype}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR:: }__; } $self->{has_error} = true; } ## TODO: Namespace well-formedness $pi = $doc-> ($name); } } ~ (S) { ?lexmode 'PIData'; my $tdata; ~? (DATA) { lang:Perl ($data => $token.value) { $tdata = $data; } } else { lang:Perl { $tdata = ''; } } lang:Perl { $pi-> ($tdata); } } lang:Perl { $doctype-> ($pi); } ~ (PIC) { ?lexmode DTD; } else { ?lexmode DTD; } } // _ProcessingInstructionDTD /* Element content parsing mode element := EmptyElemTag / STag content ETag ;; [39] content := (CharData / element / Reference / CDSect / PI / Comment) ;; [43] */ rule Element_ ($doc, $parent, $ns) : standalone { ?lexmode 'ElementContent'; my $node; // Current "parent" node my $nodes; // Node stack (w/o $current_node) my $type; // Current "parent" element type QName my $types; // Element type stack (w/o $current_type) //my $ns; // Current in-scope namespace bindings my $nses; // Namespace binding stack (w/o $current_ns) lang:Perl { $node = $parent; $nodes = []; $type = ''; $types = []; $ns ||= { xml => , xmlns => , }; $nses = []; } ~* : name => CONTENT (CharData) { // Character data lang:Perl ($data => $token.value) { $node-> ($doc-> ($data)); } } (STAGO) { // Start tag or empty element tag ?lexmode 'StartTag'; ~ (Name) { my $attrs; lang:Perl ($name => $token.value) { push @{$types}, $type; $type = $name; $attrs = {}; } ~? (S) { &AttributeSpecificationList ($doc => $doc, $attrs => $attrs); } my $el; /* Note that this implementation does not perform attribute value tokenization (but does white space normalization common to attribute types) and construct the tree as is. DOM Level 3 Core spec is unclear on this point. With tokenization, entity references cannot be preserved. The manakai Node.nodeValue and Attr.value attributes do tokenization according to attribute types. */ /* ISSUE: Should |xml:id| attribute be typed? */ lang:Perl { push @{$nses}, $ns; $ns = {%$ns}; my %gattr; my %lattr; for my $atqname (keys %$attrs) { my ($pfx, $lname) = split /:/, $atqname; $attrs->{$atqname}->{def} = $self->{attr}->{$type}->{$atqname}; if (defined $lname) { ## Global attribute ## TODO: Namespace well-formedness (lname is NCName) if ($pfx eq 'xmlns') { my $nsuri = $attrs->{$atqname}->{value}; if ($lname eq 'xml' and $nsuri ne ) { ## TODO: error } elsif ($lname eq 'xmlns') { ## TODO: error } if ($nsuri eq '') { ## TODO: error in XML 1.0 } elsif ($nsuri eq and $lname ne 'xml') { ## TODO: error } elsif ($nsuri eq ) { ## TODO: error } $ns->{$lname} = $attrs->{$atqname}->{value}; if ($attrs->{$atqname}->{def}) { my $dt = $attrs->{$atqname}->{def}->; if ({ => true, => true, => true, => true, => true, => true, => true, => true, => true, }->{$dt}) { ## Tokenization (XML 1 3.3.3) for ($ns->{$lname}) { s/^\x20+//; s/\x20+\z//; s/\x20+/ /g; } } } delete $ns->{$lname} unless length $ns->{$lname}; } elsif ($pfx eq '') { ## TODO: pfx is not NCName error } else { if ($gattr{$pfx}->{$lname}) { ## TODO: Namespace well-formedness error } } $gattr{$pfx}->{$lname} = $attrs->{$atqname}; } else { ## Local attribute if ($pfx eq 'xmlns') { $ns->{''} = $attrs->{xmlns}->{value}; if ($attrs->{$atqname}->{def}) { my $dt = $attrs->{$atqname}->{def}->; if ({ => true, => true, => true, => true, => true, => true, => true, => true, => true, }->{$dt}) { ## Tokenization (XML 1 3.3.3) for ($ns->{''}) { s/^\x20+//; s/\x20+\z//; s/\x20+/ /g; } } } delete $ns->{''} unless length $ns->{''}; } else { $lattr{$pfx} = $attrs->{$atqname}; } } } my ($pfx, $lname) = split /:/, $type; my $nsuri; ## TODO: lname is NCName? if (defined $lname) { ## Prefixed namespace if ($pfx eq '') { ## TODO: pfx is not NCName error } if (defined $ns->{$pfx}) { $nsuri = $ns->{$pfx}; } else { ## TODO: namespace ill-formed } } else { ## Default namespace $nsuri = $ns->{''}; } $el = $doc-> ($nsuri, $type); if ($attrs->{xmlns}) { my $attr = $doc-> (, 'xmlns'); for (@{$attrs->{xmlns}->{nodes}}) { $attr-> ($_); } if ($attrs->{xmlns}->{def}) { __CODE{t|setAttrType:: $attr => $attr, $type => {$attrs->{xmlns}->{def}->}, }__; } $el-> ($attr); } for my $lname (keys %lattr) { my $attr = $doc-> (null, $lname); for (@{$lattr{$lname}->{nodes}}) { $attr-> ($_); } if ($attrs->{$lname}->{def}) { __CODE{t|setAttrType:: $attr => $attr, $type => {$attrs->{$lname}->{def}->}, }__; } $el-> ($attr); } for my $pfx (keys %gattr) { for my $lname (keys %{$gattr{$pfx}}) { my $attr = $doc-> ($ns->{$pfx}, $pfx.':'.$lname); for (@{$gattr{$pfx}->{$lname}->{nodes}}) { $attr-> ($_); } if ($attrs->{$pfx}->{$lname}->{def}) { __CODE{t|setAttrType:: $attr => $attr, $type => {$attrs->{$pfx}->{$lname} ->{def}->}, }__; } $el-> ($attr); } } $node-> ($el); } ~ (TAGC) { lang:Perl { push @{$nodes}, $node; $node = $el; } ?lexmode ElementContent; } (NESTC) { my $is_docel; lang:Perl { $ns = pop @{$nses}; $type = pop @{$types}; $is_docel = (@{$types} == 0); } if-true ($is_docel) { return; } ~ (TAGC) { ?lexmode ElementContent; } else { ?lexmode ElementContent; } } else { ?lexmode ElementContent; } } else { ?lexmode ElementContent; } } (ETAGO) { // End tag ?lexmode 'EndTag'; my $is_docel; ~ (Name) { lang:Perl ($name => $token.value) : has-error { if ($name eq $type) { $type = pop @{$types}; if ($type eq '') { $is_docel = true; } $node = pop @{$nodes}; $ns = pop @{$nses}; } else { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-element-type-match:: DOMCore:location => {$location}, xp|token => {$token}, xp|expected-element-type => {$type}, xp|actual-element-type => {$name}, xp|node => {$node}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } } } ~? (S) { } if-true ($is_docel) { lang:Perl : has-error { if (@{$types}) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; for my $type (reverse @{$types}) { my $continue = __DOMCore:ERROR{xp|wf-no-end-tag:: DOMCore:location => {$location}, xp|token => {$token}, xp|expected-element-type => {$type}, xp|node => {$node}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $node = shift @{$nodes}; } $self->{has_error} = true; } } return; } ~ (TAGC) { ?lexmode ElementContent; } else { ?lexmode 'ElementContent'; } } (HCRO) { &_HexadecimalCharacterReference_ ($doc => $doc, $parent => $node); ~ (REFC) { ?lexmode 'ElementContent'; } else { ?lexmode ElementContent; } } (CRO) { &_NumericCharacterReference_ ($doc => $doc, $parent => $node); ~ (REFC) { ?lexmode 'ElementContent'; } else { ?lexmode ElementContent; } } (ERO) { &_GeneralEntityReferenceEC ($doc => $doc, $parent => $node, $ns => $ns); } (CDO) { &_CommentDeclaration_ ($doc => $doc, $parent => $node); ~ (MDC) { ?lexmode ElementContent; } else { ?lexmode ElementContent; } } (CDSO) { &_CDATASection_ ($doc => $doc, $parent => $node); ~ (MSE) { ?lexmode 'ElementContent'; } else { ?lexmode ElementContent; } } (PIO) { &_ProcessingInstruction_ ($doc => $doc, $parent => $node); ~ (PIC) { ?lexmode 'ElementContent'; } else { ?lexmode ElementContent; } } ~ (#NONE) { } } // Element_ /* content := [CharData] *((element / Reference / CDSect / PI / Comment) [CharData]) */ rule content ($parent, $ns) { // ?lexmode ElementContent; my $doc; lang:Perl { $doc = $self->{doc}; } ~* (CharData) { lang:Perl ($data => $token.value) { $parent-> ($self->{doc}-> ($data)); } } (STAGO) { &Element_ ($doc => $doc, $parent => $parent, $ns => $ns) : unshift-current-token; ~ (TAGC) { ?lexmode ElementContent; } else { ?lexmode ElementContent; } } (HCRO) { &_HexadecimalCharacterReference_ ($doc => $doc, $parent => $parent); ~ (REFC) { ?lexmode 'ElementContent'; } else { ?lexmode ElementContent; } } (CRO) { &_NumericCharacterReference_ ($doc => $doc, $parent => $parent); ~ (REFC) { ?lexmode 'ElementContent'; } else { ?lexmode ElementContent; } } (ERO) { &_GeneralEntityReferenceEC ($doc => $doc, $parent => $parent, $ns => $ns); } (CDO) { &_CommentDeclaration_ ($doc => $doc, $parent => $parent); ~ (MDC) { ?lexmode ElementContent; } else { ?lexmode ElementContent; } } (CDSO) { &_CDATASection_ ($doc => $doc, $parent => $parent); ~ (MSE) { ?lexmode 'ElementContent'; } else { ?lexmode ElementContent; } } (PIO) { &_ProcessingInstruction_ ($doc => $doc, $parent => $parent); ~ (PIC) { ?lexmode 'ElementContent'; } else { ?lexmode ElementContent; } } } // content rule AttributeSpecificationList ($doc, $attrs) : standalone { ?lexmode 'StartTag'; my $i; lang:Perl { $i = 0; } ~* (Name) { my $atqname; lang:Perl ($name => $token.value) { $atqname = $name; } my $vals; lang:Perl { if ($attrs->{$atqname}) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-unique-att-spec:: DOMCore:location => {$location}, xp|token => {$token}, xp|name => {$atqname}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } $vals = $attrs->{$atqname} = { nodes => [], value => '', index => $i++, }; } ~? (S) { } ~ (VI) { } ~? (S) { } ~ (LIT) { &_AttributeValueSpecification_ ($doc => $doc, $vals => $vals); ~ (LIT) { ?lexmode StartTag; } else { ?lexmode StartTag; } } (LITA) { &_AttributeValueSpecificationA_ ($doc => $doc, $vals => $vals); ~ (LITA) { ?lexmode StartTag; } else { ?lexmode StartTag; } } } (S) : separator : terminator? { } } // AttributeSpecificationList rule _AttributeValueSpecification_ ($doc, $vals) { // ~ (LIT) { } ?lexmode 'AttributeValueLiteral'; ~* (STRING) { lang:Perl ($value => $token.value) { $value =~ s/[\x09\x0A\x0D]/ /g; my $text = $doc-> ($value); push @{$vals->{nodes}}, $text; $vals->{value} .= $value; } } (HCRO) { &_HexadecimalCharacterReferenceV_ ($doc => $doc, $vals => $vals); ~ (REFC) { ?lexmode AttributeValueLiteral; } else { ?lexmode AttributeValueLiteral; } } (CRO) { &_NumericCharacterReferenceV_ ($doc => $doc, $vals => $vals); ~ (REFC) { ?lexmode AttributeValueLiteral; } else { ?lexmode AttributeValueLiteral; } } (ERO) { // TODO: Attribute value normalization &_GeneralEntityReferenceV_ ($doc => $doc, $vals => $vals); ~ (REFC) { ?lexmode AttributeValueLiteral; } else { ?lexmode AttributeValueLiteral; } } // ~ (LIT) { } (LITA) { } } // _AttributeValueSpecification_ rule _AttributeValueSpecificationA_ ($doc, $vals) { // ~ (LITA) { } ?lexmode 'AttributeValueLiteralA'; ~* (STRING) { lang:Perl ($value => $token.value) { $value =~ s/[\x09\x0A\x0D]/ /g; my $text = $doc-> ($value); push @{$vals->{nodes}}, $text; $vals->{value} .= $value; } } (HCRO) { &_HexadecimalCharacterReferenceV_ ($doc => $doc, $vals => $vals); ~ (REFC) { ?lexmode AttributeValueLiteralA; } else { ?lexmode AttributeValueLiteralA; } } (CRO) { &_NumericCharacterReferenceV_ ($doc => $doc, $vals => $vals); ~ (REFC) { ?lexmode AttributeValueLiteralA; } else { ?lexmode AttributeValueLiteralA; } } (ERO) { // TODO: Attribute value normalization &_GeneralEntityReferenceV_ ($doc => $doc, $vals => $vals); ~ (REFC) { ?lexmode AttributeValueLiteralA; } else { ?lexmode AttributeValueLiteralA; } } // ~ (LITA) { } } // _AttributeValueSpecificationA_ /* Parsing replacement text of an entity referenced in an attribute value specification. */ rule AttributeValueLiteralE_ ($parent, $vals) : recursive { // ?lexmode AttributeValueLiteralE; ~* (STRING) { lang:Perl ($value => $token.value) { $value =~ s/[\x09\x0A\x0D]/ /g; my $text = $self->{doc}-> ($value); $parent-> ($text); $vals->{value} .= $value; } } (HCRO) { &_HexadecimalCharacterReferenceAE_ ($parent => $parent, $vals => $vals); ~ (REFC) { ?lexmode AttributeValueLiteralE; } else { ?lexmode AttributeValueLiteralE; } } (CRO) { &_NumericCharacterReferenceAE_ ($parent => $parent, $vals => $vals); ~ (REFC) { ?lexmode AttributeValueLiteralE; } else { ?lexmode AttributeValueLiteralE; } } (ERO) { &_GeneralEntityReferenceAE_ ($parent => $parent, $vals => $vals); ~ (REFC) { ?lexmode AttributeValueLiteralE; } else { ?lexmode AttributeValueLiteralE; } } // ~ (#EOF) { } } // AttributeValueLiteralE_ /* CDATA Section Content Parsing Mode */ rule _CDATASection_ ($doc, $parent) { ?lexmode 'CDATASectionContent'; my $cdata; ~? (CData) { lang:Perl ($data => $token.value) { $cdata = $data; } } else { lang:Perl { $cdata = ''; } } lang:Perl { my $cdsect = $doc-> ($cdata); $parent-> ($cdsect); } // ~ (MSE) { } } // _CDATASection_ rule _NumericCharacterReference_ ($doc, $parent) { ?lexmode 'NumericCharacterReference'; ~ (NUMBER) { lang:Perl ($num => $token.value) : has-error { $num += 0; unless ( ($self->{xml_version} eq '1.0' and ((0x0020 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF) or $num == 0x9 or $num == 0xA or $num == 0xD)) or ($self->{xml_version} eq '1.1' and ((0x0001 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF))) ) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-legal-character:: DOMCore:location => {$location}, xp|token => {$token}, xp|character-number => {$num}, xp|parent => {$parent}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } my $ncr = $doc-> (chr $num); $parent-> ($ncr); } } // ~ (REFC) { } } // _NumericCharacterReference_ rule _NumericCharacterReferenceV_ ($doc, $vals) { ?lexmode 'NumericCharacterReference'; ~ (NUMBER) { lang:Perl ($num => $token.value) : has-error { $num += 0; unless ( ($self->{xml_version} eq '1.0' and ((0x0020 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF) or $num == 0x9 or $num == 0xA or $num == 0xD)) or ($self->{xml_version} eq '1.1' and ((0x0001 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF))) ) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-legal-character:: DOMCore:location => {$location}, xp|token => {$token}, xp|character-number => {$num}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } my $ncr = $doc-> (my $char = chr $num); push @{$vals->{nodes}}, $ncr; $vals->{value} .= $char; } } // ~ (REFC) { } } // _NumericCharacterReferenceV_ /* Numeric character reference in the replacement text of the entity referenced in an attribute value specification */ rule _NumericCharacterReferenceAE_ ($parent, $vals) { ?lexmode NumericCharacterReference; ~ (NUMBER) { lang:Perl ($num => $token.value) : has-error { $num += 0; unless ( ($self->{xml_version} eq '1.0' and ((0x0020 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF) or $num == 0x9 or $num == 0xA or $num == 0xD)) or ($self->{xml_version} eq '1.1' and ((0x0001 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF))) ) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-legal-character:: DOMCore:location => {$location}, xp|token => {$token}, xp|character-number => {$num}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } my $ncr = $self->{doc}-> (my $char = chr $num); $parent-> ($ncr); $vals->{value} .= $char; } } // ~ (REFC) { } } // _NumericCharacterReferenceAE_ rule _NumericCharacterReferenceEV_ ($vals) { ?lexmode 'NumericCharacterReference'; ~ (NUMBER) { lang:Perl ($num => $token.value) : has-error { $num += 0; unless ( ($self->{xml_version} eq '1.0' and ((0x0020 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF) or $num == 0x9 or $num == 0xA or $num == 0xD)) or ($self->{xml_version} eq '1.1' and ((0x0001 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF))) ) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-legal-character:: DOMCore:location => {$location}, xp|token => {$token}, xp|character-number => {$num}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } push @{$vals}, chr $num; } } // ~ (REFC) { } } // _NumericCharacterReferenceEV_ rule _HexadecimalCharacterReference_ ($doc, $parent) { ?lexmode 'HexadecimalCharacterReference'; ~ (Hex) { lang:Perl ($v => $token.value) : has-error { my $num = hex $v; unless ( ($self->{xml_version} eq '1.0' and ((0x0020 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF) or $num == 0x9 or $num == 0xA or $num == 0xD)) or ($self->{xml_version} eq '1.1' and ((0x0001 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF))) ) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-legal-character:: DOMCore:location => {$location}, xp|token => {$token}, xp|character-number => {$num}, xp|parent => {$parent}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } my $ncr = $doc-> (chr $num); $parent-> ($ncr); } } // ~ (REFC) { } } // _HexadecimalCharacterReference_ rule _HexadecimalCharacterReferenceV_ ($doc, $vals) { ?lexmode 'HexadecimalCharacterReference'; ~ (Hex) { lang:Perl ($v => $token.value) : has-error { my $num = hex $v; unless ( ($self->{xml_version} eq '1.0' and ((0x0020 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF) or $num == 0x9 or $num == 0xA or $num == 0xD)) or ($self->{xml_version} eq '1.1' and ((0x0001 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF))) ) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-legal-character:: DOMCore:location => {$location}, xp|token => {$token}, xp|character-number => {$num}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } my $ncr = $doc-> (my $char = chr $num); push @{$vals->{nodes}}, $ncr; $vals->{value} .= $char; } } // ~ (REFC) { } } // _HexadecimalCharacterReferenceV_ /* Hexadecimal character reference in the replacement text of the entity referenced in an attribute value literal */ rule _HexadecimalCharacterReferenceAE_ ($parent, $vals) { ?lexmode HexadecimalCharacterReference; ~ (Hex) { lang:Perl ($v => $token.value) : has-error { my $num = hex $v; unless ( ($self->{xml_version} eq '1.0' and ((0x0020 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF) or $num == 0x9 or $num == 0xA or $num == 0xD)) or ($self->{xml_version} eq '1.1' and ((0x0001 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF))) ) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-legal-character:: DOMCore:location => {$location}, xp|token => {$token}, xp|character-number => {$num}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } my $ncr = $self->{doc}-> (my $char = chr $num); $parent-> ($ncr); $vals->{value} .= $char; } } // ~ (REFC) { } } // _HexadecimalCharacterReferenceAE_ rule _HexadecimalCharacterReferenceEV_ ($vals) { ?lexmode HexadecimalCharacterReference; ~ (Hex) { lang:Perl ($v => $token.value) : has-error { my $num = hex $v; unless ( ($self->{xml_version} eq '1.0' and ((0x0020 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF) or $num == 0x9 or $num == 0xA or $num == 0xD)) or ($self->{xml_version} eq '1.1' and ((0x0001 <= $num and $num <= 0xD7FF) or (0xE000 <= $num and $num <= 0xFFFD) or (0x10000 <= $num and $num <= 0x10FFFF))) ) { my $location; __CODE{xp|get-location-from-token:: $token => $token, $result => $location, }__; my $continue = __DOMCore:ERROR{xp|wf-legal-character:: DOMCore:location => {$location}, xp|token => {$token}, xp|character-number => {$num}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR}__; } $self->{has_error} = true; } push @{$vals}, chr $num; } } // ~ (REFC) { } } // _HexadecimalCharacterReferenceEV_ /* General entity reference in element's content */ rule _GeneralEntityReferenceEC ($doc, $parent, $ns) : recursive { ?lexmode 'EntityReference'; ~ (Name == 'lt') { lang:Perl { $parent-> ($self->{doc}-> ('<')); } } (Name == 'gt') { lang:Perl { $parent-> ($self->{doc}-> ('>')); } } (Name == 'amp') { lang:Perl { $parent-> ($self->{doc}-> ('&')); } } (Name == 'quot') { lang:Perl { $parent-> ($self->{doc}-> ('"')); } } (Name == 'apos') { lang:Perl { $parent-> ($self->{doc}-> ("'")); } } (Name) { my $er; lang:Perl ($name => $token.value) { ## TODO: Namespace well-formedness ## TODO: Entity declared constraints $er = $doc-> ($name); $parent-> ($er); push @{$self->{entity}}, ; push @{$self->{entity_token}}, $self->{token}; $self->{token} = []; push @{$self->{entity_char}}, $self->{char}; $self->{char} = []; } ?lexmode ElementContent; &content ($doc => $doc, $parent => $er, $ns => $ns); ~ (#EOF) { } lang:Perl { $self->{token} = pop @{$self->{entity_token}}; $self->{char} = pop @{$self->{entity_char}}; pop @{$self->{entity}}; } // TODO: Set read-only flag ?lexmode EntityReference; ?requires-next-token; } ~ (REFC) { ?lexmode ElementContent; } else { ?lexmode ElementContent; } } // _GeneralEntityReferenceEC /* General entity reference in an attribute value literal */ rule _GeneralEntityReferenceV_ ($vals) { ?lexmode EntityReference; ~ (Name == 'lt') { lang:Perl { push @{$vals->{nodes}}, $self->{doc}-> ('<'); $vals->{value} .= '<'; } } (Name == 'gt') { lang:Perl { push @{$vals->{nodes}}, $self->{doc}-> ('>'); $vals->{value} .= '>'; } } (Name == 'amp') { lang:Perl { push @{$vals->{nodes}}, $self->{doc}-> ('&'); $vals->{value} .= '&'; } } (Name == 'quot') { lang:Perl { push @{$vals->{nodes}}, $self->{doc}-> ('"'); $vals->{value} .= '"'; } } (Name == 'apos') { lang:Perl { push @{$vals->{nodes}}, $self->{doc}-> ("'"); $vals->{value} .= "'"; } } (Name) { my $er; lang:Perl ($name => $token.value) { ## TODO: Namespace well-formedness ## TODO: Entity declared constraints ## TODO: No external entity constraint $er = $self->{doc}-> ($name); push @{$vals->{nodes}}, $er; push @{$self->{entity}}, ; push @{$self->{entity_token}}, $self->{token}; $self->{token} = []; push @{$self->{entity_char}}, $self->{char}; $self->{char} = []; } ?lexmode AttributeValueLiteralE; &AttributeValueLiteralE_ ($parent => $er, $vals => $vals); ~ (#EOF) { } lang:Perl { $self->{token} = pop @{$self->{entity_token}}; $self->{char} = pop @{$self->{entity_char}}; pop @{$self->{entity}}; } // TODO: Set read-only flag ?lexmode EntityReference; ?requires-next-token; } // ~ (REFC) { } } // _GeneralEntityReferenceV_ /* General entity reference in the replacement text of the entity referenced in an attribute value literal */ rule _GeneralEntityReferenceAE_ ($parent, $vals) { ?lexmode EntityReference; ~ (Name == 'lt') { lang:Perl { $parent-> ($self->{doc}-> ('<')); $vals->{value} .= '<'; } } (Name == 'gt') { lang:Perl { $parent-> ($self->{doc}-> ('>')); $vals->{value} .= '>'; } } (Name == 'amp') { lang:Perl { $parent-> ($self->{doc}-> ('&')); $vals->{value} .= '&'; } } (Name == 'quot') { lang:Perl { $parent-> ($self->{doc}-> ('"')); $vals->{value} .= '"'; } } (Name == 'apos') { lang:Perl { $parent-> ($self->{doc}-> ("'")); $vals->{value} .= "'"; } } (Name) { my $er; lang:Perl ($name => $token.value) { ## TODO: Namespace well-formedness ## TODO: Entity declared constraints ## TODO: No external entity constraint $er = $self->{doc}-> ($name); $parent-> ($er); push @{$self->{entity}}, ; push @{$self->{entity_token}}, $self->{token}; $self->{token} = []; push @{$self->{entity_char}}, $self->{char}; $self->{char} = []; } ?lexmode AttributeValueLiteralE; &AttributeValueLiteralE_ ($parent => $er, $vals => $vals); ~ (#EOF) { } lang:Perl { $self->{token} = pop @{$self->{entity_token}}; $self->{char} = pop @{$self->{entity_char}}; pop @{$self->{entity}}; } // TODO: Set read-only flag ?lexmode EntityReference; ?requires-next-token; } // ~ (REFC) { } } // _GeneralEntityReferenceAE_ /* General entity reference in literal entity value */ rule _GeneralEntityReferenceEV_ ($vals) { ?lexmode 'EntityReference'; ~ (Name) { lang:Perl ($name => $token.value) { ## TODO: Namespace well-formedness ## TODO: Entity declared constraints push @$vals, $name; } } // No expansion // ~ (REFC) { } } // _GeneralEntityReferenceEV_ /* Document Type Declaration */ rule _DocumentTypeDeclaration_ ($doc) { ?lexmode MarkupDeclaration; ~ (Name == 'DOCTYPE') { } ~ (S) { } my $node; // Document type name my $name; ~ (Name) { lang:Perl ($v => $token.value) { $name = $v; } } lang:Perl { $self->{docx} = $self->{doc} -> (, '3.0'); $node = $self->{docx}-> ($name); } ~? (S) { ~? (Name == 'PUBLIC') { ~ (S) { } &PubidLiteral ($doc => $doc); ~ (S) { } &SystemLiteral ($doc => $doc); ~? (S) { } } (Name == 'SYSTEM') { ~ (S) { } &SystemLiteral ($doc => $doc); ~? (S) { } } } lang:Perl { $self->{dtdef} = $node; $doc-> ($node); $doc-> -> ('schema-type' => ); } ~? (DSO) { &InternalSubset ($doc => $doc, $doctype => $node); ~ (DSC) { ?lexmode MarkupDeclaration; } else { ?lexmode MarkupDeclaration; } ~? (S) { } } // TODO: set $self->{standalone} true if only internal subset // with no param ref // ~ (MDC) { } } // _DocumentTypeDeclaration_ rule PubidLiteral ($doc) { ~ (LIT) { ?lexmode SystemLiteral; ~? (STRING) { // TODO: Charrange check & normalization is required } ~ (LIT) { ?lexmode MarkupDeclaration; } else { ?lexmode MarkupDeclaration; } } (LITA) { ?lexmode SystemLiteralA; ~? (STRING) { // TODO: Charrange check & normalization is required } ~ (LITA) { ?lexmode MarkupDeclaration; } else { ?lexmode MarkupDeclaration; } } } // PubidLiteral rule SystemLiteral ($doc) { ~ (LIT) { ?lexmode SystemLiteral; &_SystemLiteral ($doc => $doc); } (LITA) { ?lexmode SystemLiteralA; &_SystemLiteral ($doc => $doc); } } // SystemLiteral rule _SystemLiteral ($doc) { ~? (STRING) { } ~ (LIT) { ?lexmode MarkupDeclaration; } (LITA) { ?lexmode MarkupDeclaration; } else { ?lexmode MarkupDeclaration; } } // _SystemLiteral /* DTD Internal Subset intSubset := *(markupdecl / DeclSep) ;; [28b] */ rule InternalSubset ($doc, $doctype) { ?lexmode DTD; ~* (MDO) { ?lexmode MarkupDeclaration; ~ (Name == 'ELEMENT') { &_ElementDeclaration ($doc => $doc); } (Name == 'ATTLIST') { &_AttlistDeclaration ($doc => $doc, $doctype => $doctype); } (Name == 'ENTITY') { &_EntityDeclaration ($doc => $doc); } (Name == 'NOTATION') { &_NotationDeclaration ($doc => $doc); } } (S) { // } (CDO) { &_CommentDeclarationDTD ($doc => $doc); } (PIO) { &_ProcessingInstructionDTD ($doc => $doc, $doctype => $doctype); } (PERO) { ?lexmode EntityReference; ~ (Name) { } ~ (REFC) { ?lexmode DTD; } else { ?lexmode DTD; } } } // InternalSubset rule _ElementDeclaration ($doc) { // ~ (MDO) { } // ?lexmode MarkupDeclaration // ~ (Name == 'Element') { } ~ (S) { } ~ (Name) { } ?lexmode ElementDeclaration; ~ (S) { } // contentspec ~ (MGO) { &_ContentModel ($doc => $doc); } (Name == 'EMPTY') { } (Name == 'ANY') { } ~? (S) { } ~ (MDC) { ?lexmode DTD; } else { ?lexmode DTD; } } // _ElementDeclaration rule _ContentModel ($doc) { // ~ (MGO) { } ~? (S) { } ~ (Name) { // Element content model &_ModelGroup ($doc => $doc) : unshift-current-token; ~? (OPT) { } (REP) { } (PLUS) { } } (MDO) { &_ModelGroup ($doc => $doc) : unshift-current-token; ~? (OPT) { } (REP) { } (PLUS) { } } (PCDATA) { // Mixed content declaration ~? (S) { } ~* (OR) { ~? (S) { } ~ (Name) { } ~? (S) { } } ~ (MGC) { } ~? (REP) { } else { // TODO: error if |Name| } } } // _ContentModel rule _ModelGroup ($doc) : standalone : recursive { // ~ (MGO) { } // ~? (S) { } &ContentParticle ($doc => $doc); ~? (S) { } ~? (OR) { ~? (S) { } &ContentParticle ($doc => $doc); ~? (S) { } ~* (OR) { ~? (S) { } &ContentParticle ($doc => $doc); ~? (S) { } } } (SEQ) { ~? (S) { } &ContentParticle ($doc => $doc); ~? (S) { } ~* (SEQ) { ~? (S) { } &ContentParticle ($doc => $doc); ~? (S) { } } } ~ (MGC) { } } // _ModelGroup rule ContentParticle ($doc) { ~ (Name) { } (MGO) { ~? (S) { } &_ModelGroup ($doc => $doc); } ~? (OPT) { } (REP) { } (PLUS) { } } // ContentParticle /* Attribute list declaration */ rule _AttlistDeclaration ($doc, $doctype) { // ~ (MDO) { } // ~ (Name == 'ATTLIST') { } ?lexmode AttlistDeclaration; ~ (S) { } my $name; ~ (Name) { lang:Perl ($v => $token.value) { $name = $v; } } else { lang:Perl { $name = '#ILLEGAL' } } my $docxd; my $et; lang:Perl { $et = $doctype-> ($name); unless ($et) { $docxd = $doc-> (, '3.0'); $et = $docxd-> ($name); $doctype-> ($et) unless $name eq '#ILLEGAL'; } } ~? (S) { } ~* (Name) { my $at; lang:Perl ($v => $token.value) { $docxd ||= $doc-> (, '3.0'); $at = $docxd-> ($v); unless (exists $et->->{$v}) { $et-> ($at); $self->{attr}->{$name}->{$v} = $at; } } ~ (S) { } // AttType ~ (Name == 'NOTATION') { ~ (S) { } my $kwd; lang:Perl { $at-> (); $kwd = $at->; } ~ (EGO) { ~? (S) { } ~+ (Name) { lang:Perl ($v => $token.value) { push @$kwd, $v; } ~? (S) { } } (OR) : separator { ~? (S) { } } ~ (EGC) { } } } (Name) { my $type; lang:Perl ($v => $token.value) : has-error { my $map = { CDATA => , ID => , IDREF => , IDREFS => , ENTITY => , ENTITIES => , NMTOKEN => , NMTOKENS => , }; if ($map->{$v}) { $at-> ($map->{$v}); } else { ## TODO: Exception } } } (EGO) { ?lexmode Enumeration; ~? (S) { } my $kwd; lang:Perl { $at-> (); $kwd = $at->; } ~+ (Nmtoken) { lang:Perl ($v => $token.value) { push @$kwd, $v; } ~? (S) { } } (OR) : separator { ~? (S) { } } ~ (EGC) { ?lexmode AttlistDeclaration; } else { ?lexmode AttlistDeclaration; } } ~ (S) { } // DefaultDecl ~ (RNI) { ~ (Name == 'REQUIRED') { lang:Perl { $at-> (); } } (Name == 'IMPLIED') { lang:Perl { $at-> (); } } (Name == 'FIXED') { ~ (S) { } lang:Perl { $at-> (); } ~ (LIT) { my $vals; lang:Perl { $vals = {nodes => [], value => ''}; } &_AttributeValueSpecification_ ($doc => $doc, $vals => $vals); lang:Perl { for (@{$vals->{nodes}}) { $at-> ($_); } } ~ (LIT) { ?lexmode AttlistDeclaration; } else { ?lexmode AttlistDeclaration; } } (LITA) { my $vals; lang:Perl { $vals = {nodes => [], value => ''}; } &_AttributeValueSpecificationA_ ($doc => $doc, $vals => $vals); lang:Perl { for (@{$vals->{nodes}}) { $at-> ($_); } } ~ (LITA) { ?lexmode AttlistDeclaration; } else { ?lexmode AttlistDeclaration; } } } } (LIT) { my $vals; lang:Perl { $at-> (); $vals = {nodes => [], value => ''}; } &_AttributeValueSpecification_ ($doc => $doc, $vals => $vals); lang:Perl { for (@{$vals->{nodes}}) { $at-> ($_); } } ~ (LIT) { ?lexmode AttlistDeclaration; } else { ?lexmode AttlistDeclaration; } } (LITA) { my $vals; lang:Perl { $at-> (); $vals = {nodes => [], value => ''}; } &_AttributeValueSpecificationA_ ($doc => $doc, $vals => $vals); lang:Perl { for (@{$vals->{nodes}}) { $at-> ($_); } } ~ (LITA) { ?lexmode AttlistDeclaration; } else { ?lexmode AttlistDeclaration; } } } (S) : separator : terminator? { // } ~ (MDC) { ?lexmode DTD; } else { ?lexmode DTD; } } // _AttlistDeclaration /* Entity declaration */ rule _EntityDeclaration ($doc) { // ~ (MDO) { } // ~ (Name == ENTITY) { } ~ (S) { } my $decl; lang:Perl { $decl = { name => '#ILLEGAL' }; } ~? (PERO) { ~ (S) { } lang:Perl { $decl->{is_param_entity} = true; } } ~ (Name) { lang:Perl ($v => $token.value) { $decl->{name} = $v; } } lang:Perl { $decl->{node} = $self->{docx}-> ($decl->{name}); ## TODO: Parameter entity... } ~ (S) { } ~ (LIT) { &_EntityValue ($doc => $doc, $decl => $decl); } (LITA) { &_EntityValueA ($doc => $doc, $decl => $decl); } (Name == 'PUBLIC') { ~ (S) { } &PubidLiteral ($doc => $doc, $decl => $decl); ~ (S) { } &SystemLiteral ($doc => $doc, $decl => $decl); } (Name == 'SYSTEM') { ~ (S) { } &SystemLiteral ($doc => $doc, $decl => $decl); } ~? (S) { ~? (Name == 'NDATA') { // TODO: error if parameter entity ~ (S) { } ~ (Name) { lang:Perl ($v => $token.value) { $decl->{notation} = $v; $decl->{node}-> ($v); } } ~? (S) { } } } lang:Perl { if ($self->{$decl->{is_param_entity} ? 'param_entity' : 'general_entity'} ->{$decl->{name}}) { ## TODO: warning ## TODO: predefined entity error check } else { $self->{$decl->{is_param_entity} ? 'param_entity' : 'general_entity'} ->{$decl->{name}} = $decl; $self->{dtdef}-> ($decl->{node}) unless $decl->{is_param_entity}; } } ~ (MDC) { ?lexmode DTD; } else { ?lexmode DTD; } } // _EntityDeclaration rule _NotationDeclaration ($doc) { // ~ (MDO) { } // ~ (Name == NOTATION) { } ~ (S) { } ~ (Name) { } ~ (S) { } ~ (Name == 'PUBLIC') { ~ (S) { } &PubidLiteral ($doc => $doc); ~? (S) { ~? (LIT) { ?lexmode SystemLiteral; &_SystemLiteral ($doc => $doc); ~? (S) { } } (LITA) { ?lexmode SystemLiteralA; &_SystemLiteral ($doc => $doc); ~? (S) { } } } } (Name == 'SYSTEM') { ~ (S) { } &SystemLiteral ($doc => $doc); ~? (S) { } } ~ (MDC) { ?lexmode DTD; } else { ?lexmode DTD; } } // _NotationDeclaration rule _EntityValue ($decl) { ?lexmode EntityValue; my $vals; my $reptxt; lang:Perl { $vals = []; $reptxt = ''; } ~* (STRING) { lang:Perl ($v => $token.value) { $reptxt .= $v; } } (PERO) { ?lexmode EntityDeclaration; // TODO: Expand or wferror if internal subset ~ (Name) { } ~ (REFC) { ?lexmode EntityValue; } else { ?lexmode EntityValue; } } (HCRO) { &_HexadecimalCharacterReferenceEV_ ($vals => $vals); lang:Perl { $reptxt .= $vals->[-1]; } ~ (REFC) { ?lexmode EntityValue; } else { ?lexmode EntityValue; } } (CRO) { &_NumericCharacterReferenceEV_ ($vals => $vals); lang:Perl { $reptxt .= $vals->[-1]; } ~ (REFC) { ?lexmode EntityValue; } else { ?lexmode EntityValue; } } (ERO) { &_GeneralEntityReferenceEV_ ($vals => $vals); lang:Perl { $reptxt .= '&' . $vals->[-1] . ';'; } ~ (REFC) { ?lexmode EntityValue; } else { ?lexmode EntityValue; } } ~ (LIT) { ?lexmode MarkupDeclaration; } (LITA) { ?lexmode MarkupDeclaration; } else { ?lexmode MarkupDeclaration; } lang:Perl { $decl->{reptxt} = \$reptxt; } } // _EntityValue rule _EntityValueA ($decl) { ?lexmode EntityValueA; my $vals; my $reptxt; lang:Perl { $vals = []; $reptxt = ''; } ~* (STRING) { lang:Perl ($v => $token.value) { $reptxt .= $v; } } (PERO) { ?lexmode EntityDeclaration; // TODO: implement this ~ (Name) { } ~ (REFC) { ?lexmode EntityValueA; } else { ?lexmode EntityValueA; } } (HCRO) { &_HexadecimalCharacterReferenceEV_ ($vals => $vals); lang:Perl { $reptxt .= $vals->[-1]; } ~ (REFC) { ?lexmode EntityValueA; } else { ?lexmode EntityValueA; } } (CRO) { &_NumericCharacterReferenceEV_ ($vals => $vals); lang:Perl { $reptxt .= $vals->[-1]; } ~ (REFC) { ?lexmode EntityValueA; } else { ?lexmode EntityValueA; } } (ERO) { &_GeneralEntityReferenceEV_ ($vals => $vals); lang:Perl { $reptxt .= '&' . $vals->[-1] . ';'; } ~ (REFC) { ?lexmode EntityValueA; } else { ?lexmode EntityValueA; } } ~ (LITA) { ?lexmode MarkupDeclaration; } else { ?lexmode MarkupDeclaration; } lang:Perl { $decl->{reptxt} = \$reptxt; } } // _EntityValueA /* XML Name */ lexmode NameChar { $NameStartChar10 := [ '_' ':' // Letter // BaseChar U+0041..U+005A U+0061..U+007A U+00C0..U+00D6 U+00D8..U+00F6 U+00F8..U+00FF U+0100..U+0131 U+0134..U+013E U+0141..U+0148 U+014A..U+017E U+0180..U+01C3 U+01CD..U+01F0 U+01F4..U+01F5 U+01FA..U+0217 U+0250..U+02A8 U+02BB..U+02C1 U+0386 U+0388..U+038A U+038C U+038E..U+03A1 U+03A3..U+03CE U+03D0..U+03D6 U+03DA U+03DC U+03DE U+03E0 U+03E2..U+03F3 U+0401..U+040C U+040E..U+044F U+0451..U+045C U+045E..U+0481 U+0490..U+04C4 U+04C7..U+04C8 U+04CB..U+04CC U+04D0..U+04EB U+04EE..U+04F5 U+04F8..U+04F9 U+0531..U+0556 U+0559 U+0561..U+0586 U+05D0..U+05EA U+05F0..U+05F2 U+0621..U+063A U+0641..U+064A U+0671..U+06B7 U+06BA..U+06BE U+06C0..U+06CE U+06D0..U+06D3 U+06D5 U+06E5..U+06E6 U+0905..U+0939 U+093D U+0958..U+0961 U+0985..U+098C U+098F..U+0990 U+0993..U+09A8 U+09AA..U+09B0 U+09B2 U+09B6..U+09B9 U+09DC..U+09DD U+09DF..U+09E1 U+09F0..U+09F1 U+0A05..U+0A0A U+0A0F..U+0A10 U+0A13..U+0A28 U+0A2A..U+0A30 U+0A32..U+0A33 U+0A35..U+0A36 U+0A38..U+0A39 U+0A59..U+0A5C U+0A5E U+0A72..U+0A74 U+0A85..U+0A8B U+0A8D U+0A8F..U+0A91 U+0A93..U+0AA8 U+0AAA..U+0AB0 U+0AB2..U+0AB3 U+0AB5..U+0AB9 U+0ABD U+0AE0 U+0B05..U+0B0C U+0B0F..U+0B10 U+0B13..U+0B28 U+0B2A..U+0B30 U+0B32..U+0B33 U+0B36..U+0B39 U+0B3D U+0B5C..U+0B5D U+0B5F..U+0B61 U+0B85..U+0B8A U+0B8E..U+0B90 U+0B92..U+0B95 U+0B99..U+0B9A U+0B9C U+0B9E..U+0B9F U+0BA3..U+0BA4 U+0BA8..U+0BAA U+0BAE..U+0BB5 U+0BB7..U+0BB9 U+0C05..U+0C0C U+0C0E..U+0C10 U+0C12..U+0C28 U+0C2A..U+0C33 U+0C35..U+0C39 U+0C60..U+0C61 U+0C85..U+0C8C U+0C8E..U+0C90 U+0C92..U+0CA8 U+0CAA..U+0CB3 U+0CB5..U+0CB9 U+0CDE U+0CE0..U+0CE1 U+0D05..U+0D0C U+0D0E..U+0D10 U+0D12..U+0D28 U+0D2A..U+0D39 U+0D60..U+0D61 U+0E01..U+0E2E U+0E30 U+0E32..U+0E33 U+0E40..U+0E45 U+0E81..U+0E82 U+0E84 U+0E87..U+0E88 U+0E8A U+0E8D U+0E94..U+0E97 U+0E99..U+0E9F U+0EA1..U+0EA3 U+0EA5 U+0EA7 U+0EAA..U+0EAB U+0EAD..U+0EAE U+0EB0 U+0EB2..U+0EB3 U+0EBD U+0EC0..U+0EC4 U+0F40..U+0F47 U+0F49..U+0F69 U+10A0..U+10C5 U+10D0..U+10F6 U+1100 U+1102..U+1103 U+1105..U+1107 U+1109 U+110B..U+110C U+110E..U+1112 U+113C U+113E U+1140 U+114C U+114E U+1150 U+1154..U+1155 U+1159 U+115F..U+1161 U+1163 U+1165 U+1167 U+1169 U+116D..U+116E U+1172..U+1173 U+1175 U+119E U+11A8 U+11AB U+11AE..U+11AF U+11B7..U+11B8 U+11BA U+11BC..U+11C2 U+11EB U+11F0 U+11F9 U+1E00..U+1E9B U+1EA0..U+1EF9 U+1F00..U+1F15 U+1F18..U+1F1D U+1F20..U+1F45 U+1F48..U+1F4D U+1F50..U+1F57 U+1F59 U+1F5B U+1F5D U+1F5F..U+1F7D U+1F80..U+1FB4 U+1FB6..U+1FBC U+1FBE U+1FC2..U+1FC4 U+1FC6..U+1FCC U+1FD0..U+1FD3 U+1FD6..U+1FDB U+1FE0..U+1FEC U+1FF2..U+1FF4 U+1FF6..U+1FFC U+2126 U+212A..U+212B U+212E U+2180..U+2182 U+3041..U+3094 U+30A1..U+30FA U+3105..U+312C U+AC00..U+D7A3 // Ideographic U+4E00..U+9FA5 U+3007 U+3021..U+3029 ]; $NameChar10 := [ '.' '-' '_' ':' // Letter // BaseChar U+0041..U+005A U+0061..U+007A U+00C0..U+00D6 U+00D8..U+00F6 U+00F8..U+00FF U+0100..U+0131 U+0134..U+013E U+0141..U+0148 U+014A..U+017E U+0180..U+01C3 U+01CD..U+01F0 U+01F4..U+01F5 U+01FA..U+0217 U+0250..U+02A8 U+02BB..U+02C1 U+0386 U+0388..U+038A U+038C U+038E..U+03A1 U+03A3..U+03CE U+03D0..U+03D6 U+03DA U+03DC U+03DE U+03E0 U+03E2..U+03F3 U+0401..U+040C U+040E..U+044F U+0451..U+045C U+045E..U+0481 U+0490..U+04C4 U+04C7..U+04C8 U+04CB..U+04CC U+04D0..U+04EB U+04EE..U+04F5 U+04F8..U+04F9 U+0531..U+0556 U+0559 U+0561..U+0586 U+05D0..U+05EA U+05F0..U+05F2 U+0621..U+063A U+0641..U+064A U+0671..U+06B7 U+06BA..U+06BE U+06C0..U+06CE U+06D0..U+06D3 U+06D5 U+06E5..U+06E6 U+0905..U+0939 U+093D U+0958..U+0961 U+0985..U+098C U+098F..U+0990 U+0993..U+09A8 U+09AA..U+09B0 U+09B2 U+09B6..U+09B9 U+09DC..U+09DD U+09DF..U+09E1 U+09F0..U+09F1 U+0A05..U+0A0A U+0A0F..U+0A10 U+0A13..U+0A28 U+0A2A..U+0A30 U+0A32..U+0A33 U+0A35..U+0A36 U+0A38..U+0A39 U+0A59..U+0A5C U+0A5E U+0A72..U+0A74 U+0A85..U+0A8B U+0A8D U+0A8F..U+0A91 U+0A93..U+0AA8 U+0AAA..U+0AB0 U+0AB2..U+0AB3 U+0AB5..U+0AB9 U+0ABD U+0AE0 U+0B05..U+0B0C U+0B0F..U+0B10 U+0B13..U+0B28 U+0B2A..U+0B30 U+0B32..U+0B33 U+0B36..U+0B39 U+0B3D U+0B5C..U+0B5D U+0B5F..U+0B61 U+0B85..U+0B8A U+0B8E..U+0B90 U+0B92..U+0B95 U+0B99..U+0B9A U+0B9C U+0B9E..U+0B9F U+0BA3..U+0BA4 U+0BA8..U+0BAA U+0BAE..U+0BB5 U+0BB7..U+0BB9 U+0C05..U+0C0C U+0C0E..U+0C10 U+0C12..U+0C28 U+0C2A..U+0C33 U+0C35..U+0C39 U+0C60..U+0C61 U+0C85..U+0C8C U+0C8E..U+0C90 U+0C92..U+0CA8 U+0CAA..U+0CB3 U+0CB5..U+0CB9 U+0CDE U+0CE0..U+0CE1 U+0D05..U+0D0C U+0D0E..U+0D10 U+0D12..U+0D28 U+0D2A..U+0D39 U+0D60..U+0D61 U+0E01..U+0E2E U+0E30 U+0E32..U+0E33 U+0E40..U+0E45 U+0E81..U+0E82 U+0E84 U+0E87..U+0E88 U+0E8A U+0E8D U+0E94..U+0E97 U+0E99..U+0E9F U+0EA1..U+0EA3 U+0EA5 U+0EA7 U+0EAA..U+0EAB U+0EAD..U+0EAE U+0EB0 U+0EB2..U+0EB3 U+0EBD U+0EC0..U+0EC4 U+0F40..U+0F47 U+0F49..U+0F69 U+10A0..U+10C5 U+10D0..U+10F6 U+1100 U+1102..U+1103 U+1105..U+1107 U+1109 U+110B..U+110C U+110E..U+1112 U+113C U+113E U+1140 U+114C U+114E U+1150 U+1154..U+1155 U+1159 U+115F..U+1161 U+1163 U+1165 U+1167 U+1169 U+116D..U+116E U+1172..U+1173 U+1175 U+119E U+11A8 U+11AB U+11AE..U+11AF U+11B7..U+11B8 U+11BA U+11BC..U+11C2 U+11EB U+11F0 U+11F9 U+1E00..U+1E9B U+1EA0..U+1EF9 U+1F00..U+1F15 U+1F18..U+1F1D U+1F20..U+1F45 U+1F48..U+1F4D U+1F50..U+1F57 U+1F59 U+1F5B U+1F5D U+1F5F..U+1F7D U+1F80..U+1FB4 U+1FB6..U+1FBC U+1FBE U+1FC2..U+1FC4 U+1FC6..U+1FCC U+1FD0..U+1FD3 U+1FD6..U+1FDB U+1FE0..U+1FEC U+1FF2..U+1FF4 U+1FF6..U+1FFC U+2126 U+212A..U+212B U+212E U+2180..U+2182 U+3041..U+3094 U+30A1..U+30FA U+3105..U+312C U+AC00..U+D7A3 // Ideographic U+4E00..U+9FA5 U+3007 U+3021..U+3029 // Digit U+0030..U+0039 U+0660..U+0669 U+06F0..U+06F9 U+0966..U+096F U+09E6..U+09EF U+0A66..U+0A6F U+0AE6..U+0AEF U+0B66..U+0B6F U+0BE7..U+0BEF U+0C66..U+0C6F U+0CE6..U+0CEF U+0D66..U+0D6F U+0E50..U+0E59 U+0ED0..U+0ED9 U+0F20..U+0F29 // CombiningChar U+0300..U+0345 U+0360..U+0361 U+0483..U+0486 U+0591..U+05A1 U+05A3..U+05B9 U+05BB..U+05BD U+05BF U+05C1..U+05C2 U+05C4 U+064B..U+0652 U+0670 U+06D6..U+06DC U+06DD..U+06DF U+06E0..U+06E4 U+06E7..U+06E8 U+06EA..U+06ED U+0901..U+0903 U+093C U+093E..U+094C U+094D U+0951..U+0954 U+0962..U+0963 U+0981..U+0983 U+09BC U+09BE U+09BF U+09C0..U+09C4 U+09C7..U+09C8 U+09CB..U+09CD U+09D7 U+09E2..U+09E3 U+0A02 U+0A3C U+0A3E U+0A3F U+0A40..U+0A42 U+0A47..U+0A48 U+0A4B..U+0A4D U+0A70..U+0A71 U+0A81..U+0A83 U+0ABC U+0ABE..U+0AC5 U+0AC7..U+0AC9 U+0ACB..U+0ACD U+0B01..U+0B03 U+0B3C U+0B3E..U+0B43 U+0B47..U+0B48 U+0B4B..U+0B4D U+0B56..U+0B57 U+0B82..U+0B83 U+0BBE..U+0BC2 U+0BC6..U+0BC8 U+0BCA..U+0BCD U+0BD7 U+0C01..U+0C03 U+0C3E..U+0C44 U+0C46..U+0C48 U+0C4A..U+0C4D U+0C55..U+0C56 U+0C82..U+0C83 U+0CBE..U+0CC4 U+0CC6..U+0CC8 U+0CCA..U+0CCD U+0CD5..U+0CD6 U+0D02..U+0D03 U+0D3E..U+0D43 U+0D46..U+0D48 U+0D4A..U+0D4D U+0D57 U+0E31 U+0E34..U+0E3A U+0E47..U+0E4E U+0EB1 U+0EB4..U+0EB9 U+0EBB..U+0EBC U+0EC8..U+0ECD U+0F18..U+0F19 U+0F35 U+0F37 U+0F39 U+0F3E U+0F3F U+0F71..U+0F84 U+0F86..U+0F8B U+0F90..U+0F95 U+0F97 U+0F99..U+0FAD U+0FB1..U+0FB7 U+0FB9 U+20D0..U+20DC U+20E1 U+302A..U+302F U+3099 U+309A // Extender U+00B7 U+02D0 U+02D1 U+0387 U+0640 U+0E46 U+0EC6 U+3005 U+3031..U+3035 U+309D..U+309E U+30FC..U+30FE ]; $NameStartChar11 := [ ':' '_' 'A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' 'X' 'Y' 'Z' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' U+00C0..U+00D6 U+00D8..U+00F6 U+00F8..U+02FF U+0370..U+037D U+037F..U+1FFF U+200C..U+200D U+2070..U+218F U+2C00..U+2FEF U+3001..U+D7FF U+F900..U+FDCF U+FDF0..U+FFFD U+10000..U+EFFFF ]; $NameChar11 := [ '-' '.' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' U+00B7 U+0300..U+036F U+203F..U+2040 // NameStartChar ':' '_' 'A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' 'X' 'Y' 'Z' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' U+00C0..U+00D6 U+00D8..U+00F6 U+00F8..U+02FF U+0370..U+037D U+037F..U+1FFF U+200C..U+200D U+2070..U+218F U+2C00..U+2FEF U+3001..U+D7FF U+F900..U+FDCF U+FDF0..U+FFFD U+10000..U+EFFFF ]; } // NameChar lexmode Name : extends => 'NameChar' { Name : value := $NameStartChar11 $NameChar11*; } // Name lexmode Nmtoken : extends => 'NameChar' { Nmtoken : value := $NameChar11*; } // Nmtoken /* Space */ lexmode S { S := [U+0009 U+000A U+000D U+0020]+; } // S /* Document end scanning mode */ lexmode DocumentEnd : standalone : extends => 'S' { /* Processing instruction */ PIO := ['<'] ['?']; /* Comment declaration */ CDO := ['<'] ['!'] ['-'] ['-']; } // DocumentEnd /* Document misc scanning mode This mode scans |Misc| constructions as well as document element's start tag. */ lexmode DocumentMisc : standalone : extends => 'DocumentEnd' { /* Document element start tag */ STAGO := ['<']; } // DocumentMisc /* Document prolog scanning mode */ lexmode DocumentProlog : standalone : extends => 'DocumentMisc' { /* |DOCTYPE| declaration */ MDO := ['<'] ['!']; } // DocumentProlog /* Document start scanning mode */ lexmode DocumentStart : initial : standalone : extends => 'DocumentProlog' { /* XML declaration */ XDO := ['<'] ['?'] ['x'] ['m'] ['l']; } // DocumentStart /* Comment declaration scanning mode */ lexmode CommentDeclaration : standalone { /* Comment close */ COM := ['-'] ['-']; /* Comment data */ $string := ['-']? [^'-']; STRING : value := $string+; } // CommentDeclaration /* Processing instruction name and |S| scanning mode */ lexmode PIName : standalone : extends => 'Name' : extends => 'S' { /* Processing instruction close */ PIC := ['?'] ['>']; } // PIName /* Processing instruction data scanning mode */ lexmode PIData : standalone { /* Processing instruction close */ PIC := ['?'] ['>']; /* Processing instruction target data */ ?default-token DATA : value; } // PIData /* Content of element scanning mode */ lexmode ElementContent : standalone { /* Start tag open */ STAGO := ['<']; /* End tag open */ ETAGO := ['<'] ['/']; /* Hexadecimal character reference open */ HCRO := ['&'] ['#'] ['x']; /* Numeric character reference open */ CRO := ['&'] ['#']; /* General entity reference open */ ERO := ['&']; /* Comment declaration open */ CDO := ['<'] ['!'] ['-'] ['-']; /* CDATA section open */ CDSO := ['<'] ['!'] ['['] ['C'] ['D'] ['A'] ['T'] ['A'] ['[']; /* Processing instruction open */ PIO := ['<'] ['?']; /* Markup section end */ MSE := [']'] [']'] ['>']; /* Character data */ /* Character data and/or |MSE| */ ?default-token CharData : value; } // ElementContent /* CDATA section content scanning mode */ lexmode CDATASectionContent : standalone { /* Markup section end */ MSE := [']'] [']'] ['>']; /* Character data */ ?default-token CData : value; } // CDATASectionContent lexmode EntityReference : standalone : extends => 'Name' { /* Reference close */ REFC := [';']; } // EntityReference lexmode NumericCharacterReference : standalone { /* Decimal number */ $digit := ['0' '1' '2' '3' '4' '5' '6' '7' '8' '9']; NUMBER : value := $digit+; /* Reference close */ REFC := [';']; } // NumericCharacterReference lexmode HexadecimalCharacterReference : standalone { /* Hexadecimal number */ $hexdigit := ['0' '1' '2' '3' '4' '5' '6' '7' '8' '9' 'A' 'B' 'C' 'D' 'E' 'F' 'a' 'b' 'c' 'd' 'e' 'f']; Hex : value := $hexdigit+; /* Reference close */ REFC := [';']; } // HexadecimalCharacterReference lexmode XMLDeclaration : standalone : extends => 'Name' : extends => 'S' { /* Value indicator */ VI := ['=']; /* Literal open */ LIT := ['"']; LITA := [U+0027]; /* Processing instruction close */ PIC := ['?'] ['>']; } // XMLDeclaration lexmode StartTag : standalone : extends => 'Name' : extends => 'S' { /* Value indicator */ VI := ['=']; /* Literal open */ LIT := ['"']; LITA := [U+0027]; /* Tag close */ TAGC := ['>']; /* Null end-tag enabled start-tag close */ NESTC := ['/']; } // StartTag lexmode EndTag : standalone : extends => 'Name' : extends => 'S' { /* Tag close */ TAGC := ['>']; } // EndTag lexmode AttributeValueLiteral_ { ERO := ['&']; CRO := ['&'] ['#']; HCRO := ['&'] ['#'] ['x']; } // AttributeValueLiteral_ lexmode AttributeValueLiteral : standalone : extends => 'AttributeValueLiteral_' { LIT := ['"']; STRING : value := [^'"' '&' '<']+; } // AttributeValueLiteral lexmode AttributeValueLiteralA : standalone : extends => 'AttributeValueLiteral_' { LITA := [U+0027]; STRING : value := [^U+0027 '&' '<']+; } // AttributeValueLiteralA lexmode AttributeValueLiteralE : standalone : extends => 'AttributeValueLiteral_' { STRING : value := [^'&' '<']+; } // AttributeValueLiteralE lexmode EntityValue_ { PERO := ['%']; ERO := ['&']; CRO := ['&'] ['#']; HCRO := ['&'] ['#'] ['x']; } // EntityValue_ lexmode EntityValue : standalone : extends => 'EntityValue_' { LIT := ['"']; STRING : value := [^'"' '&' '%']+; } // EntityValue lexmode EntityValueA : standalone : extends => 'EntityValue_' { LITA := [U+0027]; STRING : value := [^U+0027 '&' '%']+; } // EntityValueA lexmode SystemLiteral : standalone { LIT := ['"']; ?default-token STRING : value; } // SystemLiteral lexmode SystemLiteralA : standalone { LITA := [U+0027]; ?default-token STRING : value; } // SystemLiteralA lexmode DTD : standalone : extends => 'S' { /* Markup declaration open */ MDO := ['<'] ['!']; /* Comment declaration open */ CDO := ['<'] ['!'] ['-'] ['-']; /* Processing instruction open */ PIO := ['<'] ['?']; /* Parameter entity reference open */ PERO := ['%']; /* Declaration subset close */ DSC := [']']; /* Contition section open */ CSO := ['<'] ['!'] ['[']; } // DTD /* Markup declaration scanning mode This mode is used to recognize |MDC| that terminates a comment declaration as well as the base |lexmode| for e.g. document type declaration scanning mode. */ lexmode MarkupDeclaration : standalone : extends => 'Name' : extends => 'S' { /* Markup declaration close */ MDC := ['>']; /* Literal open */ LIT := ['"']; /* Alternative literal open */ LITA := [U+0027]; /* Parameter entity reference open */ PERO := ['%']; /* Declaration subset open */ DSO := ['[']; } // MarkupDeclaration lexmode ElementDeclaration : standalone : extends => 'MarkupDeclaration' { /* Model group open */ MGO := ['(']; /* Model group close */ MGC := [')']; /* Reserved name indicator */ RNI := ['#']; /* Occurence indicators */ OPT := ['?']; REP := ['*']; PLUS := ['+']; /* Connectors */ OR := ['|']; SEQ := [',']; } // ElementDeclaration lexmode AttlistDeclaration : standalone : extends => 'MarkupDeclaration' { /* Enumeration group open */ EGO := ['(']; /* Enumeration group close */ EGC := [')']; /* Enumeration choice delimiter */ OR := ['|']; /* Reserved name indicator */ RNI := ['#']; } // AttlistDeclaration lexmode Enumeration : standalone : extends => 'Nmtoken' : extends => 'S' { /* Enumeration group close */ EGC := [')']; /* Enumeration choice delimiter */ OR := ['|']; } // Enumeration token-error default : default { lang:Perl { my $location; __CODE{xp|get-location-from-token:: $token => {$token}, $result => {$location}, }__; my $continue = __DOMCore:ERROR{xp|wf-syntax-error:: xp|error-token => {$token}, DOMCore|location => {$location}, }__; unless ($continue) { __EXCEPTION{DOMLS|PARSE_ERR:: }__; } $self->{has_error} = true; } } // default @XMLTests: @@XMLTest: @@@QName: xp.syntax.empty.test @@@DEnt: @@@@test:value: \ @@@c:erred: <[[xp:wf-syntax-error]]> { (1, 1); } @@XMLTest: @@@QName: xp.syntax.space.test @@@DEnt: @@@@test:value: \ @@@c:erred: <[[xp:wf-syntax-error]]> { (1, 4); } @@XMLTest: @@@QName: xp.syntax.newlines.test @@@DEnt: @@@@test:value: \ \ \ @@@c:erred: <[[xp:wf-syntax-error]]> { (3, 1); } @@XMLTest: @@@QName: xp.only.docel.test @@@DEnt: @@@@test:value:

@@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; element { namespace-uri: null; prefix: null; local-name: 'p'; text-content: ''; } } @@XMLTest: @@@QName: xp.only.docel.emptyelemtag.test @@@DEnt: @@@@test:value:

@@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; element { namespace-uri: null; prefix: null; local-name: 'p'; text-content: ''; } } @@XMLTest: @@@QName: xp.doctype.empty.test @@@DEnt: @@@@test:value: @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; } element { namespace-uri: null; prefix: null; local-name: 'a'; text-content: ''; } } @@XMLTest: @@@QName: xp.doctype.intsubset.empty.test @@@DEnt: @@@@test:value: @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; } element { namespace-uri: null; prefix: null; local-name: 'a'; text-content: ''; } } @@XMLTest: @@@QName: xp.doctype.intsubset.pi.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; pi { target: 'pi'; data: 'data '; } } element { namespace-uri: null; prefix: null; local-name: 'a'; text-content: ''; } } @@@enImplNote: A DOM PI node in doctype node is a manakai extension. @@XMLTest: @@@QName: xp.doctype.intsubset.entity.general.internal.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; general-entity { node-name: 'entity'; text-content: 'entity value'; has-replacement-tree: true; } } element { namespace-uri: null; prefix: null; local-name: 'a'; text-content: ''; } } @@XMLTest: @@@QName: xp.doctype.intsubset.entity.parameter.internal.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; } element { namespace-uri: null; prefix: null; local-name: 'a'; text-content: ''; } } @@XMLTest: @@@QName: xp.doctype.internal.entity.root.element.text.only.test @@@DEnt: @@@@test:value: ]> &entity; @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; general-entity { node-name: 'entity'; text-content: 'entity value'; has-replacement-tree: true; } } element { namespace-uri: null; prefix: null; local-name: 'a'; general-entity-reference { node-name: 'entity'; text { data: 'entity value'; } } } } @@XMLTest: @@@QName: xp.doctype.internal.entity.root.element.text.mult.test @@@DEnt: @@@@test:value: ]> &entity; and &entity; @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; general-entity { node-name: 'entity'; text-content: 'entity value'; has-replacement-tree: true; } } element { namespace-uri: null; prefix: null; local-name: 'a'; general-entity-reference { node-name: 'entity'; text { data: 'entity value'; } } text { data: ' and '; } general-entity-reference { node-name: 'entity'; text { data: 'entity value'; } } } } @@XMLTest: @@@QName: xp.doctype.internal.entity.root.element.text.element.test @@@DEnt: @@@@test:value: value

with element "> ]> &entity; @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; general-entity { node-name: 'entity'; has-replacement-tree: true; text { data: 'entity '; } element { node-name: 'p'; text-content: 'value'; } text { data: ' with '; } element { node-name: 'e'; text-content: 'element'; } } } element { namespace-uri: null; prefix: null; local-name: 'a'; general-entity-reference { node-name: 'entity'; text { data: 'entity '; } element { namespace-uri: null; prefix: null; local-name: 'p'; text { data: 'value'; } } text { data: ' with '; } element { namespace-uri: null; prefix: null; local-name: 'e'; text { data: 'element'; } } text { data: ' '; } } } } @@XMLTest: @@@QName: xp.doctype.internal.entity.root.element.text.in.ent.test @@@DEnt: @@@@test:value: ]> &entity2; @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; general-entity { node-name: 'entity1'; text-content: 'entity value'; } general-entity { node-name: 'entity2'; text { data: 'e'; } general-entity-reference { node-name: 'entity1'; text-content: 'entity value'; is-expanded: true; } text { data: 'n'; } } } element { namespace-uri: null; prefix: null; local-name: 'a'; general-entity-reference { node-name: 'entity2'; text { data: 'e'; } general-entity-reference { node-name: 'entity1'; text { data: 'entity value'; } } text { data: 'n'; } } } } @@XMLTest: @@@QName: xp.doctype.entity.value.charref.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { document-type { general-entity { node-name: 'entity1'; text-content: 'entity !value#'; has-replacement-tree: true; } general-entity { node-name: 'entity2'; text-content: '!value#'; has-replacement-tree: true; } } element { } } @@XMLTest: @@@QName: xp.predefined.in.content.test @@@DEnt: @@@@test:value: _<_>_"_'_&_ @@@test:domTree: document { element { text-content: '_<_>_"_' U+0027 '_&_'; } } @@XMLTest: @@@QName: xp.predefined.in.attr.test @@@DEnt: @@@@test:value: @@@test:domTree: document { element { attribute { node-name: 'at'; text-content: '_<_>_"_' U+0027 '_&_'; } } } @@XMLTest: @@@QName: xp.predefined.in.content.in.entity.test @@@DEnt: @@@@test:value: ]> &ent; @@@test:domTree: document { document-type { general-entity { node-name: 'ent'; text-content: '_<_>_"_' U+0027 '_&_'; } } element { text-content: '_<_>_"_' U+0027 '_&_'; } } @@XMLTest: @@@QName: xp.predefined.decl.ignore.test @@@DEnt: @@@@test:value: ]> _<_>_"_'_&_&other;_ @@@test:domTree: document { document-type { general-entity { node-name: 'other'; text-content: 'other'; } } element { text-content: '_<_>_"_' U+0027 '_&_other_'; } } @@XMLTest: @@@QName: xp.doctype.internal.attr.empty.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; element-type-definition { node-name: 'a'; } } element { namespace-uri: null; local-name: 'a'; } } @@XMLTest: @@@QName: xp.doctype.internal.attr.cdata.implied.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; element-type-definition { node-name: 'a'; attribute-definition { node-name: 'at'; declared-type: const (CDATA_ATTR); allowed-tokens: DOMStringList (); default-type: const (IMPLIED_DEFAULT); text-content: ''; } } } element { namespace-uri: null; local-name: 'a'; } } @@XMLTest: @@@QName: xp.doctype.internal.attr.types.implied.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; element-type-definition { node-name: 'a'; attribute-definition { node-name: 'at1'; declared-type: const (ID_ATTR); allowed-tokens: DOMStringList (); default-type: const (IMPLIED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at2'; declared-type: const (IDREF_ATTR); allowed-tokens: DOMStringList (); default-type: const (IMPLIED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at3'; declared-type: const (IDREFS_ATTR); allowed-tokens: DOMStringList (); default-type: const (IMPLIED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at4'; declared-type: const (ENTITY_ATTR); allowed-tokens: DOMStringList (); default-type: const (IMPLIED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at5'; declared-type: const (ENTITIES_ATTR); allowed-tokens: DOMStringList (); default-type: const (IMPLIED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at6'; declared-type: const (NMTOKEN_ATTR); allowed-tokens: DOMStringList (); default-type: const (IMPLIED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at7'; declared-type: const (NMTOKENS_ATTR); allowed-tokens: DOMStringList (); default-type: const (IMPLIED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at8'; declared-type: const (NOTATION_ATTR); allowed-tokens: DOMStringList ('n1', 'n2', 'n3'); default-type: const (IMPLIED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at9'; declared-type: const (ENUMERATION_ATTR); allowed-tokens: DOMStringList ('e1', 'e2', 'e3'); default-type: const (IMPLIED_DEFAULT); text-content: ''; } } } element { namespace-uri: null; local-name: 'a'; } } @@XMLTest: @@@QName: xp.doctype.internal.attr.cdata.defaults.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; element-type-definition { node-name: 'a'; attribute-definition { node-name: 'at1'; declared-type: const (CDATA_ATTR); allowed-tokens: DOMStringList (); default-type: const (IMPLIED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at2'; declared-type: const (CDATA_ATTR); allowed-tokens: DOMStringList (); default-type: const (REQUIRED_DEFAULT); text-content: ''; } attribute-definition { node-name: 'at3'; declared-type: const (CDATA_ATTR); allowed-tokens: DOMStringList (); default-type: const (FIXED_DEFAULT); text-content: 'value3'; } attribute-definition { node-name: 'at4'; declared-type: const (CDATA_ATTR); allowed-tokens: DOMStringList (); default-type: const (EXPLICIT_DEFAULT); text-content: 'value4'; } attribute-definition { node-name: 'at5'; declared-type: const (CDATA_ATTR); allowed-tokens: DOMStringList (); default-type: const (FIXED_DEFAULT); text-content: 'value5'; } attribute-definition { node-name: 'at6'; declared-type: const (CDATA_ATTR); allowed-tokens: DOMStringList (); default-type: const (EXPLICIT_DEFAULT); text-content: 'value6'; } } } element { namespace-uri: null; local-name: 'a'; attribute { node-name: 'at3'; text-content: 'value3'; specified: false; } attribute { node-name: 'at4'; text-content: 'value4'; specified: false; } attribute { node-name: 'at5'; text-content: 'value5'; specified: false; } attribute { node-name: 'at6'; text-content: 'value6'; specified: false; } } } @@XMLTest: @@@QName: xp.doctype.internal.attr.cdata.default.normalize.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; element-type-definition { node-name: 'a'; attribute-definition { node-name: 'at'; declared-type: const (CDATA_ATTR); allowed-tokens: DOMStringList (); default-type: const (EXPLICIT_DEFAULT); text-content: ' default ' U+000A 'value '; } } } element { namespace-uri: null; local-name: 'a'; attribute { node-name: 'at'; text-content: ' default ' U+000A 'value '; specified: false; } } } @@XMLTest: @@@QName: xp.doctype.internal.attr.nmtoken.default.normalize.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { node-name: 'a'; element-type-definition { node-name: 'a'; attribute-definition { node-name: 'at'; declared-type: const (NMTOKEN_ATTR); allowed-tokens: DOMStringList (); default-type: const (EXPLICIT_DEFAULT); text-content: ' default ' U+000A 'value '; } } } element { namespace-uri: null; local-name: 'a'; attribute { node-name: 'at'; text-content: ' default ' U+000A 'value '; specified: false; } } } @@XMLTest: @@@QName: xp.doctype.attrtype.no-value.test @@@DEnt: @@@@test:value: @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { } element { namespace-uri: null; local-name: 'a'; attribute { namespace-uri: null; local-name: 'at'; value: ' at value '; text { data: ' at value '; } schema-type-info: TypeInfo (null, null); specified: true; } } } @@XMLTest: @@@QName: xp.doctype.attrtype.cdata.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { } element { namespace-uri: null; local-name: 'a'; attribute { namespace-uri: null; local-name: 'at'; value: ' at value '; text { data: ' at value '; } schema-type-info: TypeInfo ('http://www.w3.org/TR/REC-xml', 'CDATA'); specified: true; } } } @@XMLTest: @@@QName: xp.doctype.attrtype.nmtoken.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { xml-version: '1.0'; xml-encoding: null; xml-standalone: false; document-type { } element { namespace-uri: null; local-name: 'a'; attribute { namespace-uri: null; local-name: 'at'; value: 'at value'; text { data: ' at value '; } schema-type-info: TypeInfo ('http://www.w3.org/TR/REC-xml', 'NMTOKEN'); specified: true; } } } @@XMLTest: @@@QName: xp.doctype.attr.normalization.1.test @@@DEnt: @@@@test:value: @@@test:domTree: document { element { attribute { node-name: 'at'; value: ' at ' U+000A 'value '; schema-type-info: TypeInfo (null, null); specified: true; } } } @@XMLTest: @@@QName: xp.doctype.attr.normalization.2.test @@@DEnt: @@@@test:value: @@@test:domTree: document { element { attribute { value: ' at ' U+000D 'value '; schema-type-info: TypeInfo (null, null); specified: true; } } } @@XMLTest: @@@QName: xp.doctype.attr.normalization.3.test @@@DEnt: @@@@test:value: @@@test:domTree: document { element { attribute { node-name: 'at'; value: ' at ' U+0009 'value '; schema-type-info: TypeInfo (null, null); specified: true; } } } @@XMLTest: @@@QName: xp.doctype.attr.specified.1.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { document-type { } element { attribute { node-name: 'at'; value: 'default'; specified: false; } } } @@XMLTest: @@@QName: xp.doctype.attr.specified.2.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { document-type { } element { attribute { node-name: 'at'; value: 'default'; specified: false; } attribute { node-name: 'at2'; value: 'specified'; specified: true; } } } @@XMLTest: @@@QName: xp.doctype.attr.specified.3.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { document-type { } element { attribute { node-name: 'at'; value: 'specified'; specified: true; } } } @@XMLTest: @@@QName: xp.attr.literal.charref.test @@@DEnt: @@@@test:value: @@@test:domTree: document { element { attribute { node-name: 'at1'; text-content: 'value!_%value'; } attribute { node-name: 'at2'; text-content: 'value%_!value'; } } } @@XMLTest: @@@QName: xp.attr.literal.entref.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { document-type { general-entity { node-name: 'ent'; text-content: 'entity!_)value'; } } element { attribute { node-name: 'at1'; text-content: 'valueentity!_)valuevalue'; } attribute { node-name: 'at2'; text-content: 'valueentity!_)valuevalue'; } } } @@XMLTest: @@@QName: xp.attr.literal.entref.nest.test @@@DEnt: @@@@test:value: ]> @@@test:domTree: document { document-type { general-entity { node-name: 'ent1'; text-content: 'entity!_)value'; } general-entity { node-name: 'ent2'; text-content: '@entity!_)value@'; } } element { attribute { node-name: 'at1'; text-content: 'value@entity!_)value@value'; } attribute { node-name: 'at2'; text-content: 'value@entity!_)value@value'; } } } @@PerlDef: my $impl = $Message::DOM::ImplementationRegistry->get_implementation ({ 'Core' => '3.0', 'XML' => '3.0', 'XMLVersion' => ['1.0', '1.1'], }); my $parser = ->new ($impl); for my $test_data (@$TestData) { $test->start_new_test ($test_data->{uri}); my $doc_ent = $test_data->{entity}->{$test_data->{root_uri}}; $parser->dom_config->set_parameter ('error-handler' => sub ($$) { my (undef, $err) = @_; my $err_type = $err->type; if ($test_data->{dom_error}->{$err_type}) { $test->assert_error_equals (actual_value => $err, expected_hash => pop @{$test_data->{dom_error} ->{$err_type}}); } else { # Uncatched error warn $err; } return true; # continue as far as possible }); if ($test_data->{dom_tree}) { # Successful test try { my $doc = $parser->parse_string ($doc_ent->{}); $test->assert_dom_tree_equals (actual_value => $doc, expected_hash => $test_data->{dom_tree}); my $has_error; for (values %{$test_data->{dom_error}||{}}) { if (@$_) { $test->failure_comment (@$_.' |DOMError|s of type |'. $_->[0]->{type}.'| are not reported'); $has_error = true; } } $has_error ? $test->not_ok : $test->ok; } catch Message::Util::IF::DTException with { # } catch Message::DOM::IF::LSException with { $test->assert_never; }; } else { try { my $doc = $parser->parse_string ($doc_ent->{}); $test->assert_never; } catch Message::Util::IF::DTException with { # } catch Message::DOM::IF::LSException with { # }; my $has_error; for (values %{$test_data->{dom_error}||{}}) { if (@$_) { $test->failure_comment (@$_.' |DOMError|s of type |'. $_->[0]->{type}.'| are not reported'); $has_error = true; } } $has_error ? $test->not_ok : $test->ok; } } @ResourceDef: @@QName: getCopyOfEntityState @@rdf:type: DISPerl|InlineCode @@ForCheck: ManakaiDOM|ForClass @@PerlDef: {%{$self->{$entity_type}->{$entity_name}}, line => 1, column => 1, pos => 0} ##ManakaiXMLParser ElementTypeBinding: @Name: XMLTests @ElementType: dis:ResourceDef @ShadowContent: @@ForCheck: ManakaiDOM|ForClass @@rdf:type: test|ParserTestSet ElementTypeBinding: @Name: XMLTest @ElementType: dis:ResourceDef @ShadowContent: @@ForCheck: ManakaiDOM|ForClass @@rdf:type: test|ParserTest ElementTypeBinding: @Name: DEnt @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: test|RootEntity ElementTypeBinding: @Name: Ent @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: test|Entity ResourceDef: @QName: xp|get-location-from-token @rdf:type: DISPerl|BlockCode @enDesc: Creates a object from a token. @PerlDef: $result = { utf32_offset => $self->{entity}->[-1]->{pos}, }; @For: ManakaiDOM|ManakaiDOM3 ElementTypeBinding: @Name: RuleDef @ElementType: dis:ResourceDef @ShadowContent: @@ForCheck: ManakaiDOM|ForClass @@rdf:type: Muf2003|RuleDefClass ElementTypeBinding: @Name: RuleParam @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: Muf2003|RuleParameter ElementTypeBinding: @Name: enImplNote @ElementType: dis:ImplNote @ShadowContent: @@lang:en ElementTypeBinding: @Name: ErrDef @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: DOMCore|DOMErrorType @@For: ManakaiDOM|DOM3 @@ecore:textFormatter: ManakaiXMLParserExceptionFormatter ElementTypeBinding: @Name: WFErrDef @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: DOMCore|DOMErrorType @@For: ManakaiDOM|DOM3 @@ecore:textFormatter: ManakaiXMLParserExceptionFormatter WFErrDef: @QName: xp|wf-syntax-error @enDesc: The entity does not match to the production rule; it is not well-formed. @DOMCore:severity: DOMCore|SEVERITY_FATAL_ERROR @enMufDef: |%xp-error-token-type;|%xp-error-token-value (prefix => { (|}, suffix => {|)}); is not allowed%xp-error-lines (prefix => { (|}, suffix => {|)}); @ecore:hasParameter: @@@: xp|error-token @@enDesc: The token that is not allowed. WFErrDef: @QName: xp|wf-pi-target-is-xml @enDesc: A processing instruction has its of (in any case) which is not allowed. @DOMCore:severity: DOMCore|SEVERITY_ERROR @enMufDef: Processing instruction target name cannot be |%p (name => {});| @ecore:hasParameter: @@@: xp|error-token @@enDesc: The token that contains the name. @ecore:hasParameter: @@@: xp|name @@enDesc: A string that is specified as target name of the processing instruction. @ecore:hasParameter: xp|parent WFErrDef: @QName: xp|wf-no-end-tag @DOMCore:severity: DOMCore|SEVERITY_ERROR @enDesc: An end-tag is not found. @enMufDef: End-tag | {});>| is required @ecore:hasParameter: xp|error-token @ecore:hasParameter: @@@: xp|node @@enDesc: The element node that is not closed. @ecore:hasParameter: @@@: xp|expected-element-type @@enDesc: The element type name of the element that is not closed. WFErrDef: @QName: xp|wf-unsupported-xml-version @DOMCore:severity: DOMCore|SEVERITY_ERROR @enDesc: The XML version specified in the version declaration is not supported. @enMufDef: XML version |%p (name => {});| is not supported @ecore:hasParameter: xp|bad-token @ecore:hasParameter: @@@: xp|parent @@enDesc: The document node. @ecore:hasParameter: @@@: infoset|version @@enDesc: The specified XML version. WFErrDef: @QName: xp|wf-malformed-enc-name @DOMCore:severity: DOMCore|SEVERITY_ERROR @enDesc: An pseudo-attribute value does not match to the procduction rule . @enMufDef: Encoding name |%p (name => {});| is not allowed @ecore:hasParameter: xp|error-token @ecore:hasParameter: @@@: xp|parent @@enDesc: The document node. @ecore:hasParameter: @@@: xp|name @@enDesc: The value. WFErrDef: @QName: xp|wf-malformed-xml-standalone @DOMCore:severity: DOMCore|SEVERITY_ERROR @enDesc: An pseudo-attribute value is neither or . @enMufDef: |standalone| pseudo-attribute value |%p (name => {});| is not allowed @ecore:hasParameter: xp|error-token @ecore:hasParameter: @@@: xp|parent @@enDesc: The document node. @ecore:hasParameter: @@@: xp|name @@enDesc: The value. WFErrDef: @QName: xp|wf-legal-literal-character @DOMCore:severity: DOMCore|SEVERITY_ERROR @enDesc: Each character in XML entity must match to the production rule . @enMufDef: Character %character-code-point (v => {}); is not allowed @ecore:hasParameter: @@@: xp|character-number @@enDesc: The code position of the character being referred. WFErrDef: @QName: xp|wf-element-type-match @DOMCore:severity: DOMCore|SEVERITY_FATAL_ERROR @enDesc: The in an element's end-tag must match the element type in the start-tag. @enMufDef: End-tag | {});>| does not match to start-tag |<%p (name => {});>| @ecore:hasParameter: xp|error-token @ecore:hasParameter: @@@: xp|node @@enDesc: The current opening element node. @ecore:hasParameter: @@@: xp|expected-element-type @@enDesc: The element type name of the current element. @ecore:hasParameter: @@@: xp|actual-element-type @@enDesc: The occurs in the end-tag. WFErrDef: @QName: xp|wf-unique-att-spec @DOMCore:severity: DOMCore|SEVERITY_ERROR @enDesc: An attribute name appear more than once in the same start-tag or empty-element tag. @enMufDef: Attribute |%p (name => {});| is specified more than once in the same tag @ecore:hasParameter: xp|error-token @ecore:hasParameter: @@@: xp|name @@enDesc: The name of the attribute. WFErrDef: @QName: xp|wf-legal-character @DOMCore:severity: DOMCore|SEVERITY_ERROR @enDesc: Characters referred to using character references match the production for . @enMufDef: Reference to character %character-code-point (v => {}); is not allowed @ecore:hasParameter: xp|error-token @ecore:hasParameter: @@@: xp|character-number @@enDesc: The code position of the character being referred. @ecore:hasParameter: @@@: xp|parent @@enDesc: The parent node in which the character reference has occurred, if available. XWParam: @QName: xp|error-token @enDesc: The token where the parser found an error. XWParam: @QName: xp|name @enDesc: A name. XWParam: @QName: xp|parent @enDesc: The parent node in which the error occurs. XWParam: @QName: xp|node @enDesc: The current node. XWParam: @QName: xp|actual-element-type @enDesc: The actual element type name occured in the source. XWParam: @QName: xp|expected-element-type @enDesc: The element type name expected. XWParam: @QName: xp|character-number @enDesc: The character code position. ElementTypeBinding: @Name: XWParam @ElementType: dis:ResourceDef @ShadowContent: @@For: =ManakaiDOM|all @@rdf:type: ecore|Parameter ElementTypeBinding: @Name:enMufDef @ElementType: ecore:defaultMessage @ShadowContent: @@lang:en @@ContentType: lang:muf ResourceDef: @QName: DOMImpl @AliasFor: DOMCore|DOMImplementation @For: ManakaiDOM|DOM ElementTypeBinding: @Name: Attr @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: DISLang|Attribute @@ForCheck: !=ManakaiDOM|ManakaiDOM ElementTypeBinding: @Name: Get @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: DISLang|AttributeGet ElementTypeBinding: @Name: Set @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: DISLang|AttributeSet ElementTypeBinding: @Name: enDesc @ElementType: dis:Description @ShadowContent: @@lang:en ElementTypeBinding: @Name: Method @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: DISLang|Method @@For: !=ManakaiDOM|ManakaiDOM ElementTypeBinding: @Name: Return @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: DISLang|MethodReturn ElementTypeBinding: @Name: Param @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: DISLang|MethodParameter ElementTypeBinding: @Name: PerlDef @ElementType: dis:Def @ShadowContent: @@ContentType: lang|Perl ElementTypeBinding: @Name: PropDef @ElementType: dis:ResourceDef @ShadowContent: @@rdf:type: rdf|Property ClsDef: @ClsQName: ManakaiXMLParserExceptionFormatter @ClsISA: ecore|MUErrorFormatter||ManakaiDOM|Perl @RuleDef: @@Name: xp-error-token-type @@enDesc: The type of the token the parser is encountered. @@Method: @@@Name: after @@@Param: @@@@Name: name @@@@Type: DOMString @@@@enDesc: The name of the method. @@@Param: @@@@Name: p @@@@Type: DISPerl|HASH @@@@enDesc: The set of the parameters to the method. @@@Param: @@@@Name: o @@@@Type: DISPerl|HASH @@@@enDesc: The option value. @@@Return: @@@@PerlDef: $p->{-result} = $o->{}->{type} if defined $o->{}->{type}; @RuleDef: @@Name: xp-error-token-value @@enDesc: The value of the token the parser is encountered, if any. @@Method: @@@Name: after @@@Param: @@@@Name: name @@@@Type: DOMString @@@@enDesc: The name of the method. @@@Param: @@@@Name: p @@@@Type: DISPerl|HASH @@@@enDesc: The set of the parameters to the method. @@@Param: @@@@Name: o @@@@Type: DISPerl|HASH @@@@enDesc: The option value. @@@Return: @@@@PerlDef: $p->{-result} = $o->{}->{value} if defined $o->{}->{value}; @RuleDef: @@Name: xp-error-lines @@enDesc: A copy of fragment of the source text that contains the line where the error occurred, if available. @@Method: @@@Name: after @@@Param: @@@@Name: name @@@@Type: DOMString @@@@enDesc: The name of the method. @@@Param: @@@@Name: p @@@@Type: DISPerl|HASH @@@@enDesc: The set of the parameters to the method. @@@Param: @@@@Name: o @@@@Type: DISPerl|HASH @@@@enDesc: The option value. @@@Return: @@@@PerlDef: my $pos = $o-> ->; if ($pos > -1) { my $src = $o->{}->{entity}->[-1]->{reptxt}; my $start = $pos; $start = rindex ($$src, "\x0A", $start - 1) for 0..2; $start++; my $end = $pos; $end = index ($$src, "\x0A", $end + 1) for 0..2; $end = length $$src if $end < 0; $p->{-result} = substr $$src, $start, $end - $start; } @RuleDef: @@Name: character-code-point @@enDesc: The character code position, in > notation. @@Method: @@@Name: after @@@Param: @@@@Name: name @@@@Type: DOMString @@@@enDesc: The name of the method. @@@Param: @@@@Name: p @@@@Type: DISPerl|HASH @@@@enDesc: The set of the parameters to the method. @@@Param: @@@@Name: o @@@@Type: DISPerl|HASH @@@@enDesc: The option value. @@@RuleParam: @@@@Name: v @@@@Type: DISPerl|Number @@@@enDesc: The name of the error parameter that contains the character code. @@@Return: @@@@PerlDef: $p->{-result} = sprintf 'U+%04X', $o->{$p->{v}}; ##XMLParserExceptionFormatter