source: trunk/src/corelib/xml/qxmlstream.g@ 440

Last change on this file since 440 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 55.5 KB
Line 
1----------------------------------------------------------------------------
2--
3-- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4-- Contact: Qt Software Information ([email protected])
5--
6-- This file is part of the QtCore module of the Qt Toolkit.
7--
8-- $QT_BEGIN_LICENSE:LGPL$
9-- Commercial Usage
10-- Licensees holding valid Qt Commercial licenses may use this file in
11-- accordance with the Qt Commercial License Agreement provided with the
12-- Software or, alternatively, in accordance with the terms contained in
13-- a written agreement between you and Nokia.
14--
15-- GNU Lesser General Public License Usage
16-- Alternatively, this file may be used under the terms of the GNU Lesser
17-- General Public License version 2.1 as published by the Free Software
18-- Foundation and appearing in the file LICENSE.LGPL included in the
19-- packaging of this file. Please review the following information to
20-- ensure the GNU Lesser General Public License version 2.1 requirements
21-- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22--
23-- In addition, as a special exception, Nokia gives you certain
24-- additional rights. These rights are described in the Nokia Qt LGPL
25-- Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26-- package.
27--
28-- GNU General Public License Usage
29-- Alternatively, this file may be used under the terms of the GNU
30-- General Public License version 3.0 as published by the Free Software
31-- Foundation and appearing in the file LICENSE.GPL included in the
32-- packaging of this file. Please review the following information to
33-- ensure the GNU General Public License version 3.0 requirements will be
34-- met: http://www.gnu.org/copyleft/gpl.html.
35--
36-- If you are unsure which license is appropriate for your use, please
37-- contact the sales department at [email protected].
38-- $QT_END_LICENSE$
39--
40-- This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
41-- WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
42--
43----------------------------------------------------------------------------
44
45%parser QXmlStreamReader_Table
46
47%merged_output qxmlstream_p.h
48
49%token NOTOKEN
50%token SPACE " "
51%token LANGLE "<"
52%token RANGLE ">"
53%token AMPERSAND "&"
54%token HASH "#"
55%token QUOTE "\'"
56%token DBLQUOTE "\""
57%token LBRACK "["
58%token RBRACK "]"
59%token LPAREN "("
60%token RPAREN ")"
61%token PIPE "|"
62%token EQ "="
63%token PERCENT "%"
64%token SLASH "/"
65%token COLON ":"
66%token SEMICOLON ";"
67%token COMMA ","
68%token DASH "-"
69%token PLUS "+"
70%token STAR "*"
71%token DOT "."
72%token QUESTIONMARK "?"
73%token BANG "!"
74%token LETTER "[a-zA-Z]"
75%token DIGIT "[0-9]"
76
77-- after langle_bang
78%token CDATA_START "[CDATA["
79%token DOCTYPE "DOCTYPE"
80%token ELEMENT "ELEMENT"
81%token ATTLIST "ATTLIST"
82%token ENTITY "ENTITY"
83%token NOTATION "NOTATION"
84
85-- entity decl
86%token SYSTEM "SYSTEM"
87%token PUBLIC "PUBLIC"
88%token NDATA "NDATA"
89
90-- default decl
91%token REQUIRED "REQUIRED"
92%token IMPLIED "IMPLIED"
93%token FIXED "FIXED"
94
95-- conent spec
96%token EMPTY "EMPTY"
97%token ANY "ANY"
98%token PCDATA "PCDATA"
99
100-- error
101%token ERROR
102
103-- entities
104%token PARSE_ENTITY
105%token ENTITY_DONE
106%token UNRESOLVED_ENTITY
107
108-- att type
109%token CDATA "CDATA"
110%token ID "ID"
111%token IDREF "IDREF"
112%token IDREFS "IDREFS"
113%token ENTITY "ENTITY"
114%token ENTITIES "ENTITIES"
115%token NMTOKEN "NMTOKEN"
116%token NMTOKENS "NMTOKENS"
117
118-- xml declaration
119%token XML "<?xml"
120%token VERSION "version"
121
122%nonassoc SHIFT_THERE
123%nonassoc AMPERSAND
124 BANG
125 COLON
126 COMMA
127 DASH
128 DBLQUOTE
129 DIGIT
130 DOT
131 ENTITY_DONE
132 EQ
133 HASH
134 LBRACK
135 LETTER
136 LPAREN
137 PERCENT
138 PIPE
139 PLUS
140 QUESTIONMARK
141 QUOTE
142 RANGLE
143 RBRACK
144 RPAREN
145 SEMICOLON
146 SLASH
147 SPACE
148 STAR
149
150%start document
151
152/.
153template <typename T> class QXmlStreamSimpleStack {
154 T *data;
155 int tos, cap;
156public:
157 inline QXmlStreamSimpleStack():data(0), tos(-1), cap(0){}
158 inline ~QXmlStreamSimpleStack(){ if (data) qFree(data); }
159
160 inline void reserve(int extraCapacity) {
161 if (tos + extraCapacity + 1 > cap) {
162 cap = qMax(tos + extraCapacity + 1, cap << 1 );
163 data = reinterpret_cast<T *>(qRealloc(data, cap * sizeof(T)));
164 }
165 }
166
167 inline T &push() { reserve(1); return data[++tos]; }
168 inline T &rawPush() { return data[++tos]; }
169 inline const T &top() const { return data[tos]; }
170 inline T &top() { return data[tos]; }
171 inline T &pop() { return data[tos--]; }
172 inline T &operator[](int index) { return data[index]; }
173 inline const T &at(int index) const { return data[index]; }
174 inline int size() const { return tos + 1; }
175 inline void resize(int s) { tos = s - 1; }
176 inline bool isEmpty() const { return tos < 0; }
177 inline void clear() { tos = -1; }
178};
179
180
181class QXmlStream
182{
183 Q_DECLARE_TR_FUNCTIONS(QXmlStream)
184};
185
186class QXmlStreamPrivateTagStack {
187public:
188 struct NamespaceDeclaration
189 {
190 QStringRef prefix;
191 QStringRef namespaceUri;
192 };
193
194 struct Tag
195 {
196 QStringRef name;
197 QStringRef qualifiedName;
198 NamespaceDeclaration namespaceDeclaration;
199 int tagStackStringStorageSize;
200 int namespaceDeclarationsSize;
201 };
202
203
204 QXmlStreamPrivateTagStack();
205 QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
206 QString tagStackStringStorage;
207 int tagStackStringStorageSize;
208 bool tagsDone;
209
210 inline QStringRef addToStringStorage(const QStringRef &s) {
211 int pos = tagStackStringStorageSize;
212 int sz = s.size();
213 if (pos != tagStackStringStorage.size())
214 tagStackStringStorage.resize(pos);
215 tagStackStringStorage.insert(pos, s.unicode(), sz);
216 tagStackStringStorageSize += sz;
217 return QStringRef(&tagStackStringStorage, pos, sz);
218 }
219 inline QStringRef addToStringStorage(const QString &s) {
220 int pos = tagStackStringStorageSize;
221 int sz = s.size();
222 if (pos != tagStackStringStorage.size())
223 tagStackStringStorage.resize(pos);
224 tagStackStringStorage.insert(pos, s.unicode(), sz);
225 tagStackStringStorageSize += sz;
226 return QStringRef(&tagStackStringStorage, pos, sz);
227 }
228
229 QXmlStreamSimpleStack<Tag> tagStack;
230
231
232 inline Tag &tagStack_pop() {
233 Tag& tag = tagStack.pop();
234 tagStackStringStorageSize = tag.tagStackStringStorageSize;
235 namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
236 tagsDone = tagStack.isEmpty();
237 return tag;
238 }
239 inline Tag &tagStack_push() {
240 Tag &tag = tagStack.push();
241 tag.tagStackStringStorageSize = tagStackStringStorageSize;
242 tag.namespaceDeclarationsSize = namespaceDeclarations.size();
243 return tag;
244 }
245};
246
247
248class QXmlStreamEntityResolver;
249
250class QXmlStreamReaderPrivate : public QXmlStreamReader_Table, public QXmlStreamPrivateTagStack{
251 QXmlStreamReader *q_ptr;
252 Q_DECLARE_PUBLIC(QXmlStreamReader)
253public:
254 QXmlStreamReaderPrivate(QXmlStreamReader *q);
255 ~QXmlStreamReaderPrivate();
256 void init();
257
258 QByteArray rawReadBuffer;
259 QByteArray dataBuffer;
260 uchar firstByte;
261 qint64 nbytesread;
262 QString readBuffer;
263 int readBufferPos;
264 QXmlStreamSimpleStack<uint> putStack;
265 struct Entity {
266 Entity(const QString& str = QString())
267 :value(str), external(false), unparsed(false), literal(false),
268 hasBeenParsed(false), isCurrentlyReferenced(false){}
269 static inline Entity createLiteral(const QString &entity)
270 { Entity result(entity); result.literal = result.hasBeenParsed = true; return result; }
271 QString value;
272 uint external : 1;
273 uint unparsed : 1;
274 uint literal : 1;
275 uint hasBeenParsed : 1;
276 uint isCurrentlyReferenced : 1;
277 };
278 QHash<QString, Entity> entityHash;
279 QHash<QString, Entity> parameterEntityHash;
280 QXmlStreamSimpleStack<Entity *>entityReferenceStack;
281 inline bool referenceEntity(Entity &entity) {
282 if (entity.isCurrentlyReferenced) {
283 raiseWellFormedError(QXmlStream::tr("Recursive entity detected."));
284 return false;
285 }
286 entity.isCurrentlyReferenced = true;
287 entityReferenceStack.push() = &entity;
288 injectToken(ENTITY_DONE);
289 return true;
290 }
291
292
293 QIODevice *device;
294 bool deleteDevice;
295#ifndef QT_NO_TEXTCODEC
296 QTextCodec *codec;
297 QTextDecoder *decoder;
298#endif
299 bool atEnd;
300
301 /*!
302 \sa setType()
303 */
304 QXmlStreamReader::TokenType type;
305 QXmlStreamReader::Error error;
306 QString errorString;
307 QString unresolvedEntity;
308
309 qint64 lineNumber, lastLineStart, characterOffset;
310
311
312 void write(const QString &);
313 void write(const char *);
314
315
316 QXmlStreamAttributes attributes;
317 QStringRef namespaceForPrefix(const QStringRef &prefix);
318 void resolveTag();
319 void resolvePublicNamespaces();
320 void resolveDtd();
321 uint resolveCharRef(int symbolIndex);
322 bool checkStartDocument();
323 void startDocument();
324 void parseError();
325 void checkPublicLiteral(const QStringRef &publicId);
326
327 bool scanDtd;
328 QStringRef lastAttributeValue;
329 bool lastAttributeIsCData;
330 struct DtdAttribute {
331 QStringRef tagName;
332 QStringRef attributeQualifiedName;
333 QStringRef attributePrefix;
334 QStringRef attributeName;
335 QStringRef defaultValue;
336 bool isCDATA;
337 bool isNamespaceAttribute;
338 };
339 QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
340 struct NotationDeclaration {
341 QStringRef name;
342 QStringRef publicId;
343 QStringRef systemId;
344 };
345 QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
346 QXmlStreamNotationDeclarations publicNotationDeclarations;
347 QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
348
349 struct EntityDeclaration {
350 QStringRef name;
351 QStringRef notationName;
352 QStringRef publicId;
353 QStringRef systemId;
354 QStringRef value;
355 bool parameter;
356 bool external;
357 inline void clear() {
358 name.clear();
359 notationName.clear();
360 publicId.clear();
361 systemId.clear();
362 value.clear();
363 parameter = external = false;
364 }
365 };
366 QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
367 QXmlStreamEntityDeclarations publicEntityDeclarations;
368
369 QStringRef text;
370
371 QStringRef prefix, namespaceUri, qualifiedName, name;
372 QStringRef processingInstructionTarget, processingInstructionData;
373 QStringRef dtdName, dtdPublicId, dtdSystemId;
374 QStringRef documentVersion, documentEncoding;
375 uint isEmptyElement : 1;
376 uint isWhitespace : 1;
377 uint isCDATA : 1;
378 uint standalone : 1;
379 uint hasCheckedStartDocument : 1;
380 uint normalizeLiterals : 1;
381 uint hasSeenTag : 1;
382 uint inParseEntity : 1;
383 uint referenceToUnparsedEntityDetected : 1;
384 uint referenceToParameterEntityDetected : 1;
385 uint hasExternalDtdSubset : 1;
386 uint lockEncoding : 1;
387 uint namespaceProcessing : 1;
388
389 int resumeReduction;
390 void resume(int rule);
391
392 inline bool entitiesMustBeDeclared() const {
393 return (!inParseEntity
394 && (standalone
395 || (!referenceToUnparsedEntityDetected
396 && !referenceToParameterEntityDetected // Errata 13 as of 2006-04-25
397 && !hasExternalDtdSubset)));
398 }
399
400 // qlalr parser
401 int tos;
402 int stack_size;
403 struct Value {
404 int pos;
405 int len;
406 int prefix;
407 ushort c;
408 };
409
410 Value *sym_stack;
411 int *state_stack;
412 inline void reallocateStack();
413 inline Value &sym(int index) const
414 { return sym_stack[tos + index - 1]; }
415 QString textBuffer;
416 inline void clearTextBuffer() {
417 if (!scanDtd) {
418 textBuffer.resize(0);
419 textBuffer.reserve(256);
420 }
421 }
422 struct Attribute {
423 Value key;
424 Value value;
425 };
426 QXmlStreamSimpleStack<Attribute> attributeStack;
427
428 inline QStringRef symString(int index) {
429 const Value &symbol = sym(index);
430 return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
431 }
432 inline QStringRef symName(int index) {
433 const Value &symbol = sym(index);
434 return QStringRef(&textBuffer, symbol.pos, symbol.len);
435 }
436 inline QStringRef symString(int index, int offset) {
437 const Value &symbol = sym(index);
438 return QStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
439 }
440 inline QStringRef symPrefix(int index) {
441 const Value &symbol = sym(index);
442 if (symbol.prefix)
443 return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
444 return QStringRef();
445 }
446 inline QStringRef symString(const Value &symbol) {
447 return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
448 }
449 inline QStringRef symName(const Value &symbol) {
450 return QStringRef(&textBuffer, symbol.pos, symbol.len);
451 }
452 inline QStringRef symPrefix(const Value &symbol) {
453 if (symbol.prefix)
454 return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
455 return QStringRef();
456 }
457
458 inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
459
460
461 short token;
462 ushort token_char;
463
464 uint filterCarriageReturn();
465 inline uint getChar();
466 inline uint peekChar();
467 inline void putChar(uint c) { putStack.push() = c; }
468 inline void putChar(QChar c) { putStack.push() = c.unicode(); }
469 void putString(const QString &s, int from = 0);
470 void putStringLiteral(const QString &s);
471 void putReplacement(const QString &s);
472 void putReplacementInAttributeValue(const QString &s);
473 ushort getChar_helper();
474
475 bool scanUntil(const char *str, short tokenToInject = -1);
476 bool scanString(const char *str, short tokenToInject, bool requireSpace = true);
477 inline void injectToken(ushort tokenToInject) {
478 putChar(int(tokenToInject) << 16);
479 }
480
481 QString resolveUndeclaredEntity(const QString &name);
482 void parseEntity(const QString &value);
483 QXmlStreamReaderPrivate *entityParser;
484
485 bool scanAfterLangleBang();
486 bool scanPublicOrSystem();
487 bool scanNData();
488 bool scanAfterDefaultDecl();
489 bool scanAttType();
490
491
492 // scan optimization functions. Not strictly necessary but LALR is
493 // not very well suited for scanning fast
494 int fastScanLiteralContent();
495 int fastScanSpace();
496 int fastScanContentCharList();
497 int fastScanName(int *prefix = 0);
498 inline int fastScanNMTOKEN();
499
500
501 bool parse();
502 inline void consumeRule(int);
503
504 void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
505 void raiseWellFormedError(const QString &message);
506
507 QXmlStreamEntityResolver *entityResolver;
508
509private:
510 /*! \internal
511 Never assign to variable type directly. Instead use this function.
512
513 This prevents errors from being ignored.
514 */
515 inline void setType(const QXmlStreamReader::TokenType t)
516 {
517 if(type != QXmlStreamReader::Invalid)
518 type = t;
519 }
520};
521
522bool QXmlStreamReaderPrivate::parse()
523{
524 // cleanup currently reported token
525
526 switch (type) {
527 case QXmlStreamReader::StartElement:
528 name.clear();
529 prefix.clear();
530 qualifiedName.clear();
531 namespaceUri.clear();
532 if (publicNamespaceDeclarations.size())
533 publicNamespaceDeclarations.clear();
534 if (attributes.size())
535 attributes.resize(0);
536 if (isEmptyElement) {
537 setType(QXmlStreamReader::EndElement);
538 Tag &tag = tagStack_pop();
539 namespaceUri = tag.namespaceDeclaration.namespaceUri;
540 name = tag.name;
541 qualifiedName = tag.qualifiedName;
542 isEmptyElement = false;
543 return true;
544 }
545 clearTextBuffer();
546 break;
547 case QXmlStreamReader::EndElement:
548 name.clear();
549 prefix.clear();
550 qualifiedName.clear();
551 namespaceUri.clear();
552 clearTextBuffer();
553 break;
554 case QXmlStreamReader::DTD:
555 publicNotationDeclarations.clear();
556 publicEntityDeclarations.clear();
557 dtdName.clear();
558 dtdPublicId.clear();
559 dtdSystemId.clear();
560 // fall through
561 case QXmlStreamReader::Comment:
562 case QXmlStreamReader::Characters:
563 isCDATA = false;
564 isWhitespace = true;
565 text.clear();
566 clearTextBuffer();
567 break;
568 case QXmlStreamReader::EntityReference:
569 text.clear();
570 name.clear();
571 clearTextBuffer();
572 break;
573 case QXmlStreamReader::ProcessingInstruction:
574 processingInstructionTarget.clear();
575 processingInstructionData.clear();
576 clearTextBuffer();
577 break;
578 case QXmlStreamReader::NoToken:
579 case QXmlStreamReader::Invalid:
580 break;
581 case QXmlStreamReader::StartDocument:
582 lockEncoding = true;
583 documentVersion.clear();
584 documentEncoding.clear();
585#ifndef QT_NO_TEXTCODEC
586 if(decoder->hasFailure()) {
587 raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
588 readBuffer.clear();
589 return false;
590 }
591#endif
592 // fall through
593 default:
594 clearTextBuffer();
595 ;
596 }
597
598 setType(QXmlStreamReader::NoToken);
599
600
601 // the main parse loop
602 int act, r;
603
604 if (resumeReduction) {
605 act = state_stack[tos-1];
606 r = resumeReduction;
607 resumeReduction = 0;
608 goto ResumeReduction;
609 }
610
611 act = state_stack[tos];
612
613 forever {
614 if (token == -1 && - TERMINAL_COUNT != action_index[act]) {
615 uint cu = getChar();
616 token = NOTOKEN;
617 token_char = cu;
618 if (cu & 0xff0000) {
619 token = cu >> 16;
620 } else switch (token_char) {
621 case 0xfffe:
622 case 0xffff:
623 token = ERROR;
624 break;
625 case '\r':
626 token = SPACE;
627 if (cu == '\r') {
628 if ((token_char = filterCarriageReturn())) {
629 ++lineNumber;
630 lastLineStart = characterOffset + readBufferPos;
631 break;
632 }
633 } else {
634 break;
635 }
636 // fall through
637 case '\0': {
638 token = EOF_SYMBOL;
639 if (!tagsDone && !inParseEntity) {
640 int a = t_action(act, token);
641 if (a < 0) {
642 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
643 return false;
644 }
645 }
646
647 } break;
648 case '\n':
649 ++lineNumber;
650 lastLineStart = characterOffset + readBufferPos;
651 case ' ':
652 case '\t':
653 token = SPACE;
654 break;
655 case '&':
656 token = AMPERSAND;
657 break;
658 case '#':
659 token = HASH;
660 break;
661 case '\'':
662 token = QUOTE;
663 break;
664 case '\"':
665 token = DBLQUOTE;
666 break;
667 case '<':
668 token = LANGLE;
669 break;
670 case '>':
671 token = RANGLE;
672 break;
673 case '[':
674 token = LBRACK;
675 break;
676 case ']':
677 token = RBRACK;
678 break;
679 case '(':
680 token = LPAREN;
681 break;
682 case ')':
683 token = RPAREN;
684 break;
685 case '|':
686 token = PIPE;
687 break;
688 case '=':
689 token = EQ;
690 break;
691 case '%':
692 token = PERCENT;
693 break;
694 case '/':
695 token = SLASH;
696 break;
697 case ':':
698 token = COLON;
699 break;
700 case ';':
701 token = SEMICOLON;
702 break;
703 case ',':
704 token = COMMA;
705 break;
706 case '-':
707 token = DASH;
708 break;
709 case '+':
710 token = PLUS;
711 break;
712 case '*':
713 token = STAR;
714 break;
715 case '.':
716 token = DOT;
717 break;
718 case '?':
719 token = QUESTIONMARK;
720 break;
721 case '!':
722 token = BANG;
723 break;
724 case '0':
725 case '1':
726 case '2':
727 case '3':
728 case '4':
729 case '5':
730 case '6':
731 case '7':
732 case '8':
733 case '9':
734 token = DIGIT;
735 break;
736 default:
737 if (cu < 0x20)
738 token = NOTOKEN;
739 else
740 token = LETTER;
741 break;
742 }
743 }
744
745 act = t_action (act, token);
746 if (act == ACCEPT_STATE) {
747 // reset the parser in case someone resumes (process instructions can follow a valid document)
748 tos = 0;
749 state_stack[tos++] = 0;
750 state_stack[tos] = 0;
751 return true;
752 } else if (act > 0) {
753 if (++tos == stack_size)
754 reallocateStack();
755
756 Value &val = sym_stack[tos];
757 val.c = token_char;
758 val.pos = textBuffer.size();
759 val.prefix = 0;
760 val.len = 1;
761 if (token_char)
762 textBuffer += QChar(token_char);
763
764 state_stack[tos] = act;
765 token = -1;
766
767
768 } else if (act < 0) {
769 r = - act - 1;
770
771#if defined (QLALR_DEBUG)
772 int ridx = rule_index[r];
773 printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]);
774 ++ridx;
775 for (int i = ridx; i < ridx + rhs[r]; ++i) {
776 int symbol = rule_info[i];
777 if (const char *name = spell[symbol])
778 printf (" %s", name);
779 else
780 printf (" #%d", symbol);
781 }
782 printf ("\n");
783#endif
784
785 tos -= rhs[r];
786 act = state_stack[tos++];
787 ResumeReduction:
788 switch (r) {
789./
790
791document ::= PARSE_ENTITY content;
792/.
793 case $rule_number:
794 setType(QXmlStreamReader::EndDocument);
795 break;
796./
797
798document ::= prolog;
799/.
800 case $rule_number:
801 if (type != QXmlStreamReader::Invalid) {
802 if (hasSeenTag || inParseEntity) {
803 setType(QXmlStreamReader::EndDocument);
804 } else {
805 raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected."));
806 // reset the parser
807 tos = 0;
808 state_stack[tos++] = 0;
809 state_stack[tos] = 0;
810 return false;
811 }
812 }
813 break;
814./
815
816
817prolog ::= prolog stag content etag;
818prolog ::= prolog empty_element_tag;
819prolog ::= prolog comment;
820prolog ::= prolog xml_decl;
821prolog ::= prolog processing_instruction;
822prolog ::= prolog doctype_decl;
823prolog ::= prolog SPACE;
824prolog ::=;
825
826entity_done ::= ENTITY_DONE;
827/.
828 case $rule_number:
829 entityReferenceStack.pop()->isCurrentlyReferenced = false;
830 clearSym();
831 break;
832./
833
834
835xml_decl_start ::= XML;
836/.
837 case $rule_number:
838 if (!scanString(spell[VERSION], VERSION, false) && atEnd) {
839 resume($rule_number);
840 return false;
841 }
842 break;
843./
844
845xml_decl ::= xml_decl_start VERSION space_opt EQ space_opt literal attribute_list_opt QUESTIONMARK RANGLE;
846/.
847 case $rule_number:
848 setType(QXmlStreamReader::StartDocument);
849 documentVersion = symString(6);
850 startDocument();
851 break;
852./
853
854external_id ::= SYSTEM literal;
855/.
856 case $rule_number:
857 hasExternalDtdSubset = true;
858 dtdSystemId = symString(2);
859 break;
860./
861external_id ::= PUBLIC public_literal space literal;
862/.
863 case $rule_number:
864 checkPublicLiteral(symString(2));
865 dtdPublicId = symString(2);
866 dtdSystemId = symString(4);
867 hasExternalDtdSubset = true;
868 break;
869./
870external_id ::=;
871
872doctype_decl_start ::= langle_bang DOCTYPE qname space;
873/.
874 case $rule_number:
875 if (!scanPublicOrSystem() && atEnd) {
876 resume($rule_number);
877 return false;
878 }
879 dtdName = symString(3);
880 break;
881./
882
883doctype_decl ::= langle_bang DOCTYPE qname RANGLE;
884/.
885 case $rule_number:./
886doctype_decl ::= langle_bang DOCTYPE qname markup space_opt RANGLE;
887/.
888 case $rule_number:
889 dtdName = symString(3);
890 // fall through
891./
892doctype_decl ::= doctype_decl_start external_id space_opt markup space_opt RANGLE;
893/.
894 case $rule_number:./
895doctype_decl ::= doctype_decl_start external_id space_opt RANGLE;
896/.
897 case $rule_number:
898 setType(QXmlStreamReader::DTD);
899 text = &textBuffer;
900 break;
901./
902
903markup_start ::= LBRACK;
904/.
905 case $rule_number:
906 scanDtd = true;
907 break;
908./
909
910markup ::= markup_start markup_list RBRACK;
911/.
912 case $rule_number:
913 scanDtd = false;
914 break;
915./
916
917
918markup_list ::= markup_decl | space | pereference;
919markup_list ::= markup_list markup_decl | markup_list space | markup_list pereference;
920
921markup_decl ::= element_decl | attlist_decl | entity_decl | entity_done | notation_decl | processing_instruction | comment;
922
923
924element_decl_start ::= langle_bang ELEMENT qname space;
925/.
926 case $rule_number:
927 if (!scanString(spell[EMPTY], EMPTY, false)
928 && !scanString(spell[ANY], ANY, false)
929 && atEnd) {
930 resume($rule_number);
931 return false;
932 }
933 break;
934./
935
936element_decl ::= element_decl_start content_spec space_opt RANGLE;
937
938
939content_spec ::= EMPTY | ANY | mixed | children;
940
941pcdata_start ::= HASH;
942/.
943 case $rule_number:
944 if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) {
945 resume($rule_number);
946 return false;
947 }
948 break;
949./
950
951pcdata ::= pcdata_start PCDATA;
952
953questionmark_or_star_or_plus_opt ::= QUESTIONMARK | STAR | PLUS;
954questionmark_or_star_or_plus_opt ::=;
955
956cp ::= qname questionmark_or_star_or_plus_opt | choice_or_seq questionmark_or_star_or_plus_opt;
957
958cp_pipe_or_comma_list ::= cp space_opt;
959cp_pipe_or_comma_list ::= cp space_opt PIPE space_opt cp_pipe_list space_opt;
960cp_pipe_or_comma_list ::= cp space_opt COMMA space_opt cp_comma_list space_opt;
961cp_pipe_list ::= cp | cp_pipe_list space_opt PIPE space_opt cp;
962cp_comma_list ::= cp | cp_comma_list space_opt COMMA space_opt cp;
963
964
965name_pipe_list ::= PIPE space_opt qname;
966name_pipe_list ::= name_pipe_list space_opt PIPE space_opt qname;
967
968star_opt ::= | STAR;
969
970mixed ::= LPAREN space_opt pcdata space_opt RPAREN star_opt;
971mixed ::= LPAREN space_opt pcdata space_opt name_pipe_list space_opt RPAREN STAR;
972
973choice_or_seq ::= LPAREN space_opt cp_pipe_or_comma_list RPAREN;
974
975children ::= choice_or_seq questionmark_or_star_or_plus_opt;
976
977
978nmtoken_pipe_list ::= nmtoken;
979nmtoken_pipe_list ::= nmtoken_pipe_list space_opt PIPE space_opt nmtoken;
980
981
982att_type ::= CDATA;
983/.
984 case $rule_number: {
985 lastAttributeIsCData = true;
986 } break;
987./
988att_type ::= ID | IDREF | IDREFS | ENTITY | ENTITIES | NMTOKEN | NMTOKENS;
989att_type ::= LPAREN space_opt nmtoken_pipe_list space_opt RPAREN space;
990att_type ::= NOTATION LPAREN space_opt nmtoken_pipe_list space_opt RPAREN space;
991
992
993default_declhash ::= HASH;
994/.
995 case $rule_number:
996 if (!scanAfterDefaultDecl() && atEnd) {
997 resume($rule_number);
998 return false;
999 }
1000 break;
1001./
1002
1003default_decl ::= default_declhash REQUIRED;
1004default_decl ::= default_declhash IMPLIED;
1005default_decl ::= attribute_value;
1006default_decl ::= default_declhash FIXED space attribute_value;
1007attdef_start ::= space qname space;
1008/.
1009 case $rule_number:
1010 sym(1) = sym(2);
1011 lastAttributeValue.clear();
1012 lastAttributeIsCData = false;
1013 if (!scanAttType() && atEnd) {
1014 resume($rule_number);
1015 return false;
1016 }
1017 break;
1018./
1019
1020attdef ::= attdef_start att_type default_decl;
1021/.
1022 case $rule_number: {
1023 DtdAttribute &dtdAttribute = dtdAttributes.push();
1024 dtdAttribute.tagName.clear();
1025 dtdAttribute.isCDATA = lastAttributeIsCData;
1026 dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1));
1027 dtdAttribute.attributeName = addToStringStorage(symString(1));
1028 dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1));
1029 dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns")
1030 || (dtdAttribute.attributePrefix.isEmpty()
1031 && dtdAttribute.attributeName == QLatin1String("xmlns")));
1032 if (lastAttributeValue.isNull()) {
1033 dtdAttribute.defaultValue.clear();
1034 } else {
1035 if (dtdAttribute.isCDATA)
1036 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue);
1037 else
1038 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified());
1039
1040 }
1041 } break;
1042./
1043
1044attdef_list ::= attdef;
1045attdef_list ::= attdef_list attdef;
1046
1047attlist_decl ::= langle_bang ATTLIST qname space_opt RANGLE;
1048attlist_decl ::= langle_bang ATTLIST qname attdef_list space_opt RANGLE;
1049/.
1050 case $rule_number: {
1051 if (referenceToUnparsedEntityDetected && !standalone)
1052 break;
1053 int n = dtdAttributes.size();
1054 QStringRef tagName = addToStringStorage(symName(3));
1055 while (n--) {
1056 DtdAttribute &dtdAttribute = dtdAttributes[n];
1057 if (!dtdAttribute.tagName.isNull())
1058 break;
1059 dtdAttribute.tagName = tagName;
1060 for (int i = 0; i < n; ++i) {
1061 if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
1062 && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
1063 dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
1064 break;
1065 }
1066 }
1067 }
1068 } break;
1069./
1070
1071entity_decl_start ::= langle_bang ENTITY name space;
1072/.
1073 case $rule_number: {
1074 if (!scanPublicOrSystem() && atEnd) {
1075 resume($rule_number);
1076 return false;
1077 }
1078 EntityDeclaration &entityDeclaration = entityDeclarations.push();
1079 entityDeclaration.clear();
1080 entityDeclaration.name = symString(3);
1081 } break;
1082./
1083
1084entity_decl_start ::= langle_bang ENTITY PERCENT space name space;
1085/.
1086 case $rule_number: {
1087 if (!scanPublicOrSystem() && atEnd) {
1088 resume($rule_number);
1089 return false;
1090 }
1091 EntityDeclaration &entityDeclaration = entityDeclarations.push();
1092 entityDeclaration.clear();
1093 entityDeclaration.name = symString(5);
1094 entityDeclaration.parameter = true;
1095 } break;
1096./
1097
1098entity_decl_external ::= entity_decl_start SYSTEM literal;
1099/.
1100 case $rule_number: {
1101 if (!scanNData() && atEnd) {
1102 resume($rule_number);
1103 return false;
1104 }
1105 EntityDeclaration &entityDeclaration = entityDeclarations.top();
1106 entityDeclaration.systemId = symString(3);
1107 entityDeclaration.external = true;
1108 } break;
1109./
1110
1111entity_decl_external ::= entity_decl_start PUBLIC public_literal space literal;
1112/.
1113 case $rule_number: {
1114 if (!scanNData() && atEnd) {
1115 resume($rule_number);
1116 return false;
1117 }
1118 EntityDeclaration &entityDeclaration = entityDeclarations.top();
1119 checkPublicLiteral((entityDeclaration.publicId = symString(3)));
1120 entityDeclaration.systemId = symString(5);
1121 entityDeclaration.external = true;
1122 } break;
1123./
1124
1125entity_decl ::= entity_decl_external NDATA name space_opt RANGLE;
1126/.
1127 case $rule_number: {
1128 EntityDeclaration &entityDeclaration = entityDeclarations.top();
1129 entityDeclaration.notationName = symString(3);
1130 if (entityDeclaration.parameter)
1131 raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration."));
1132 }
1133 //fall through
1134./
1135
1136entity_decl ::= entity_decl_external space_opt RANGLE;
1137/.
1138 case $rule_number:./
1139
1140entity_decl ::= entity_decl_start entity_value space_opt RANGLE;
1141/.
1142 case $rule_number: {
1143 if (referenceToUnparsedEntityDetected && !standalone) {
1144 entityDeclarations.pop();
1145 break;
1146 }
1147 EntityDeclaration &entityDeclaration = entityDeclarations.top();
1148 if (!entityDeclaration.external)
1149 entityDeclaration.value = symString(2);
1150 QString entityName = entityDeclaration.name.toString();
1151 QHash<QString, Entity> &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
1152 if (!hash.contains(entityName)) {
1153 Entity entity(entityDeclaration.value.toString());
1154 entity.unparsed = (!entityDeclaration.notationName.isNull());
1155 entity.external = entityDeclaration.external;
1156 hash.insert(entityName, entity);
1157 }
1158 } break;
1159./
1160
1161
1162processing_instruction ::= LANGLE QUESTIONMARK name space;
1163/.
1164 case $rule_number: {
1165 setType(QXmlStreamReader::ProcessingInstruction);
1166 int pos = sym(4).pos + sym(4).len;
1167 processingInstructionTarget = symString(3);
1168 if (scanUntil("?>")) {
1169 processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
1170 const QString piTarget(processingInstructionTarget.toString());
1171 if (!piTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
1172 raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
1173 }
1174 else if(!QXmlUtils::isNCName(piTarget))
1175 raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.").arg(piTarget));
1176 } else if (type != QXmlStreamReader::Invalid){
1177 resume($rule_number);
1178 return false;
1179 }
1180 } break;
1181./
1182
1183processing_instruction ::= LANGLE QUESTIONMARK name QUESTIONMARK RANGLE;
1184/.
1185 case $rule_number:
1186 setType(QXmlStreamReader::ProcessingInstruction);
1187 processingInstructionTarget = symString(3);
1188 if (!processingInstructionTarget.toString().compare(QLatin1String("xml"), Qt::CaseInsensitive))
1189 raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
1190 break;
1191./
1192
1193
1194langle_bang ::= LANGLE BANG;
1195/.
1196 case $rule_number:
1197 if (!scanAfterLangleBang() && atEnd) {
1198 resume($rule_number);
1199 return false;
1200 }
1201 break;
1202./
1203
1204comment_start ::= langle_bang DASH DASH;
1205/.
1206 case $rule_number:
1207 if (!scanUntil("--")) {
1208 resume($rule_number);
1209 return false;
1210 }
1211 break;
1212./
1213
1214comment ::= comment_start RANGLE;
1215/.
1216 case $rule_number: {
1217 setType(QXmlStreamReader::Comment);
1218 int pos = sym(1).pos + 4;
1219 text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
1220 } break;
1221./
1222
1223
1224cdata ::= langle_bang CDATA_START;
1225/.
1226 case $rule_number: {
1227 setType(QXmlStreamReader::Characters);
1228 isCDATA = true;
1229 isWhitespace = false;
1230 int pos = sym(2).pos;
1231 if (scanUntil("]]>", -1)) {
1232 text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
1233 } else {
1234 resume($rule_number);
1235 return false;
1236 }
1237 } break;
1238./
1239
1240notation_decl_start ::= langle_bang NOTATION name space;
1241/.
1242 case $rule_number: {
1243 if (!scanPublicOrSystem() && atEnd) {
1244 resume($rule_number);
1245 return false;
1246 }
1247 NotationDeclaration &notationDeclaration = notationDeclarations.push();
1248 notationDeclaration.name = symString(3);
1249 } break;
1250./
1251
1252notation_decl ::= notation_decl_start SYSTEM literal space_opt RANGLE;
1253/.
1254 case $rule_number: {
1255 NotationDeclaration &notationDeclaration = notationDeclarations.top();
1256 notationDeclaration.systemId = symString(3);
1257 notationDeclaration.publicId.clear();
1258 } break;
1259./
1260
1261notation_decl ::= notation_decl_start PUBLIC public_literal space_opt RANGLE;
1262/.
1263 case $rule_number: {
1264 NotationDeclaration &notationDeclaration = notationDeclarations.top();
1265 notationDeclaration.systemId.clear();
1266 checkPublicLiteral((notationDeclaration.publicId = symString(3)));
1267 } break;
1268./
1269
1270notation_decl ::= notation_decl_start PUBLIC public_literal space literal space_opt RANGLE;
1271/.
1272 case $rule_number: {
1273 NotationDeclaration &notationDeclaration = notationDeclarations.top();
1274 checkPublicLiteral((notationDeclaration.publicId = symString(3)));
1275 notationDeclaration.systemId = symString(5);
1276 } break;
1277./
1278
1279
1280
1281content_char ::= RANGLE | HASH | LBRACK | RBRACK | LPAREN | RPAREN | PIPE | EQ | PERCENT | SLASH | COLON | SEMICOLON | COMMA | DASH | PLUS | STAR | DOT | QUESTIONMARK | BANG | QUOTE | DBLQUOTE | LETTER | DIGIT;
1282
1283scan_content_char ::= content_char;
1284/.
1285 case $rule_number:
1286 isWhitespace = false;
1287 // fall through
1288./
1289
1290scan_content_char ::= SPACE;
1291/.
1292 case $rule_number:
1293 sym(1).len += fastScanContentCharList();
1294 if (atEnd && !inParseEntity) {
1295 resume($rule_number);
1296 return false;
1297 }
1298 break;
1299./
1300
1301content_char_list ::= content_char_list char_ref;
1302content_char_list ::= content_char_list entity_ref;
1303content_char_list ::= content_char_list entity_done;
1304content_char_list ::= content_char_list scan_content_char;
1305content_char_list ::= char_ref;
1306content_char_list ::= entity_ref;
1307content_char_list ::= entity_done;
1308content_char_list ::= scan_content_char;
1309
1310
1311character_content ::= content_char_list %prec SHIFT_THERE;
1312/.
1313 case $rule_number:
1314 if (!textBuffer.isEmpty()) {
1315 setType(QXmlStreamReader::Characters);
1316 text = &textBuffer;
1317 }
1318 break;
1319./
1320
1321literal ::= QUOTE QUOTE;
1322/.
1323 case $rule_number:./
1324literal ::= DBLQUOTE DBLQUOTE;
1325/.
1326 case $rule_number:
1327 clearSym();
1328 break;
1329./
1330literal ::= QUOTE literal_content_with_dblquote QUOTE;
1331/.
1332 case $rule_number:./
1333literal ::= DBLQUOTE literal_content_with_quote DBLQUOTE;
1334/.
1335 case $rule_number:
1336 sym(1) = sym(2);
1337 break;
1338./
1339
1340literal_content_with_dblquote ::= literal_content_with_dblquote literal_content;
1341/.
1342 case $rule_number:./
1343literal_content_with_quote ::= literal_content_with_quote literal_content;
1344/.
1345 case $rule_number:./
1346literal_content_with_dblquote ::= literal_content_with_dblquote DBLQUOTE;
1347/.
1348 case $rule_number:./
1349literal_content_with_quote ::= literal_content_with_quote QUOTE;
1350/.
1351 case $rule_number:
1352 sym(1).len += sym(2).len;
1353 break;
1354./
1355literal_content_with_dblquote ::= literal_content;
1356literal_content_with_quote ::= literal_content;
1357literal_content_with_dblquote ::= DBLQUOTE;
1358literal_content_with_quote ::= QUOTE;
1359
1360literal_content_start ::= LETTER | DIGIT | RANGLE | HASH | LBRACK | RBRACK | LPAREN | RPAREN | PIPE | EQ | PERCENT | SLASH | COLON | SEMICOLON | COMMA | DASH | PLUS | STAR | DOT | QUESTIONMARK | BANG;
1361
1362literal_content_start ::= SPACE;
1363/.
1364 case $rule_number:
1365 if (normalizeLiterals)
1366 textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' ');
1367 break;
1368./
1369
1370literal_content ::= literal_content_start;
1371/.
1372 case $rule_number:
1373 sym(1).len += fastScanLiteralContent();
1374 if (atEnd) {
1375 resume($rule_number);
1376 return false;
1377 }
1378 break;
1379./
1380
1381
1382public_literal ::= literal;
1383/.
1384 case $rule_number: {
1385 if (!QXmlUtils::isPublicID(symString(1).toString())) {
1386 raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1).toString()));
1387 resume($rule_number);
1388 return false;
1389 }
1390 } break;
1391./
1392
1393entity_value ::= QUOTE QUOTE;
1394/.
1395 case $rule_number:./
1396entity_value ::= DBLQUOTE DBLQUOTE;
1397/.
1398 case $rule_number:
1399 clearSym();
1400 break;
1401./
1402
1403entity_value ::= QUOTE entity_value_content_with_dblquote QUOTE;
1404/.
1405 case $rule_number:./
1406entity_value ::= DBLQUOTE entity_value_content_with_quote DBLQUOTE;
1407/.
1408 case $rule_number:
1409 sym(1) = sym(2);
1410 break;
1411./
1412
1413entity_value_content_with_dblquote ::= entity_value_content_with_dblquote entity_value_content;
1414/.
1415 case $rule_number:./
1416entity_value_content_with_quote ::= entity_value_content_with_quote entity_value_content;
1417/.
1418 case $rule_number:./
1419entity_value_content_with_dblquote ::= entity_value_content_with_dblquote DBLQUOTE;
1420/.
1421 case $rule_number:./
1422entity_value_content_with_quote ::= entity_value_content_with_quote QUOTE;
1423/.
1424 case $rule_number:
1425 sym(1).len += sym(2).len;
1426 break;
1427./
1428entity_value_content_with_dblquote ::= entity_value_content;
1429entity_value_content_with_quote ::= entity_value_content;
1430entity_value_content_with_dblquote ::= DBLQUOTE;
1431entity_value_content_with_quote ::= QUOTE;
1432
1433entity_value_content ::= LETTER | DIGIT | LANGLE | RANGLE | HASH | LBRACK | RBRACK | LPAREN | RPAREN | PIPE | EQ | SLASH | COLON | SEMICOLON | COMMA | SPACE | DASH | PLUS | STAR | DOT | QUESTIONMARK | BANG;
1434entity_value_content ::= char_ref | entity_ref_in_entity_value | entity_done;
1435
1436
1437attribute_value ::= QUOTE QUOTE;
1438/.
1439 case $rule_number:./
1440attribute_value ::= DBLQUOTE DBLQUOTE;
1441/.
1442 case $rule_number:
1443 clearSym();
1444 break;
1445./
1446attribute_value ::= QUOTE attribute_value_content_with_dblquote QUOTE;
1447/.
1448 case $rule_number:./
1449attribute_value ::= DBLQUOTE attribute_value_content_with_quote DBLQUOTE;
1450/.
1451 case $rule_number:
1452 sym(1) = sym(2);
1453 lastAttributeValue = symString(1);
1454 break;
1455./
1456
1457attribute_value_content_with_dblquote ::= attribute_value_content_with_dblquote attribute_value_content;
1458/.
1459 case $rule_number:./
1460attribute_value_content_with_quote ::= attribute_value_content_with_quote attribute_value_content;
1461/.
1462 case $rule_number:./
1463attribute_value_content_with_dblquote ::= attribute_value_content_with_dblquote DBLQUOTE;
1464/.
1465 case $rule_number:./
1466attribute_value_content_with_quote ::= attribute_value_content_with_quote QUOTE;
1467/.
1468 case $rule_number:
1469 sym(1).len += sym(2).len;
1470 break;
1471./
1472attribute_value_content_with_dblquote ::= attribute_value_content | DBLQUOTE;
1473attribute_value_content_with_quote ::= attribute_value_content | QUOTE;
1474
1475attribute_value_content ::= literal_content | char_ref | entity_ref_in_attribute_value | entity_done;
1476
1477attribute ::= qname space_opt EQ space_opt attribute_value;
1478/.
1479 case $rule_number: {
1480 QStringRef prefix = symPrefix(1);
1481 if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
1482 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
1483 namespaceDeclaration.prefix.clear();
1484
1485 const QStringRef ns(symString(5));
1486 if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
1487 ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
1488 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
1489 else
1490 namespaceDeclaration.namespaceUri = addToStringStorage(ns);
1491 } else {
1492 Attribute &attribute = attributeStack.push();
1493 attribute.key = sym(1);
1494 attribute.value = sym(5);
1495
1496 QStringRef attributeQualifiedName = symName(1);
1497 bool normalize = false;
1498 for (int a = 0; a < dtdAttributes.size(); ++a) {
1499 DtdAttribute &dtdAttribute = dtdAttributes[a];
1500 if (!dtdAttribute.isCDATA
1501 && dtdAttribute.tagName == qualifiedName
1502 && dtdAttribute.attributeQualifiedName == attributeQualifiedName
1503 ) {
1504 normalize = true;
1505 break;
1506 }
1507 }
1508 if (normalize) {
1509 // normalize attribute value (simplify and trim)
1510 int pos = textBuffer.size();
1511 int n = 0;
1512 bool wasSpace = true;
1513 for (int i = 0; i < attribute.value.len; ++i) {
1514 QChar c = textBuffer.at(attribute.value.pos + i);
1515 if (c.unicode() == ' ') {
1516 if (wasSpace)
1517 continue;
1518 wasSpace = true;
1519 } else {
1520 wasSpace = false;
1521 }
1522 textBuffer += textBuffer.at(attribute.value.pos + i);
1523 ++n;
1524 }
1525 if (wasSpace)
1526 while (n && textBuffer.at(pos + n - 1).unicode() == ' ')
1527 --n;
1528 attribute.value.pos = pos;
1529 attribute.value.len = n;
1530 }
1531 if (prefix == QLatin1String("xmlns") && namespaceProcessing) {
1532 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
1533 QStringRef namespacePrefix = symString(attribute.key);
1534 QStringRef namespaceUri = symString(attribute.value);
1535 attributeStack.pop();
1536 if ((namespacePrefix == QLatin1String("xml")
1537 ^ namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))
1538 || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
1539 || namespaceUri.isEmpty()
1540 || namespacePrefix == QLatin1String("xmlns"))
1541 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
1542
1543 namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
1544 namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
1545 }
1546 }
1547 } break;
1548./
1549
1550
1551
1552attribute_list_opt ::= | space | space attribute_list space_opt;
1553attribute_list ::= attribute | attribute_list space attribute;
1554
1555stag_start ::= LANGLE qname;
1556/.
1557 case $rule_number: {
1558 normalizeLiterals = true;
1559 Tag &tag = tagStack_push();
1560 prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2));
1561 name = tag.name = addToStringStorage(symString(2));
1562 qualifiedName = tag.qualifiedName = addToStringStorage(symName(2));
1563 if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name))
1564 raiseWellFormedError(QXmlStream::tr("Invalid XML name."));
1565 } break;
1566./
1567
1568
1569empty_element_tag ::= stag_start attribute_list_opt SLASH RANGLE;
1570/.
1571 case $rule_number:
1572 isEmptyElement = true;
1573 // fall through
1574./
1575
1576
1577stag ::= stag_start attribute_list_opt RANGLE;
1578/.
1579 case $rule_number:
1580 setType(QXmlStreamReader::StartElement);
1581 resolveTag();
1582 if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
1583 raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
1584 hasSeenTag = true;
1585 break;
1586./
1587
1588
1589etag ::= LANGLE SLASH qname space_opt RANGLE;
1590/.
1591 case $rule_number: {
1592 setType(QXmlStreamReader::EndElement);
1593 Tag &tag = tagStack_pop();
1594
1595 namespaceUri = tag.namespaceDeclaration.namespaceUri;
1596 name = tag.name;
1597 qualifiedName = tag.qualifiedName;
1598 if (qualifiedName != symName(3))
1599 raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch."));
1600 } break;
1601./
1602
1603
1604unresolved_entity ::= UNRESOLVED_ENTITY;
1605/.
1606 case $rule_number:
1607 if (entitiesMustBeDeclared()) {
1608 raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity));
1609 break;
1610 }
1611 setType(QXmlStreamReader::EntityReference);
1612 name = &unresolvedEntity;
1613 break;
1614./
1615
1616entity_ref ::= AMPERSAND name SEMICOLON;
1617/.
1618 case $rule_number: {
1619 sym(1).len += sym(2).len + 1;
1620 QString reference = symString(2).toString();
1621 if (entityHash.contains(reference)) {
1622 Entity &entity = entityHash[reference];
1623 if (entity.unparsed) {
1624 raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference));
1625 } else {
1626 if (!entity.hasBeenParsed) {
1627 parseEntity(entity.value);
1628 entity.hasBeenParsed = true;
1629 }
1630 if (entity.literal)
1631 putStringLiteral(entity.value);
1632 else if (referenceEntity(entity))
1633 putReplacement(entity.value);
1634 textBuffer.chop(2 + sym(2).len);
1635 clearSym();
1636 }
1637 break;
1638 }
1639
1640 if (entityResolver) {
1641 QString replacementText = resolveUndeclaredEntity(reference);
1642 if (!replacementText.isNull()) {
1643 putReplacement(replacementText);
1644 textBuffer.chop(2 + sym(2).len);
1645 clearSym();
1646 break;
1647 }
1648 }
1649
1650 injectToken(UNRESOLVED_ENTITY);
1651 unresolvedEntity = symString(2).toString();
1652 textBuffer.chop(2 + sym(2).len);
1653 clearSym();
1654
1655 } break;
1656./
1657
1658pereference ::= PERCENT name SEMICOLON;
1659/.
1660 case $rule_number: {
1661 sym(1).len += sym(2).len + 1;
1662 QString reference = symString(2).toString();
1663 if (parameterEntityHash.contains(reference)) {
1664 referenceToParameterEntityDetected = true;
1665 Entity &entity = parameterEntityHash[reference];
1666 if (entity.unparsed || entity.external) {
1667 referenceToUnparsedEntityDetected = true;
1668 } else {
1669 if (referenceEntity(entity))
1670 putString(entity.value);
1671 textBuffer.chop(2 + sym(2).len);
1672 clearSym();
1673 }
1674 } else if (entitiesMustBeDeclared()) {
1675 raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2).toString()));
1676 }
1677 } break;
1678./
1679
1680
1681
1682entity_ref_in_entity_value ::= AMPERSAND name SEMICOLON;
1683/.
1684 case $rule_number:
1685 sym(1).len += sym(2).len + 1;
1686 break;
1687./
1688
1689entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON;
1690/.
1691 case $rule_number: {
1692 sym(1).len += sym(2).len + 1;
1693 QString reference = symString(2).toString();
1694 if (entityHash.contains(reference)) {
1695 Entity &entity = entityHash[reference];
1696 if (entity.unparsed || entity.value.isNull()) {
1697 raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference));
1698 break;
1699 }
1700 if (!entity.hasBeenParsed) {
1701 parseEntity(entity.value);
1702 entity.hasBeenParsed = true;
1703 }
1704 if (entity.literal)
1705 putStringLiteral(entity.value);
1706 else if (referenceEntity(entity))
1707 putReplacementInAttributeValue(entity.value);
1708 textBuffer.chop(2 + sym(2).len);
1709 clearSym();
1710 break;
1711 }
1712
1713 if (entityResolver) {
1714 QString replacementText = resolveUndeclaredEntity(reference);
1715 if (!replacementText.isNull()) {
1716 putReplacement(replacementText);
1717 textBuffer.chop(2 + sym(2).len);
1718 clearSym();
1719 break;
1720 }
1721 }
1722 if (entitiesMustBeDeclared()) {
1723 raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference));
1724 }
1725 } break;
1726./
1727
1728char_ref ::= AMPERSAND HASH char_ref_value SEMICOLON;
1729/.
1730 case $rule_number: {
1731 if (uint s = resolveCharRef(3)) {
1732 if (s >= 0xffff)
1733 putStringLiteral(QString::fromUcs4(&s, 1));
1734 else
1735 putChar((LETTER << 16) | s);
1736
1737 textBuffer.chop(3 + sym(3).len);
1738 clearSym();
1739 } else {
1740 raiseWellFormedError(QXmlStream::tr("Invalid character reference."));
1741 }
1742 } break;
1743./
1744
1745
1746char_ref_value ::= LETTER | DIGIT;
1747char_ref_value ::= char_ref_value LETTER;
1748/.
1749 case $rule_number:./
1750char_ref_value ::= char_ref_value DIGIT;
1751/.
1752 case $rule_number:
1753 sym(1).len += sym(2).len;
1754 break;
1755./
1756
1757
1758content ::= content character_content;
1759content ::= content stag content etag;
1760content ::= content empty_element_tag;
1761content ::= content comment;
1762content ::= content cdata;
1763content ::= content xml_decl;
1764content ::= content processing_instruction;
1765content ::= content doctype_decl;
1766content ::= content unresolved_entity;
1767content ::= ;
1768
1769
1770space ::= SPACE;
1771/.
1772 case $rule_number:
1773 sym(1).len += fastScanSpace();
1774 if (atEnd) {
1775 resume($rule_number);
1776 return false;
1777 }
1778 break;
1779./
1780
1781
1782space_opt ::=;
1783space_opt ::= space;
1784
1785qname ::= LETTER;
1786/.
1787 case $rule_number: {
1788 sym(1).len += fastScanName(&sym(1).prefix);
1789 if (atEnd) {
1790 resume($rule_number);
1791 return false;
1792 }
1793 } break;
1794./
1795
1796name ::= LETTER;
1797/.
1798 case $rule_number:
1799 sym(1).len += fastScanName();
1800 if (atEnd) {
1801 resume($rule_number);
1802 return false;
1803 }
1804 break;
1805./
1806
1807nmtoken ::= LETTER;
1808/.
1809 case $rule_number:./
1810nmtoken ::= DIGIT;
1811/.
1812 case $rule_number:./
1813nmtoken ::= DOT;
1814/.
1815 case $rule_number:./
1816nmtoken ::= DASH;
1817/.
1818 case $rule_number:./
1819nmtoken ::= COLON;
1820/.
1821 case $rule_number:
1822 sym(1).len += fastScanNMTOKEN();
1823 if (atEnd) {
1824 resume($rule_number);
1825 return false;
1826 }
1827
1828 break;
1829./
1830
1831
1832/.
1833 default:
1834 ;
1835 } // switch
1836 act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT);
1837 if (type != QXmlStreamReader::NoToken)
1838 return true;
1839 } else {
1840 parseError();
1841 break;
1842 }
1843 }
1844 return false;
1845}
1846./
Note: See TracBrowser for help on using the repository browser.