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 >= stack_size-1)
278 Value &val = sym_stack[tos];
280 val.pos = textBuffer.size();
284 textBuffer += QChar(token_char);
286 state_stack[tos] = act;
290 }
else if (act < 0) {
293#if defined (QLALR_DEBUG)
294 int ridx = rule_index[r];
295 printf (
"%3d) %s ::=", r + 1, spell[rule_info[ridx]]);
297 for (
int i = ridx; i < ridx + rhs[r]; ++i) {
298 int symbol = rule_info[i];
299 if (
const char *name = spell[symbol])
300 printf (
" %s", name);
302 printf (
" #%d", symbol);
308 act = state_stack[tos++];
313 setType(QXmlStreamReader::EndDocument);
317 if (type != QXmlStreamReader::Invalid) {
318 if (hasSeenTag || inParseEntity) {
319 setType(QXmlStreamReader::EndDocument);
321 raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr(
"Start tag expected."));
324 state_stack[tos++] = 0;
325 state_stack[tos] = 0;
332 auto reference = entityReferenceStack.pop();
333 auto it = reference.hash->find(reference.name);
334 Q_ASSERT(it != reference.hash->end());
335 it->isCurrentlyReferenced =
false;
336 if (entityReferenceStack.isEmpty())
342 if (!scanString(spell[VERSION], VERSION,
false) && atEnd) {
349 setType(QXmlStreamReader::StartDocument);
350 documentVersion = symString(6);
355 hasExternalDtdSubset =
true;
356 dtdSystemId = symString(2);
360 checkPublicLiteral(symString(2));
361 dtdPublicId = symString(2);
362 dtdSystemId = symString(4);
363 hasExternalDtdSubset =
true;
367 if (!scanPublicOrSystem() && atEnd) {
371 dtdName = symString(3);
376 dtdName = symString(3);
381 setType(QXmlStreamReader::DTD);
394 if (!scanString(spell[EMPTY], EMPTY,
false)
395 && !scanString(spell[ANY], ANY,
false)
403 if (!scanString(spell[PCDATA], PCDATA,
false) && atEnd) {
410 lastAttributeIsCData =
true;
414 if (!scanAfterDefaultDecl() && atEnd) {
422 lastAttributeValue.clear();
423 lastAttributeIsCData =
false;
424 if (!scanAttType() && atEnd) {
431 DtdAttribute &dtdAttribute = dtdAttributes.push();
432 dtdAttribute.tagName.clear();
433 dtdAttribute.isCDATA = lastAttributeIsCData;
434 auto symbol = symQName(1);
435 symbol.resetBackingStorage(addToStringStorage(symbol.all()));
436 dtdAttribute.attributePrefix = symbol.prefix();
437 dtdAttribute.attributeName = symbol.localPart();
438 dtdAttribute.attributeQualifiedName = symbol.qname();
439 dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix ==
"xmlns"_L1
440 || (dtdAttribute.attributePrefix.isEmpty()
441 && dtdAttribute.attributeName ==
"xmlns"_L1));
442 if (lastAttributeValue.isNull()) {
443 dtdAttribute.defaultValue.clear();
445 if (dtdAttribute.isCDATA)
446 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue);
448 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified());
454 if (referenceToUnparsedEntityDetected && !standalone)
456 qsizetype n = dtdAttributes.size();
457 XmlStringRef tagName = addToStringStorage(symName(3));
459 DtdAttribute &dtdAttribute = dtdAttributes[n];
460 if (!dtdAttribute.tagName.isNull())
462 dtdAttribute.tagName = tagName;
463 for (qsizetype i = 0; i < n; ++i) {
464 if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
465 && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
466 dtdAttribute.attributeQualifiedName.clear();
474 if (!scanPublicOrSystem() && atEnd) {
478 EntityDeclaration &entityDeclaration = entityDeclarations.push();
479 entityDeclaration.clear();
480 entityDeclaration.name = symString(3);
484 if (!scanPublicOrSystem() && atEnd) {
488 EntityDeclaration &entityDeclaration = entityDeclarations.push();
489 entityDeclaration.clear();
490 entityDeclaration.name = symString(5);
491 entityDeclaration.parameter =
true;
495 if (!scanNData() && atEnd) {
499 EntityDeclaration &entityDeclaration = entityDeclarations.top();
500 entityDeclaration.systemId = symString(3);
501 entityDeclaration.external =
true;
505 if (!scanNData() && atEnd) {
509 EntityDeclaration &entityDeclaration = entityDeclarations.top();
510 checkPublicLiteral((entityDeclaration.publicId = symString(3)));
511 entityDeclaration.systemId = symString(5);
512 entityDeclaration.external =
true;
516 EntityDeclaration &entityDeclaration = entityDeclarations.top();
517 entityDeclaration.notationName = symString(3);
518 if (entityDeclaration.parameter)
519 raiseWellFormedError(QXmlStream::tr(
"NDATA in parameter entity declaration."));
525 if (referenceToUnparsedEntityDetected && !standalone) {
526 entityDeclarations.pop();
529 EntityDeclaration &entityDeclaration = entityDeclarations.top();
530 if (!entityDeclaration.external)
531 entityDeclaration.value = symString(2);
532 auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
533 if (!hash.contains(entityDeclaration.name)) {
534 Entity entity(entityDeclaration.name.toString(),
535 entityDeclaration.value.toString());
536 entity.unparsed = (!entityDeclaration.notationName.isNull());
537 entity.external = entityDeclaration.external;
538 hash.insert(qToStringViewIgnoringNull(entity.name), entity);
543 setType(QXmlStreamReader::ProcessingInstruction);
544 const qsizetype pos = sym(4).pos + sym(4).len;
545 processingInstructionTarget = symString(3);
546 if (scanUntil(
"?>")) {
547 processingInstructionData = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
548 if (!processingInstructionTarget.view().compare(
"xml"_L1, Qt::CaseInsensitive)) {
549 raiseWellFormedError(QXmlStream::tr(
"XML declaration not at start of document."));
551 else if (!QXmlUtils::isNCName(processingInstructionTarget))
552 raiseWellFormedError(QXmlStream::tr(
"%1 is an invalid processing instruction name.")
553 .arg(processingInstructionTarget));
554 }
else if (type != QXmlStreamReader::Invalid){
561 setType(QXmlStreamReader::ProcessingInstruction);
562 processingInstructionTarget = symString(3);
563 if (!processingInstructionTarget.view().compare(
"xml"_L1, Qt::CaseInsensitive))
564 raiseWellFormedError(QXmlStream::tr(
"Invalid processing instruction name."));
568 if (!scanAfterLangleBang() && atEnd) {
575 if (!scanUntil(
"--")) {
582 setType(QXmlStreamReader::Comment);
583 const qsizetype pos = sym(1).pos + 4;
584 text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
588 setType(QXmlStreamReader::Characters);
590 isWhitespace =
false;
591 const qsizetype pos = sym(2).pos;
592 if (scanUntil(
"]]>", -1)) {
593 text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
601 if (!scanPublicOrSystem() && atEnd) {
605 NotationDeclaration ¬ationDeclaration = notationDeclarations.push();
606 notationDeclaration.name = symString(3);
610 NotationDeclaration ¬ationDeclaration = notationDeclarations.top();
611 notationDeclaration.systemId = symString(3);
612 notationDeclaration.publicId.clear();
616 NotationDeclaration ¬ationDeclaration = notationDeclarations.top();
617 notationDeclaration.systemId.clear();
618 checkPublicLiteral((notationDeclaration.publicId = symString(3)));
622 NotationDeclaration ¬ationDeclaration = notationDeclarations.top();
623 checkPublicLiteral((notationDeclaration.publicId = symString(3)));
624 notationDeclaration.systemId = symString(5);
628 isWhitespace =
false;
632 sym(1).len += fastScanContentCharList();
633 if (atEnd && !inParseEntity) {
640 if (!textBuffer.isEmpty()) {
641 setType(QXmlStreamReader::Characters);
660 sym(1).len += sym(2).len;
664 if (normalizeLiterals)
665 textBuffer.data()[textBuffer.size()-1] = u' ';
669 sym(1).len += fastScanLiteralContent();
677 if (!QXmlUtils::isPublicID(symString(1))) {
678 raiseWellFormedError(QXmlStream::tr(
"%1 is an invalid PUBLIC identifier.").arg(symString(1)));
698 sym(1).len += sym(2).len;
709 lastAttributeValue = symString(1);
716 sym(1).len += sym(2).len;
720 const XmlStringRef prfx = symPrefix(1);
721 if (prfx.isEmpty() && symString(1) ==
"xmlns"_L1 && namespaceProcessing) {
722 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
723 namespaceDeclaration.prefix.clear();
725 const XmlStringRef ns(symString(5));
726 if (ns.view() ==
"http://www.w3.org/2000/xmlns/"_L1 ||
727 ns.view() ==
"http://www.w3.org/XML/1998/namespace"_L1)
728 raiseWellFormedError(QXmlStream::tr(
"Illegal namespace declaration."));
730 namespaceDeclaration.namespaceUri = addToStringStorage(ns);
732 Attribute &attribute = attributeStack.push();
733 attribute.key = sym(1);
734 attribute.value = sym(5);
736 XmlStringRef attributeQualifiedName = symName(1);
737 bool normalize =
false;
738 for (
const DtdAttribute &dtdAttribute : std::as_const(dtdAttributes)) {
739 if (!dtdAttribute.isCDATA
740 && dtdAttribute.tagName == qualifiedName
741 && dtdAttribute.attributeQualifiedName == attributeQualifiedName
749 const qsizetype pos = textBuffer.size();
751 bool wasSpace =
true;
752 for (qsizetype i = 0; i < attribute.value.len; ++i) {
753 QChar c = textBuffer.at(attribute.value.pos + i);
754 if (c.unicode() ==
' ') {
761 textBuffer += textBuffer.at(attribute.value.pos + i);
765 while (n && textBuffer.at(pos + n - 1).unicode() ==
' ')
767 attribute.value.pos = pos;
768 attribute.value.len = n;
770 if (prfx ==
"xmlns"_L1 && namespaceProcessing) {
771 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
772 XmlStringRef namespacePrefix = symString(attribute.key);
773 XmlStringRef namespaceUri = symString(attribute.value);
774 attributeStack.pop();
775 if (((namespacePrefix ==
"xml"_L1)
776 ^ (namespaceUri ==
"http://www.w3.org/XML/1998/namespace"_L1))
777 || namespaceUri ==
"http://www.w3.org/2000/xmlns/"_L1
778 || namespaceUri.isEmpty()
779 || namespacePrefix ==
"xmlns"_L1)
780 raiseWellFormedError(QXmlStream::tr(
"Illegal namespace declaration."));
782 namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
783 namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
789 normalizeLiterals =
true;
790 Tag &tag = tagStack_push();
791 auto symbol = symQName(2);
792 symbol.resetBackingStorage(addToStringStorage(symbol.all()));
793 prefix = tag.namespaceDeclaration.prefix = symbol.prefix();
794 name = tag.name = symbol.localPart();
795 qualifiedName = tag.qualifiedName = symbol.qname();
796 if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name))
797 raiseWellFormedError(QXmlStream::tr(
"Invalid XML name."));
801 isEmptyElement =
true;
805 setType(QXmlStreamReader::StartElement);
807 if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
808 raiseWellFormedError(QXmlStream::tr(
"Extra content at end of document."));
813 setType(QXmlStreamReader::EndElement);
814 Tag tag = tagStack_pop();
816 namespaceUri = tag.namespaceDeclaration.namespaceUri;
817 prefix = tag.namespaceDeclaration.prefix;
819 qualifiedName = tag.qualifiedName;
820 if (qualifiedName != symName(3))
821 raiseWellFormedError(QXmlStream::tr(
"Opening and ending tag mismatch."));
825 if (entitiesMustBeDeclared()) {
826 raiseWellFormedError(QXmlStream::tr(
"Entity '%1' not declared.").arg(unresolvedEntity));
829 setType(QXmlStreamReader::EntityReference);
830 name = &unresolvedEntity;
834 sym(1).len += sym(2).len + 1;
835 QStringView reference = symView(2);
836 if (
const auto it = entityHash.find(reference); it != entityHash.end()) {
837 Entity &entity = *it;
838 if (entity.unparsed) {
839 raiseWellFormedError(QXmlStream::tr(
"Reference to unparsed entity '%1'.").arg(reference));
841 if (!entity.hasBeenParsed) {
842 parseEntity(entity.value);
843 entity.hasBeenParsed =
true;
846 putStringLiteral(entity.value);
847 else if (referenceEntity(&entityHash, entity))
848 putReplacement(entity.value);
849 textBuffer.chop(2 + sym(2).len);
855 if (entityResolver) {
856 QString replacementText = resolveUndeclaredEntity(reference.toString());
857 if (!replacementText.isNull()) {
858 putReplacement(replacementText);
859 textBuffer.chop(2 + sym(2).len);
865 injectToken(UNRESOLVED_ENTITY);
866 unresolvedEntity = symString(2).toString();
867 textBuffer.chop(2 + sym(2).len);
873 sym(1).len += sym(2).len + 1;
874 QStringView reference = symView(2);
875 if (
const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) {
876 referenceToParameterEntityDetected =
true;
877 Entity &entity = *it;
878 if (entity.unparsed || entity.external) {
879 referenceToUnparsedEntityDetected =
true;
881 if (referenceEntity(¶meterEntityHash, entity))
882 putString(entity.value);
883 textBuffer.chop(2 + sym(2).len);
886 }
else if (entitiesMustBeDeclared()) {
887 raiseWellFormedError(QXmlStream::tr(
"Entity '%1' not declared.").arg(symString(2)));
892 sym(1).len += sym(2).len + 1;
896 sym(1).len += sym(2).len + 1;
897 QStringView reference = symView(2);
898 if (
const auto it = entityHash.find(reference); it != entityHash.end()) {
899 Entity &entity = *it;
900 if (entity.unparsed || entity.value.isNull()) {
901 raiseWellFormedError(QXmlStream::tr(
"Reference to external entity '%1' in attribute value.").arg(reference));
904 if (!entity.hasBeenParsed) {
905 parseEntity(entity.value);
906 entity.hasBeenParsed =
true;
909 putStringLiteral(entity.value);
910 else if (referenceEntity(&entityHash, entity))
911 putReplacementInAttributeValue(entity.value);
912 textBuffer.chop(2 + sym(2).len);
917 if (entityResolver) {
918 QString replacementText = resolveUndeclaredEntity(reference.toString());
919 if (!replacementText.isNull()) {
920 putReplacement(replacementText);
921 textBuffer.chop(2 + sym(2).len);
926 if (entitiesMustBeDeclared()) {
927 raiseWellFormedError(QXmlStream::tr(
"Entity '%1' not declared.").arg(reference));
932 if (
char32_t s = resolveCharRef(3)) {
933 putStringLiteral(QChar::fromUcs4(s));
934 textBuffer.chop(3 + sym(3).len);
937 raiseWellFormedError(QXmlStream::tr(
"Invalid character reference."));
943 sym(1).len += sym(2).len;
947 sym(1).len += fastScanSpace();
956 if (
auto res = fastScanName(&val))
968 if (
auto res = fastScanName())
984 sym(1).len += fastScanNMTOKEN();
995 act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT);
996 if (type != QXmlStreamReader::NoToken)
Combined button and popup list for selecting options.