29#include <QtCore/private/qglobal_p.h>
30#include <qxmlstream.h>
33#include <qstringconverter.h>
37#ifndef QXMLSTREAMPARSER_P_H
38#define QXMLSTREAMPARSER_P_H
42#if QT_CONFIG(xmlstreamreader)
44bool QXmlStreamReaderPrivate::parse()
48 using namespace Qt::StringLiterals;
51 case QXmlStreamReader::StartElement:
54 qualifiedName.clear();
56 publicNamespaceDeclarations.clear();
59 setType(QXmlStreamReader::EndElement);
60 Tag tag = tagStack_pop();
61 namespaceUri = tag.namespaceDeclaration.namespaceUri;
62 prefix = tag.namespaceDeclaration.prefix;
64 qualifiedName = tag.qualifiedName;
65 isEmptyElement =
false;
70 case QXmlStreamReader::EndElement:
73 qualifiedName.clear();
77 case QXmlStreamReader::DTD:
78 publicNotationDeclarations.clear();
79 publicEntityDeclarations.clear();
84 case QXmlStreamReader::Comment:
85 case QXmlStreamReader::Characters:
91 case QXmlStreamReader::EntityReference:
96 case QXmlStreamReader::ProcessingInstruction:
97 processingInstructionTarget.clear();
98 processingInstructionData.clear();
101 case QXmlStreamReader::NoToken:
102 case QXmlStreamReader::Invalid:
104 case QXmlStreamReader::StartDocument:
106 documentVersion.clear();
107 documentEncoding.clear();
108 if (decoder.isValid() && decoder.hasError()) {
109 raiseWellFormedError(QXmlStream::tr(
"Encountered incorrectly encoded content."));
119 setType(QXmlStreamReader::NoToken);
125 if (resumeReduction) {
126 act = state_stack[tos-1];
129 goto ResumeReduction;
132 act = state_stack[tos];
135 if (token == -1 && - TERMINAL_COUNT != action_index[act]) {
138 token_char = cu == ~0U ? cu : ushort(cu);
139 if ((cu != ~0U) && (cu & 0xff0000)) {
141 }
else switch (token_char) {
149 if ((token_char = filterCarriageReturn())) {
151 lastLineStart = characterOffset + readBufferPos;
160 if (!tagsDone && !inParseEntity) {
161 int a = t_action(act, token);
163 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
171 lastLineStart = characterOffset + readBufferPos;
241 token = QUESTIONMARK;
267 act = t_action (act, token);
268 if (act == ACCEPT_STATE) {
271 state_stack[tos++] = 0;
272 state_stack[tos] = 0;
274 }
else if (act > 0) {
275 if (tos + 1 >= stack_size - 1)
279 Value &val = sym_stack[tos];
281 val.pos = textBuffer.size();
285 textBuffer += QChar(token_char);
287 state_stack[tos] = act;
291 }
else if (act < 0) {
294#if defined (QLALR_DEBUG)
295 int ridx = rule_index[r];
296 printf (
"%3d) %s ::=", r + 1, spell[rule_info[ridx]]);
298 for (
int i = ridx; i < ridx + rhs[r]; ++i) {
299 int symbol = rule_info[i];
300 if (
const char *name = spell[symbol])
301 printf (
" %s", name);
303 printf (
" #%d", symbol);
309 act = state_stack[tos++];
314 setType(QXmlStreamReader::EndDocument);
318 if (type != QXmlStreamReader::Invalid) {
319 if (hasSeenTag || inParseEntity) {
320 setType(QXmlStreamReader::EndDocument);
322 raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr(
"Start tag expected."));
325 state_stack[tos++] = 0;
326 state_stack[tos] = 0;
333 auto reference = entityReferenceStack.pop();
334 auto it = reference.hash->find(reference.name);
335 Q_ASSERT(it != reference.hash->end());
336 it->isCurrentlyReferenced =
false;
337 if (entityReferenceStack.isEmpty())
343 if (!scanString(spell[VERSION], VERSION,
false) && atEnd) {
350 setType(QXmlStreamReader::StartDocument);
351 documentVersion = symString(6);
356 hasExternalDtdSubset =
true;
357 dtdSystemId = symString(2);
361 checkPublicLiteral(symString(2));
362 dtdPublicId = symString(2);
363 dtdSystemId = symString(4);
364 hasExternalDtdSubset =
true;
368 if (!scanPublicOrSystem() && atEnd) {
372 dtdName = symString(3);
377 dtdName = symString(3);
382 setType(QXmlStreamReader::DTD);
395 if (!scanString(spell[EMPTY], EMPTY,
false)
396 && !scanString(spell[ANY], ANY,
false)
404 if (!scanString(spell[PCDATA], PCDATA,
false) && atEnd) {
411 lastAttributeIsCData =
true;
415 if (!scanAfterDefaultDecl() && atEnd) {
423 lastAttributeValue.clear();
424 lastAttributeIsCData =
false;
425 if (!scanAttType() && atEnd) {
432 DtdAttribute &dtdAttribute = dtdAttributes.push();
433 dtdAttribute.tagName.clear();
434 dtdAttribute.isCDATA = lastAttributeIsCData;
435 auto symbol = symQName(1);
436 symbol.resetBackingStorage(addToStringStorage(symbol.all()));
437 dtdAttribute.attributePrefix = symbol.prefix();
438 dtdAttribute.attributeName = symbol.localPart();
439 dtdAttribute.attributeQualifiedName = symbol.qname();
440 dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix ==
"xmlns"_L1
441 || (dtdAttribute.attributePrefix.isEmpty()
442 && dtdAttribute.attributeName ==
"xmlns"_L1));
443 if (lastAttributeValue.isNull()) {
444 dtdAttribute.defaultValue.clear();
446 if (dtdAttribute.isCDATA)
447 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue);
449 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified());
455 if (referenceToUnparsedEntityDetected && !standalone)
457 qsizetype n = dtdAttributes.size();
458 XmlStringRef tagName = addToStringStorage(symName(3));
460 DtdAttribute &dtdAttribute = dtdAttributes[n];
461 if (!dtdAttribute.tagName.isNull())
463 dtdAttribute.tagName = tagName;
464 for (qsizetype i = 0; i < n; ++i) {
465 if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
466 && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
467 dtdAttribute.attributeQualifiedName.clear();
475 if (!scanPublicOrSystem() && atEnd) {
479 EntityDeclaration &entityDeclaration = entityDeclarations.push();
480 entityDeclaration.clear();
481 entityDeclaration.name = symString(3);
485 if (!scanPublicOrSystem() && atEnd) {
489 EntityDeclaration &entityDeclaration = entityDeclarations.push();
490 entityDeclaration.clear();
491 entityDeclaration.name = symString(5);
492 entityDeclaration.parameter =
true;
496 if (!scanNData() && atEnd) {
500 EntityDeclaration &entityDeclaration = entityDeclarations.top();
501 entityDeclaration.systemId = symString(3);
502 entityDeclaration.external =
true;
506 if (!scanNData() && atEnd) {
510 EntityDeclaration &entityDeclaration = entityDeclarations.top();
511 checkPublicLiteral((entityDeclaration.publicId = symString(3)));
512 entityDeclaration.systemId = symString(5);
513 entityDeclaration.external =
true;
517 EntityDeclaration &entityDeclaration = entityDeclarations.top();
518 entityDeclaration.notationName = symString(3);
519 if (entityDeclaration.parameter)
520 raiseWellFormedError(QXmlStream::tr(
"NDATA in parameter entity declaration."));
526 if (referenceToUnparsedEntityDetected && !standalone) {
527 entityDeclarations.pop();
530 EntityDeclaration &entityDeclaration = entityDeclarations.top();
531 if (!entityDeclaration.external)
532 entityDeclaration.value = symString(2);
533 auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
534 if (!hash.contains(entityDeclaration.name)) {
535 Entity entity(entityDeclaration.name.toString(),
536 entityDeclaration.value.toString());
537 entity.unparsed = (!entityDeclaration.notationName.isNull());
538 entity.external = entityDeclaration.external;
539 hash.insert(qToStringViewIgnoringNull(entity.name), entity);
544 setType(QXmlStreamReader::ProcessingInstruction);
545 const qsizetype pos = sym(4).pos + sym(4).len;
546 processingInstructionTarget = symString(3);
547 if (scanUntil(
"?>")) {
548 processingInstructionData = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
549 if (!processingInstructionTarget.view().compare(
"xml"_L1, Qt::CaseInsensitive)) {
550 raiseWellFormedError(QXmlStream::tr(
"XML declaration not at start of document."));
552 else if (!QXmlUtils::isNCName(processingInstructionTarget))
553 raiseWellFormedError(QXmlStream::tr(
"%1 is an invalid processing instruction name.")
554 .arg(processingInstructionTarget));
555 }
else if (type != QXmlStreamReader::Invalid){
562 setType(QXmlStreamReader::ProcessingInstruction);
563 processingInstructionTarget = symString(3);
564 if (!processingInstructionTarget.view().compare(
"xml"_L1, Qt::CaseInsensitive))
565 raiseWellFormedError(QXmlStream::tr(
"Invalid processing instruction name."));
569 if (!scanAfterLangleBang() && atEnd) {
576 if (!scanUntil(
"--")) {
583 setType(QXmlStreamReader::Comment);
584 const qsizetype pos = sym(1).pos + 4;
585 text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
589 setType(QXmlStreamReader::Characters);
591 isWhitespace =
false;
592 const qsizetype pos = sym(2).pos;
593 if (scanUntil(
"]]>", -1)) {
594 text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
602 if (!scanPublicOrSystem() && atEnd) {
606 NotationDeclaration ¬ationDeclaration = notationDeclarations.push();
607 notationDeclaration.name = symString(3);
611 NotationDeclaration ¬ationDeclaration = notationDeclarations.top();
612 notationDeclaration.systemId = symString(3);
613 notationDeclaration.publicId.clear();
617 NotationDeclaration ¬ationDeclaration = notationDeclarations.top();
618 notationDeclaration.systemId.clear();
619 checkPublicLiteral((notationDeclaration.publicId = symString(3)));
623 NotationDeclaration ¬ationDeclaration = notationDeclarations.top();
624 checkPublicLiteral((notationDeclaration.publicId = symString(3)));
625 notationDeclaration.systemId = symString(5);
629 isWhitespace =
false;
633 sym(1).len += fastScanContentCharList();
634 if (atEnd && !inParseEntity) {
641 if (!textBuffer.isEmpty()) {
642 setType(QXmlStreamReader::Characters);
661 sym(1).len += sym(2).len;
665 if (normalizeLiterals)
666 textBuffer.data()[textBuffer.size()-1] = u' ';
670 sym(1).len += fastScanLiteralContent();
678 if (!QXmlUtils::isPublicID(symString(1))) {
679 raiseWellFormedError(QXmlStream::tr(
"%1 is an invalid PUBLIC identifier.").arg(symString(1)));
699 sym(1).len += sym(2).len;
710 lastAttributeValue = symString(1);
717 sym(1).len += sym(2).len;
721 const XmlStringRef prfx = symPrefix(1);
722 if (prfx.isEmpty() && symString(1) ==
"xmlns"_L1 && namespaceProcessing) {
723 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
724 namespaceDeclaration.prefix.clear();
726 const XmlStringRef ns(symString(5));
727 if (ns.view() ==
"http://www.w3.org/2000/xmlns/"_L1 ||
728 ns.view() ==
"http://www.w3.org/XML/1998/namespace"_L1)
729 raiseWellFormedError(QXmlStream::tr(
"Illegal namespace declaration."));
731 namespaceDeclaration.namespaceUri = addToStringStorage(ns);
733 Attribute &attribute = attributeStack.push();
734 attribute.key = sym(1);
735 attribute.value = sym(5);
737 XmlStringRef attributeQualifiedName = symName(1);
738 bool normalize =
false;
739 for (
const DtdAttribute &dtdAttribute : std::as_const(dtdAttributes)) {
740 if (!dtdAttribute.isCDATA
741 && dtdAttribute.tagName == qualifiedName
742 && dtdAttribute.attributeQualifiedName == attributeQualifiedName
750 const qsizetype pos = textBuffer.size();
752 bool wasSpace =
true;
753 for (qsizetype i = 0; i < attribute.value.len; ++i) {
754 QChar c = textBuffer.at(attribute.value.pos + i);
755 if (c.unicode() ==
' ') {
762 textBuffer += textBuffer.at(attribute.value.pos + i);
766 while (n && textBuffer.at(pos + n - 1).unicode() ==
' ')
768 attribute.value.pos = pos;
769 attribute.value.len = n;
771 if (prfx ==
"xmlns"_L1 && namespaceProcessing) {
772 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
773 XmlStringRef namespacePrefix = symString(attribute.key);
774 XmlStringRef namespaceUri = symString(attribute.value);
775 attributeStack.pop();
776 if (((namespacePrefix ==
"xml"_L1)
777 ^ (namespaceUri ==
"http://www.w3.org/XML/1998/namespace"_L1))
778 || namespaceUri ==
"http://www.w3.org/2000/xmlns/"_L1
779 || namespaceUri.isEmpty()
780 || namespacePrefix ==
"xmlns"_L1)
781 raiseWellFormedError(QXmlStream::tr(
"Illegal namespace declaration."));
783 namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
784 namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
790 normalizeLiterals =
true;
791 Tag &tag = tagStack_push();
792 auto symbol = symQName(2);
793 symbol.resetBackingStorage(addToStringStorage(symbol.all()));
794 prefix = tag.namespaceDeclaration.prefix = symbol.prefix();
795 name = tag.name = symbol.localPart();
796 qualifiedName = tag.qualifiedName = symbol.qname();
797 if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name))
798 raiseWellFormedError(QXmlStream::tr(
"Invalid XML name."));
802 isEmptyElement =
true;
806 setType(QXmlStreamReader::StartElement);
808 if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
809 raiseWellFormedError(QXmlStream::tr(
"Extra content at end of document."));
814 setType(QXmlStreamReader::EndElement);
815 Tag tag = tagStack_pop();
817 namespaceUri = tag.namespaceDeclaration.namespaceUri;
818 prefix = tag.namespaceDeclaration.prefix;
820 qualifiedName = tag.qualifiedName;
821 if (qualifiedName != symName(3))
822 raiseWellFormedError(QXmlStream::tr(
"Opening and ending tag mismatch."));
826 if (entitiesMustBeDeclared()) {
827 raiseWellFormedError(QXmlStream::tr(
"Entity '%1' not declared.").arg(unresolvedEntity));
830 setType(QXmlStreamReader::EntityReference);
831 name = &unresolvedEntity;
835 sym(1).len += sym(2).len + 1;
836 QStringView reference = symView(2);
837 if (
const auto it = entityHash.find(reference); it != entityHash.end()) {
838 Entity &entity = *it;
839 if (entity.unparsed) {
840 raiseWellFormedError(QXmlStream::tr(
"Reference to unparsed entity '%1'.").arg(reference));
842 if (!entity.hasBeenParsed) {
843 parseEntity(entity.value);
844 entity.hasBeenParsed =
true;
847 putStringLiteral(entity.value);
848 else if (referenceEntity(&entityHash, entity))
849 putReplacement(entity.value);
850 textBuffer.chop(2 + sym(2).len);
856 if (entityResolver) {
857 QString replacementText = resolveUndeclaredEntity(reference.toString());
858 if (!replacementText.isNull()) {
859 putReplacement(replacementText);
860 textBuffer.chop(2 + sym(2).len);
866 injectToken(UNRESOLVED_ENTITY);
867 unresolvedEntity = symString(2).toString();
868 textBuffer.chop(2 + sym(2).len);
874 sym(1).len += sym(2).len + 1;
875 QStringView reference = symView(2);
876 if (
const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) {
877 referenceToParameterEntityDetected =
true;
878 Entity &entity = *it;
879 if (entity.unparsed || entity.external) {
880 referenceToUnparsedEntityDetected =
true;
882 if (referenceEntity(¶meterEntityHash, entity))
883 putString(entity.value);
884 textBuffer.chop(2 + sym(2).len);
887 }
else if (entitiesMustBeDeclared()) {
888 raiseWellFormedError(QXmlStream::tr(
"Entity '%1' not declared.").arg(symString(2)));
893 sym(1).len += sym(2).len + 1;
897 sym(1).len += sym(2).len + 1;
898 QStringView reference = symView(2);
899 if (
const auto it = entityHash.find(reference); it != entityHash.end()) {
900 Entity &entity = *it;
901 if (entity.unparsed || entity.value.isNull()) {
902 raiseWellFormedError(QXmlStream::tr(
"Reference to external entity '%1' in attribute value.").arg(reference));
905 if (!entity.hasBeenParsed) {
906 parseEntity(entity.value);
907 entity.hasBeenParsed =
true;
910 putStringLiteral(entity.value);
911 else if (referenceEntity(&entityHash, entity))
912 putReplacementInAttributeValue(entity.value);
913 textBuffer.chop(2 + sym(2).len);
918 if (entityResolver) {
919 QString replacementText = resolveUndeclaredEntity(reference.toString());
920 if (!replacementText.isNull()) {
921 putReplacement(replacementText);
922 textBuffer.chop(2 + sym(2).len);
927 if (entitiesMustBeDeclared()) {
928 raiseWellFormedError(QXmlStream::tr(
"Entity '%1' not declared.").arg(reference));
933 if (
char32_t s = resolveCharRef(3)) {
934 putStringLiteral(QChar::fromUcs4(s));
935 textBuffer.chop(3 + sym(3).len);
938 raiseWellFormedError(QXmlStream::tr(
"Invalid character reference."));
944 sym(1).len += sym(2).len;
948 sym(1).len += fastScanSpace();
957 if (
auto res = fastScanName(&val))
969 if (
auto res = fastScanName())
985 sym(1).len += fastScanNMTOKEN();
996 act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT);
997 if (type != QXmlStreamReader::NoToken)
Combined button and popup list for selecting options.