parseInstance.cxx revision 7c478bd95313f5f23a4c958a745db2134aa03244
// Copyright (c) 1994 James Clark
// See the file COPYING for copying permission.
#pragma ident "%Z%%M% %I% %E% SMI"
#include "splib.h"
#include "Parser.h"
#include "ParserMessages.h"
#include "MessageArg.h"
#include "TokenMessageArg.h"
#include "StringVectorMessageArg.h"
#include "token.h"
#include "macros.h"
#ifdef SP_NAMESPACE
namespace SP_NAMESPACE {
#endif
void Parser::doInstanceStart()
{
if (cancelled()) {
allDone();
return;
}
// FIXME check here that we have a valid dtd
switch (token) {
case tokenEe:
case tokenStagoNameStart:
case tokenStagoTagc:
case tokenStagoGrpo:
case tokenEtagoNameStart:
case tokenEtagoTagc:
case tokenEtagoGrpo:
break;
default:
unsigned startImpliedCount = 0;
unsigned attributeListIndex = 0;
if (!tryImplyTag(currentLocation(),
}
else
}
currentInput()->ungetToken();
}
void Parser::endInstance()
{
// Do checking before popping entity stack so that there's a
// current location for error messages.
while (markedSectionLevel() > 0) {
}
checkIdrefs();
allDone();
}
void Parser::checkIdrefs()
{
}
}
}
{
do {
if (cancelled()) {
allDone();
return;
}
switch (token) {
case tokenEe:
if (inputLevel() == 1) {
endInstance();
return;
}
if (inputLevel() == specialParseInputLevel()) {
// FIXME have separate messages for each type of special parse
// perhaps force end of marked section or element
}
if (eventsWanted().wantInstanceMarkup())
if (afterDocumentElement())
if (sd().integrallyStored()
&& tagLevel()
break;
case tokenCroDigit:
case tokenHcroHexDigit:
{
if (afterDocumentElement())
noteData();
break;
if (!isSgmlChar) {
break;
}
break;
}
}
break;
case tokenCroNameStart:
if (afterDocumentElement())
break;
case tokenEroGrpo:
case tokenEroNameStart:
{
if (afterDocumentElement())
if (entity->isCharacterData())
if (inputLevel() == specialParseInputLevel())
else
}
}
}
break;
case tokenEtagoNameStart:
break;
case tokenEtagoTagc:
break;
case tokenEtagoGrpo:
break;
case tokenMdoNameStart:
unsigned startLevel;
startLevel = inputLevel();
if (parseDeclarationName(&name)) {
switch (name) {
if (afterDocumentElement())
result = parseUsemapDecl();
break;
if (afterDocumentElement())
result = parseUselinkDecl();
break;
result = 0;
break;
default:
result = 0;
break;
}
}
else
result = 0;
if (!result)
noteMarkup();
break;
case tokenMdoMdc:
// empty comment
noteMarkup();
break;
case tokenMdoCom:
noteMarkup();
break;
case tokenMdoDso:
if (afterDocumentElement())
noteMarkup();
break;
case tokenMscMdc:
noteMarkup();
break;
case tokenNet:
break;
case tokenPio:
break;
case tokenStagoNameStart:
break;
case tokenStagoTagc:
break;
case tokenStagoGrpo:
break;
case tokenRe:
break;
case tokenRs:
noteRs();
if (eventsWanted().wantInstanceMarkup())
currentLocation()));
break;
case tokenS:
if (eventsWanted().wantInstanceMarkup())
0));
break;
case tokenIgnoredChar:
extendData();
if (eventsWanted().wantMarkedSections())
0));
break;
case tokenUnrecognized:
parsePcdata();
break;
case tokenCharDelim:
currentInput()->currentTokenLength())));
// fall through
case tokenChar:
parsePcdata();
break;
default:
break;
}
} while (eventQueueEmpty());
}
{
const unsigned skipMax = 250;
unsigned skipCount = 0;
for (;;) {
if (inputLevel() == startLevel)
skipCount++;
switch (token) {
case tokenUnrecognized:
(void)getChar();
break;
case tokenEe:
if (inputLevel() <= startLevel)
return;
return;
case tokenMdc:
if (inputLevel() == startLevel)
return;
break;
case tokenS:
return;
break;
default:
break;
}
}
}
{
if (eventsWanted().wantInstanceMarkup()) {
}
return;
}
size_t i = 0;
// FIXME do this in advance (what about B sequence?)
;
if (i > 0 && eventsWanted().wantInstanceMarkup())
SSepEvent(s, i, currentLocation(), 0));
}
if (i < length) {
location += i;
s += i;
length -= i;
noteData();
location, 0));
return;
}
// FIXME speed this up
noteRs();
if (eventsWanted().wantInstanceMarkup())
IgnoredRsEvent(*s, location));
}
else {
noteData();
location, 0));
}
}
}
}
void Parser::parsePcdata()
{
extendData();
noteData();
0));
}
void Parser::parseStartTag()
{
in->currentLocation());
in->discardInitial();
if (markup) {
}
if (!e)
e = completeRankStem(name);
else if (e->isRankedElement())
}
if (!e)
if (closeToken == tokenTagc) {
attributes->finish(*this);
netEnabling = 0;
if (markup)
}
else {
in->ungetToken();
// The difference between the indices will be the difference
// in offsets plus 1 for each named character reference.
}
else
netEnabling = 0;
e->setAttributeDef(newAttDef);
}
}
new (eventAllocator())
markup),
}
{
if (rankStem) {
else
}
return 0;
}
{
}
}
{
const InputSourceOrigin *origin
}
void Parser::parseEmptyStartTag()
{
if (options().warnEmptyTag)
// FIXME error if not in base.
const ElementType *e = 0;
e = lastEndedElementType();
else if (tagLevel() > 0)
e = currentElement().type();
if (!e)
e = currentDtd().documentElementType();
attributes->finish(*this);
currentLocation());
if (markup) {
}
new (eventAllocator())
markup),
0);
}
void Parser::parseGroupStartTag()
{
}
if (!parseTagNameGroup(active))
return;
// Location startLocation = in->currentLocation();
in->startToken();
if (!syntax().isNameStartCharacter(c)) {
return;
}
in->discardInitial();
if (currentMarkup())
if (currentMarkup())
currentMarkup()));
noteMarkup();
}
void Parser::parseGroupEndTag()
{
}
if (!parseTagNameGroup(active))
return;
// Location startLocation = in->currentLocation();
in->startToken();
if (!syntax().isNameStartCharacter(c)) {
return;
}
in->discardInitial();
if (currentMarkup())
if (currentMarkup())
currentMarkup()));
noteMarkup();
}
{
if (currentElement().tryTransitionPcdata())
return;
// Need to test here since implying tags may turn off pcdataRecovering.
if (pcdataRecovering())
return;
unsigned startImpliedCount = 0;
unsigned attributeListIndex = 0;
keepMessages();
if (currentElement().tryTransitionPcdata()) {
return;
}
if (validate() || afterDocumentElement())
}
{
if (elementIsExcluded(e)) {
keepMessages();
if (validate())
checkExclusion(e);
}
else {
if (currentElement().tryTransition(e)) {
return;
}
if (elementIsIncluded(e)) {
event->setIncluded();
return;
}
keepMessages();
}
unsigned startImpliedCount = 0;
unsigned attributeListIndex = 1;
return;
else {
// If element couldn't occur because it was excluded, then
// do the transition here.
(void)currentElement().tryTransition(e);
}
}
{
p->undo(this);
delete p;
}
}
{
// FIXME provide IList<T>::reverse function
// reverse it
}
else {
}
}
}
{
if (token)
}
{
if (elementIsExcluded(e)) {
checkExclusion(e);
return 0;
}
if (currentElement().tryTransition(e)) {
return 1;
}
if (elementIsIncluded(e)) {
event->setIncluded();
return 1;
}
return 0;
}
unsigned &startImpliedCount,
unsigned &attributeListIndex,
{
return 0;
if (currentElement().isFinished()) {
if (tagLevel() == 0)
return 0;
#if 1
return 0;
#endif
// imply an end tag
if (startImpliedCount > 0) {
}
#if 0
currentElement().startLocation());
#endif
loc,
0);
return 1;
}
if (!token)
return 0;
if (elementIsExcluded(e))
StringMessageArg(e->name()),
if (tagLevel() != 0)
StringMessageArg(e->name()));
else if (!def->canOmitStartTag())
= allocAttributeList(e->attributeDef(),
// this will give an error if the element has a required attribute
attributes->finish(*this);
= new (eventAllocator()) StartElementEvent(e,
loc,
0);
return 0;
return 1;
}
{
if (event->mustOmitEnd()) {
if (sd().emptyElementNormal()) {
}
else {
= new (eventAllocator()) EndElementEvent(e,
0);
end->setIncluded();
noteEndElement(1);
}
else
noteEndElement(0);
}
}
else {
if (!map)
map,
// Can't access event after it's passed to the event handler.
}
}
{
switch (token) {
case tokenNet:
if (netEnabling) {
currentLocation());
if (markup)
= new (eventAllocator()) EndElementEvent(e,
markup);
if (included)
end->setIncluded();
return;
}
break;
case tokenEtagoTagc:
{
if (options().warnEmptyTag)
currentLocation());
if (markup) {
}
= new (eventAllocator()) EndElementEvent(e,
markup);
if (included)
end->setIncluded();
return;
}
case tokenEtagoNameStart:
{
if (end->elementType() == e) {
if (included)
end->setIncluded();
return;
}
delete end;
break;
}
return;
}
default:
break;
}
currentInput()->ungetToken();
}
{
StringMessageArg(e->name()),
startLoc);
else {
StringMessageArg(e->name()),
startLoc);
}
= new (eventAllocator()) EndElementEvent(e,
0);
if (included)
end->setIncluded();
}
{
if (event->mustOmitEnd()) {
= new (eventAllocator()) EndElementEvent(e,
0);
end->setIncluded();
}
else {
if (!map)
0,
map,
}
}
{
currentLocation());
currentInput()->discardInitial();
if (markup) {
}
if (!e)
e = completeRankStem(name);
}
if (!e)
return new (eventAllocator())
markup);
}
void Parser::parseEndTagClose()
{
for (;;) {
switch (token) {
case tokenUnrecognized:
if (!reportNonSgmlCharacter())
return;
case tokenEe:
return;
case tokenEtago:
case tokenStago:
if (!sd().endTagUnclosed())
currentInput()->ungetToken();
return;
case tokenTagc:
if (currentMarkup())
return;
case tokenS:
if (currentMarkup())
break;
default:
return;
}
}
}
void Parser::parseEmptyEndTag()
{
if (options().warnEmptyTag)
// FIXME what to do if not in base
if (tagLevel() == 0)
else {
currentLocation());
if (markup) {
}
markup));
}
}
void Parser::parseNullEndTag()
{
// If a null end tag was recognized, then there must be a net enabling
// element on the stack.
for (;;) {
if (currentElement().netEnabling())
break;
}
currentLocation());
if (markup)
markup));
}
void Parser::endAllElements()
{
while (tagLevel() > 0) {
if (!currentElement().isFinished())
}
}
{
if (!elementIsOpen(e)) {
delete event;
return;
}
for (;;){
if (currentElement().type() == e)
break;
}
if (currentElement().included())
event->setIncluded();
popElement();
}
{
currentElement().startLocation());
else {
currentElement().startLocation());
}
loc,
0);
if (currentElement().included())
event->setIncluded();
popElement();
}
void Parser::extendData()
{
// This is one of the parser's inner loops, so it needs to be fast.
length++;
}
void Parser::extendContentS()
{
for (;;) {
break;
length++;
}
}
{
keepMessages();
for (;;) {
findMissingTag(e, missing);
const ElementType *m = missing[0];
StringMessageArg(e->name()),
StringMessageArg(m->name()));
// this will give an error if the element has a required attribute
attributes->finish(*this);
= new (eventAllocator()) StartElementEvent(m,
0);
if (!currentElement().tryTransition(m))
pushElementCheck(m, inferEvent, 0);
if (!currentElement().tryTransition(e))
event->setIncluded();
return;
}
StringMessageArg(e->name()),
return;
}
|| !currentElement().isFinished()
|| tagLevel() == 0
break;
0);
}
// If element couldn't occur because it was excluded, then
// do the transition here.
(void)currentElement().tryTransition(e);
}
Vector<const ElementType *> &v)
{
if (!currentElement().currentPosition()) {
if (!e)
v.push_back((const ElementType *)0);
return;
}
if (elementIsExcluded(e))
return;
// FIXME also get currentInclusions
if (v[i] && !elementIsExcluded(v[i])) {
switch (v[i]->definition()->declaredContent()) {
case ElementDefinition::modelGroup:
{
const CompiledModelGroup *grp
= v[i]->definition()->compiledModelGroup();
if (!e) {
if (state.tryTransitionPcdata())
success = 1;
}
else {
if (state.tryTransition(e))
success = 1;
if (!success) {
if (v[i]->definition()->inclusion(j) == e) {
success = 1;
break;
}
}
if (success) {
if (v[i]->definition()->exclusion(j) == e) {
success = 0;
break;
}
}
}
}
break;
#if 0
case ElementDefinition::any:
success = 1;
break;
#endif
case ElementDefinition::cdata:
case ElementDefinition::rcdata:
if (e == 0)
success = 1;
break;
default:
break;
}
if (success)
v[newSize++] = v[i];
}
}
// Sort them according to the order of their occurrence in the DTD.
// Do an insertion sort.
const ElementType *tem = v[i];
size_t j;
v[j] = v[j - 1];
v[j] = tem;
}
}
#if 0
// This produces messages that are too verbose
// This doesn't try to be very efficient.
// 0 for #pcdata
{
v.clear();
// FIXME get a list of all inclusions first
// getCurrentInclusions(v);
// x says whether each element of v was excluded
unsigned startImpliedCount = 0;
for (;;) {
if (currentElement().currentPosition()) {
// have a model group
x[j] = (v[j] && elementIsExcluded(v[j]));
break;
// Try to imply a tag
if (currentElement().isFinished()) {
if (tagLevel() == 0)
break;
if (startImpliedCount)
break;
UndoEndTag(popSaveElement()));
else
break;
}
else {
if (!token)
break;
if (elementIsExcluded(e))
break;
if (!def
|| !def->canOmitStartTag())
break;
0,
0,
0,
Location()));
break;
x.push_back(0);
}
}
}
else {
// must be allowed #pcdata
v.push_back((const ElementType *)0);
x.push_back((PackedBoolean)0);
break;
}
}
// Remove exclusions and duplicates and undefined
if (!x[i] && (!v[i] || !v[i]->definition()->undefined())) {
if (v[i] == v[j]) {
dup = 1;
break;
}
if (!dup)
v[newSize++] = v[i];
}
}
#endif
#ifdef SP_NAMESPACE
}
#endif