TIVI-153: Add as dependency for iputils
[profile/ivi/opensp.git] / lib / parseParam.cxx
1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3
4 #include "splib.h"
5 #include "Parser.h"
6 #include "Param.h"
7 #include "Group.h"
8 #include "Markup.h"
9 #include "ParserMessages.h"
10 #include "MessageArg.h"
11 #include "TokenMessageArg.h"
12 #include "token.h"
13 #include "macros.h"
14
15 #ifdef SP_NAMESPACE
16 namespace SP_NAMESPACE {
17 #endif
18
19 Boolean Parser::parseParam(const AllowedParams &allow,
20                            unsigned declInputLevel,
21                            Param &parm)
22 {
23   for (;;) {
24     Token token = getToken(allow.mainMode());
25     switch (token) {
26     case tokenUnrecognized:
27       if (reportNonSgmlCharacter())
28         break;
29       {
30         message(ParserMessages::markupDeclarationCharacter,
31                 StringMessageArg(currentToken()),
32                 AllowedParamsMessageArg(allow, syntaxPointer()));
33       }
34       return 0;
35     case tokenEe:
36       if (inputLevel() <= declInputLevel) {
37         message(ParserMessages::declarationLevel);
38         return 0;
39       }
40       if (currentMarkup())
41         currentMarkup()->addEntityEnd();
42       popInputStack();
43       break;
44     case tokenCom:
45       if (!parseComment(comMode))
46         return 0;
47       if (options().warnPsComment)
48         message(ParserMessages::psComment);
49       break;
50     case tokenDso:
51       if (!allow.dso()) {
52         paramInvalidToken(tokenDso, allow);
53         return 0;
54       }
55       if (currentMarkup())
56         currentMarkup()->addDelim(Syntax::dDSO);
57       parm.type = Param::dso;
58       return 1;
59     case tokenGrpo:
60       if (currentMarkup())
61         currentMarkup()->addDelim(Syntax::dGRPO);
62       switch (allow.group()) {
63       case Param::invalid:
64         paramInvalidToken(tokenGrpo, allow);
65         return 0;
66       case Param::modelGroup:
67         {
68           ModelGroup *group;
69           if (!parseModelGroup(1, declInputLevel, group, grpsufMode))
70             return 0;
71           parm.type = Param::modelGroup;
72           parm.modelGroupPtr = group;
73         }
74         break;
75       case Param::nameGroup:
76         if (!parseNameGroup(declInputLevel, parm))
77           return 0;
78         break;
79       case Param::nameTokenGroup:
80         if (!parseNameTokenGroup(declInputLevel, parm))
81           return 0;
82         break;
83       default:
84         CANNOT_HAPPEN();
85       }
86       parm.type = allow.group();
87       return 1;
88     case tokenLita:
89     case tokenLit:
90       parm.type = allow.literal();
91       parm.lita = token == tokenLita;
92       switch (allow.literal()) {
93       case Param::invalid:
94         paramInvalidToken(token, allow);
95         return 0;
96       case Param::minimumLiteral:
97         if (!parseMinimumLiteral(parm.lita, parm.literalText))
98           return 0;
99         break;
100       case Param::attributeValueLiteral:
101         if (!parseAttributeValueLiteral(parm.lita, parm.literalText))
102           return 0;
103         break;
104       case Param::tokenizedAttributeValueLiteral:
105         if (!parseTokenizedAttributeValueLiteral(parm.lita, parm.literalText))
106           return 0;
107         break;
108       case Param::systemIdentifier:
109         if (!parseSystemIdentifier(parm.lita, parm.literalText))
110           return 0;
111         break;
112       case Param::paramLiteral:
113         if (!parseParameterLiteral(parm.lita, parm.literalText))
114           return 0;
115         break;
116       }
117       if (currentMarkup())
118         currentMarkup()->addLiteral(parm.literalText);
119       return 1;
120     case tokenMdc:
121       if (!allow.mdc()) {
122         paramInvalidToken(tokenMdc, allow);
123         return 0;
124       }
125       if (inputLevel() > declInputLevel)
126         message(ParserMessages::parameterEntityNotEnded);
127       if (currentMarkup())
128         currentMarkup()->addDelim(Syntax::dMDC);
129       parm.type = Param::mdc;
130       return 1;
131     case tokenMinus:
132       parm.type = Param::minus;
133       if (currentMarkup())
134         currentMarkup()->addDelim(Syntax::dMINUS);
135       return 1;
136     case tokenMinusGrpo:
137       if (!allow.exclusions()) {
138         paramInvalidToken(tokenMinusGrpo, allow);
139         return 0;
140       }
141       if (currentMarkup()) {
142         currentMarkup()->addDelim(Syntax::dMINUS);
143         currentMarkup()->addDelim(Syntax::dGRPO);
144       }
145       parm.type = Param::exclusions;
146       return parseElementNameGroup(declInputLevel, parm);
147     case tokenPero:
148       parm.type = Param::pero;
149       if (currentMarkup())
150         currentMarkup()->addDelim(Syntax::dPERO);
151       return 1;
152     case tokenPeroGrpo:
153       if (!inInstance())
154         message(ParserMessages::peroGrpoProlog);
155       // fall through
156     case tokenPeroNameStart:
157       {
158         if (inInstance()) {
159           if (options().warnInstanceParamEntityRef)
160             message(ParserMessages::instanceParamEntityRef);
161         }
162         else {
163           if (options().warnInternalSubsetPsParamEntityRef && inputLevel() == 1)
164             message(ParserMessages::internalSubsetPsParamEntityRef);
165         }
166         ConstPtr<Entity> entity;
167         Ptr<EntityOrigin> origin;
168         if (!parseEntityReference(1, token == tokenPeroGrpo, entity, origin))
169           return 0;
170         if (!entity.isNull())
171           entity->declReference(*this, origin);
172       }
173       break;
174     case tokenPlusGrpo:
175       if (!allow.inclusions()) {
176         paramInvalidToken(tokenPlusGrpo, allow);
177         return 0;
178       }
179       if (currentMarkup()) {
180         currentMarkup()->addDelim(Syntax::dPLUS);
181         currentMarkup()->addDelim(Syntax::dGRPO);
182       }
183       parm.type = Param::inclusions;
184       return parseElementNameGroup(declInputLevel, parm);
185     case tokenRni:
186       if (!allow.rni()) {
187         paramInvalidToken(tokenRni, allow);
188         return 0;
189       }
190       return parseIndicatedReservedName(allow, parm);
191     case tokenS:
192       if (currentMarkup())
193         currentMarkup()->addS(currentChar());
194       break;
195     case tokenNameStart:
196       switch (allow.nameStart()) {
197       case Param::invalid:
198         paramInvalidToken(tokenNameStart, allow);
199         return 0;
200       case Param::reservedName:
201         return parseReservedName(allow, parm);
202       case Param::name:
203         {
204         extendNameToken(syntax().namelen(), ParserMessages::nameLength);
205         parm.type = Param::name;
206         getCurrentToken(parm.origToken);
207         parm.token = StringC(parm.origToken);
208         const SubstTable *subst = syntax().generalSubstTable();
209         StringC::iterator s = parm.token.begin();
210         size_t count = parm.token.size();
211         const Char *tokenData = parm.token.data();
212         for (; count > 0; --count)
213           *s++ = (*subst)[*tokenData++];
214         if (currentMarkup())
215           currentMarkup()->addName(currentInput());
216         return 1;
217         }
218       case Param::entityName:
219         extendNameToken(syntax().namelen(), ParserMessages::nameLength);
220         parm.type = Param::entityName;
221         getCurrentToken(syntax().entitySubstTable(), parm.token);
222         if (currentMarkup())
223           currentMarkup()->addName(currentInput());
224         return 1;
225       case Param::paramEntityName:
226         extendNameToken(syntax().penamelen(),
227                         ParserMessages::parameterEntityNameLength);
228         parm.type = Param::paramEntityName;
229         getCurrentToken(syntax().entitySubstTable(), parm.token);
230         if (currentMarkup())
231           currentMarkup()->addName(currentInput());
232         return 1;
233       case Param::attributeValue:
234         return parseAttributeValueParam(parm);
235       }
236       break;
237     case tokenDigit:
238       switch (allow.digit()) {
239       case Param::invalid:
240         paramInvalidToken(tokenDigit, allow);
241         return 0;
242       case Param::number:
243         extendNumber(syntax().namelen(), ParserMessages::numberLength);
244         parm.type = Param::number;
245         getCurrentToken(parm.token);
246         if (currentMarkup())
247           currentMarkup()->addNumber(currentInput());
248         return 1;
249       case Param::attributeValue:
250         return parseAttributeValueParam(parm);
251       }
252       break;
253     case tokenLcUcNmchar:
254       switch (allow.nmchar()) {
255       case Param::invalid:
256         paramInvalidToken(tokenLcUcNmchar, allow);
257         return 0;
258       case Param::attributeValue:
259         return parseAttributeValueParam(parm);
260       }
261       break;
262     default:
263       CANNOT_HAPPEN();
264     }
265   }
266 }
267
268 void Parser::paramInvalidToken(Token token, const AllowedParams &allow)
269 {
270   if (!allow.silent())
271     message(ParserMessages::paramInvalidToken,
272             TokenMessageArg(token, allow.mainMode(),
273                             syntaxPointer(), sdPointer()),
274             AllowedParamsMessageArg(allow, syntaxPointer()));
275 }
276
277 Boolean Parser::parseGroupToken(const AllowedGroupTokens &allow,
278                                 unsigned nestingLevel,
279                                 unsigned declInputLevel,
280                                 unsigned groupInputLevel,
281                                 GroupToken &gt)
282 {
283   for (;;) {
284     Token token = getToken(grpMode);
285     switch (token) {
286     case tokenEe:
287       if (inputLevel() <= groupInputLevel) {
288         message(ParserMessages::groupLevel);
289         if (inputLevel() <= declInputLevel)
290           return 0;
291       }
292       else if (!sd().www())
293         message(ParserMessages::groupEntityEnd);
294       if (currentMarkup())
295         currentMarkup()->addEntityEnd();
296       popInputStack();
297       break;
298     case tokenPeroGrpo:
299       {
300         if (!inInstance())
301           message(ParserMessages::peroGrpoProlog);
302         Boolean start;
303         if (inTag(start))
304             message(start
305                     ? ParserMessages::peroGrpoStartTag
306                     : ParserMessages::peroGrpoEndTag);
307         // fall through
308       }
309     case tokenPeroNameStart:
310       {
311         if (options().warnInternalSubsetTsParamEntityRef && inputLevel() == 1)
312           message(ParserMessages::internalSubsetTsParamEntityRef);
313         ConstPtr<Entity> entity;
314         Ptr<EntityOrigin> origin;
315         if (!parseEntityReference(1, token == tokenPeroGrpo, entity, origin))
316           return 0;
317         if (!entity.isNull())
318           entity->declReference(*this, origin);
319       }
320       break;
321     case tokenUnrecognized:
322       if (reportNonSgmlCharacter())
323         break;
324       {
325         message(ParserMessages::groupCharacter,
326                 StringMessageArg(currentToken()),
327                 AllowedGroupTokensMessageArg(allow, syntaxPointer()));
328       }
329       return 0;
330     case tokenDtgo:
331       if (!allow.groupToken(GroupToken::dataTagGroup)) {
332         groupTokenInvalidToken(tokenDtgo, allow);
333         return 0;
334       }
335       if (sd().datatag())
336         message(ParserMessages::datatagNotImplemented);
337       if (!defDtd().isBase())
338         message(ParserMessages::datatagBaseDtd);
339       if (currentMarkup())
340         currentMarkup()->addDelim(Syntax::dDTGO);
341       return parseDataTagGroup(nestingLevel + 1, declInputLevel, gt);
342     case tokenGrpo:
343       if (currentMarkup())
344         currentMarkup()->addDelim(Syntax::dGRPO);
345       switch (allow.group()) {
346       case GroupToken::modelGroup:
347         {
348           ModelGroup *modelGroup;
349           if (!parseModelGroup(nestingLevel + 1, declInputLevel, modelGroup,
350                                grpMode))
351             return 0;
352           gt.model = modelGroup;
353           gt.type = GroupToken::modelGroup;
354           return 1;
355         }
356       case GroupToken::dataTagTemplateGroup:
357         return parseDataTagTemplateGroup(nestingLevel + 1, declInputLevel, gt);
358       default:
359         groupTokenInvalidToken(tokenGrpo, allow);
360         return 0;
361       }
362       break;
363     case tokenRni:
364       if (!allow.groupToken(GroupToken::pcdata)
365           && !allow.groupToken(GroupToken::all)
366           && !allow.groupToken(GroupToken::implicit)) {
367         groupTokenInvalidToken(tokenRni, allow);
368         return 0;
369       }
370       Syntax::ReservedName rn;
371       if (!getIndicatedReservedName(&rn))
372         return 0;
373       if (rn == Syntax::rPCDATA && allow.groupToken(GroupToken::pcdata)) {
374         gt.type = GroupToken::pcdata;
375         gt.contentToken = new PcdataToken;
376         return 1;
377       }
378       else if (rn == Syntax::rALL && allow.groupToken(GroupToken::all)) {
379         message(ParserMessages::sorryAllImplicit);
380         return 0;
381       }
382       else if (rn == Syntax::rIMPLICIT && allow.groupToken(GroupToken::implicit)) {
383         message(ParserMessages::sorryAllImplicit);
384         return 0;
385       }
386       else {
387         StringC token(syntax().delimGeneral(Syntax::dRNI));
388         token += syntax().reservedName(rn);
389         message(ParserMessages::invalidToken, StringMessageArg(token));
390         return 0;
391       }
392     case tokenS:
393       if (currentMarkup()) {
394         extendS();
395         currentMarkup()->addS(currentInput());
396       }
397       break;
398     case tokenNameStart:
399       switch (allow.nameStart()) {
400       case GroupToken::elementToken:
401         {
402           extendNameToken(syntax().namelen(), ParserMessages::nameLength);
403           gt.type = GroupToken::elementToken;
404           StringC &buffer = nameBuffer();
405           getCurrentToken(syntax().generalSubstTable(), buffer);
406           if (currentMarkup())
407             currentMarkup()->addName(currentInput());
408           const ElementType *e = lookupCreateElement(buffer);
409           ContentToken::OccurrenceIndicator oi
410             = getOccurrenceIndicator(grpMode);
411           gt.contentToken = new ElementToken(e, oi);
412           return 1;
413         }
414       case GroupToken::name:
415       case GroupToken::nameToken:
416         extendNameToken(syntax().namelen(),
417                         token == GroupToken::name
418                         ? ParserMessages::nameLength
419                         : ParserMessages::nameTokenLength);
420         getCurrentToken(syntax().generalSubstTable(), gt.token);
421         gt.type = allow.nameStart();
422         if (currentMarkup()) {
423           if (gt.type == GroupToken::nameToken)
424             currentMarkup()->addNameToken(currentInput());
425           else
426             currentMarkup()->addName(currentInput());
427         }
428         return 1;
429       default:
430         groupTokenInvalidToken(tokenNameStart, allow);
431         return 0;
432       }
433     case tokenDigit:
434     case tokenLcUcNmchar:
435       if (!allow.groupToken(GroupToken::nameToken)) {
436         groupTokenInvalidToken(token, allow);
437         return 0;
438       }
439       extendNameToken(syntax().namelen(), ParserMessages::nameTokenLength);
440       getCurrentToken(syntax().generalSubstTable(), gt.token);
441       gt.type = GroupToken::nameToken;
442       if (currentMarkup())
443         currentMarkup()->addNameToken(currentInput());
444       return 1;
445     case tokenLit:
446     case tokenLita:
447       // parameter literal in data tag pattern
448       if (!allow.groupToken(GroupToken::dataTagLiteral)) {
449         groupTokenInvalidToken(token, allow);
450         return 0;
451       }
452       if (!parseDataTagParameterLiteral(token == tokenLita, gt.text))
453         return 0;
454       gt.type = GroupToken::dataTagLiteral;
455       if (currentMarkup())
456         currentMarkup()->addLiteral(gt.text);
457       return 1;
458     case tokenAnd:
459     case tokenSeq:
460     case tokenOr:
461     case tokenDtgc:
462     case tokenGrpc:
463     case tokenOpt:
464     case tokenPlus:
465     case tokenRep:
466       groupTokenInvalidToken(token, allow);
467       return 0;
468     }
469   }
470 }
471
472
473 void Parser::groupTokenInvalidToken(Token token, const AllowedGroupTokens &allow)
474 {
475   message(ParserMessages::groupTokenInvalidToken,
476           TokenMessageArg(token, grpMode, syntaxPointer(), sdPointer()),
477           AllowedGroupTokensMessageArg(allow, syntaxPointer()));
478 }
479
480
481 Boolean Parser::parseGroupConnector(const AllowedGroupConnectors &allow,
482                                     unsigned declInputLevel,
483                                     unsigned groupInputLevel,
484                                     GroupConnector &gc)
485 {
486   for (;;) {
487     Token token = getToken(grpMode);
488     switch (token) {
489     case tokenEe:
490       if (inputLevel() <= groupInputLevel) {
491         message(ParserMessages::groupLevel);
492         if (inputLevel() <= declInputLevel)
493           return 0;
494       }
495       if (currentMarkup())
496         currentMarkup()->addEntityEnd();
497       popInputStack();
498       break;
499     case tokenS:
500       if (currentMarkup()) {
501         extendS();
502         currentMarkup()->addS(currentInput());
503       }
504       break;
505     case tokenPeroGrpo:
506       if (inInstance()) {
507         message(ParserMessages::peroGrpoProlog);
508         break;
509       }
510       // fall through
511     case tokenPeroNameStart:
512       if (!sd().www())
513         message(ParserMessages::groupEntityReference);
514       else {
515         ConstPtr<Entity> entity;
516         Ptr<EntityOrigin> origin;
517         if (!parseEntityReference(1, token == tokenPeroGrpo, entity, origin))
518           return 0;
519         if (!entity.isNull())
520           entity->declReference(*this, origin);
521       }
522       break;
523     case tokenUnrecognized:
524       if (reportNonSgmlCharacter())
525         break;
526       {
527         message(ParserMessages::groupCharacter,
528                 StringMessageArg(currentToken()),
529                 AllowedGroupConnectorsMessageArg(allow, syntaxPointer()));
530       }
531       return 0;
532     case tokenAnd:
533       if (!allow.groupConnector(GroupConnector::andGC)) {
534         groupConnectorInvalidToken(tokenAnd, allow);
535         return 0;
536       }
537       gc.type = GroupConnector::andGC;
538       if (currentMarkup())
539         currentMarkup()->addDelim(Syntax::dAND);
540       return 1;
541     case tokenSeq:
542       if (!allow.groupConnector(GroupConnector::seqGC)) {
543         groupConnectorInvalidToken(tokenSeq, allow);
544         return 0;
545       }
546       gc.type = GroupConnector::seqGC;
547       if (currentMarkup())
548         currentMarkup()->addDelim(Syntax::dSEQ);
549       return 1;
550     case tokenOr:
551       if (!allow.groupConnector(GroupConnector::orGC)) {
552         groupConnectorInvalidToken(tokenOr, allow);
553         return 0;
554       }
555       gc.type = GroupConnector::orGC;
556       if (currentMarkup())
557         currentMarkup()->addDelim(Syntax::dOR);
558       return 1;
559     case tokenDtgc:
560       if (!allow.groupConnector(GroupConnector::dtgcGC)) {
561         groupConnectorInvalidToken(tokenDtgc, allow);
562         return 0;
563       }
564       gc.type = GroupConnector::dtgcGC;
565       if (inputLevel() > groupInputLevel)
566         message(ParserMessages::groupParameterEntityNotEnded);
567       if (currentMarkup())
568         currentMarkup()->addDelim(Syntax::dDTGC);
569       return 1;
570     case tokenGrpc:
571       if (!allow.groupConnector(GroupConnector::grpcGC)) {
572         groupConnectorInvalidToken(tokenGrpc, allow);
573         return 0;
574       }
575       gc.type = GroupConnector::grpcGC;
576       if (inputLevel() > groupInputLevel)
577         message(ParserMessages::groupParameterEntityNotEnded);
578       if (currentMarkup())
579         currentMarkup()->addDelim(Syntax::dGRPC);
580       return 1;
581     default:
582       groupConnectorInvalidToken(token, allow);
583       return 0;
584     }
585   }
586 }
587
588 void Parser::groupConnectorInvalidToken(Token token,
589                                         const AllowedGroupConnectors &allow)
590 {
591   message(ParserMessages::connectorInvalidToken,
592           TokenMessageArg(token, grpMode, syntaxPointer(), sdPointer()),
593           AllowedGroupConnectorsMessageArg(allow, syntaxPointer()));
594 }
595
596 static AllowedGroupTokens allowName(GroupToken::name);
597
598 Boolean Parser::parseElementNameGroup(unsigned declInputLevel, Param &parm)
599 {
600   static AllowedGroupTokens allowCommonName(GroupToken::name,
601                                              GroupToken::all,
602                                              GroupToken::implicit);
603   if (!parseGroup(sd().www() ? allowCommonName : allowName, declInputLevel, parm))
604     return 0;
605   parm.elementVector.resize(parm.nameTokenVector.size());
606   for (size_t i = 0; i < parm.nameTokenVector.size(); i++)
607     parm.elementVector[i] = lookupCreateElement(parm.nameTokenVector[i].name);
608   return 1;
609 }
610
611 Boolean Parser::parseEntityReferenceNameGroup(Boolean &ignore)
612 {
613   Param parm;
614   if (!parseNameGroup(inputLevel(), parm))
615     return 0;
616   if (inInstance()) {
617     for (size_t i = 0; i < parm.nameTokenVector.size(); i++) {
618       const Lpd *lpd = lookupLpd(parm.nameTokenVector[i].name).pointer();
619       if (lpd && lpd->active()) {
620         ignore = 0;
621         return 1;
622       }
623       Ptr<Dtd> dtd = lookupDtd(parm.nameTokenVector[i].name).pointer();
624       if (!dtd.isNull()) {
625         instantiateDtd(dtd);
626         if (currentDtdPointer() == dtd) {
627           ignore = 0;
628           return 1;
629         }
630       }
631     }
632   }
633   ignore = 1;
634   return 1;
635 }
636
637 Boolean Parser::parseTagNameGroup(Boolean &active, Boolean start)
638 {
639   Param parm;
640   enterTag(start);
641   Boolean ret = parseNameGroup(inputLevel(), parm);
642   leaveTag();
643   if (!ret)
644     return 0;
645   active = 0;
646   for (size_t i = 0; i < parm.nameTokenVector.size(); i++) {
647     Ptr<Dtd> dtd = lookupDtd(parm.nameTokenVector[i].name).pointer();
648     if (!dtd.isNull()) {
649       instantiateDtd(dtd);
650       if (currentDtdPointer() == dtd)
651         active = 1;
652     }
653   }
654   return 1;
655 }
656
657 Boolean Parser::parseNameGroup(unsigned declInputLevel, Param &parm)
658 {
659   return parseGroup(allowName, declInputLevel, parm);
660 }
661
662 Boolean Parser::parseNameTokenGroup(unsigned declInputLevel, Param &parm)
663 {
664   static AllowedGroupTokens allowNameToken(GroupToken::nameToken);
665   return parseGroup(allowNameToken, declInputLevel, parm);
666 }
667
668 static
669 Boolean groupContains(const Vector<NameToken> &vec, const StringC &str)
670 {
671   for (size_t i = 0; i < vec.size(); i++)
672     if (vec[i].name == str)
673       return 1;
674   return 0;
675 }
676
677 Boolean Parser::parseGroup(const AllowedGroupTokens &allowToken,
678                            unsigned declInputLevel,
679                            Param &parm)
680 {
681   unsigned groupInputLevel = inputLevel();
682   int nDuplicates = 0;
683   Vector<NameToken> &vec = parm.nameTokenVector;
684   vec.clear();
685   GroupConnector::Type connector = GroupConnector::grpcGC;
686   GroupToken gt;
687   for (;;) {
688     if (!parseGroupToken(allowToken, 0, declInputLevel, groupInputLevel, gt))
689       return 0;
690     if (groupContains(vec, gt.token)) {
691       nDuplicates++;
692       message(ParserMessages::duplicateGroupToken,
693               StringMessageArg(gt.token));
694     }
695     else {
696       vec.resize(vec.size() + 1);
697       gt.token.swap(vec.back().name);
698       getCurrentToken(vec.back().origName);
699       vec.back().loc = currentLocation();
700     }
701     GroupConnector gc;
702     static AllowedGroupConnectors allowAnyConnectorGrpc(GroupConnector::orGC,
703                                                         GroupConnector::andGC,
704                                                         GroupConnector::seqGC,
705                                                         GroupConnector::grpcGC);
706
707     if (!parseGroupConnector(allowAnyConnectorGrpc, declInputLevel,
708                              groupInputLevel, gc))
709       return 0;
710     if (gc.type == GroupConnector::grpcGC)
711       break;
712     if (options().warnNameGroupNotOr) {
713       if (gc.type != GroupConnector::orGC)
714         message(ParserMessages::nameGroupNotOr);
715     }
716     else if (options().warnShould) {
717       if (connector == GroupConnector::grpcGC)
718         connector = gc.type;
719       else if (gc.type != connector) {
720         message(ParserMessages::mixedConnectors);
721         connector = gc.type;
722       }
723     }
724   }
725   if (nDuplicates + vec.size() > syntax().grpcnt())
726     message(ParserMessages::groupCount, NumberMessageArg(syntax().grpcnt()));
727   return 1;
728 }
729
730 Boolean Parser::parseDataTagGroup(unsigned nestingLevel,
731                                   unsigned declInputLevel, GroupToken &result)
732 {
733   if (nestingLevel - 1 == syntax().grplvl())
734     message(ParserMessages::grplvl, NumberMessageArg(syntax().grplvl()));
735   unsigned groupInputLevel = inputLevel();
736   GroupToken gt;
737   static AllowedGroupTokens allowName(GroupToken::name);
738   if (!parseGroupToken(allowName, nestingLevel, declInputLevel,
739                        groupInputLevel, gt))
740     return 0;
741   const ElementType *element = lookupCreateElement(gt.token);
742   GroupConnector gc;
743   static AllowedGroupConnectors allowSeq(GroupConnector::seqGC);
744   if (!parseGroupConnector(allowSeq, declInputLevel, groupInputLevel, gc))
745     return 0;
746   static AllowedGroupTokens
747     allowDataTagLiteralDataTagTemplateGroup(GroupToken::dataTagLiteral,
748                                             GroupToken::dataTagTemplateGroup);
749   if (!parseGroupToken(allowDataTagLiteralDataTagTemplateGroup,
750                        nestingLevel,
751                        declInputLevel,
752                        groupInputLevel,
753                        gt))
754     return 0;
755   Vector<Text> templates;
756   if (gt.type == GroupToken::dataTagTemplateGroup)
757     gt.textVector.swap(templates);
758   else {
759     templates.resize(1);
760     gt.text.swap(templates[0]);
761   }
762   static AllowedGroupConnectors allowSeqDtgc(GroupConnector::seqGC,
763                                              GroupConnector::dtgcGC);
764   if (!parseGroupConnector(allowSeqDtgc, declInputLevel, groupInputLevel, gc))
765     return 0;
766   NCVector<Owner<ContentToken> > vec(2);
767   vec[1] = new PcdataToken;
768   if (gc.type != GroupConnector::dtgcGC) {
769     static AllowedGroupTokens allowDataTagLiteral(GroupToken::dataTagLiteral);
770     if (!parseGroupToken(allowDataTagLiteral,
771                          nestingLevel,
772                          declInputLevel,
773                          groupInputLevel,
774                          gt))
775       return 0;
776     vec[0] = new DataTagElementToken(element, templates, gt.text);
777     static AllowedGroupConnectors allowDtgc(GroupConnector::dtgcGC);
778     if (!parseGroupConnector(allowDtgc, declInputLevel, groupInputLevel, gc))
779       return 0;
780   }
781   else
782     vec[0] = new DataTagElementToken(element, templates);
783   ContentToken::OccurrenceIndicator oi = getOccurrenceIndicator(grpMode);
784   result.contentToken = new DataTagGroup(vec, oi);
785   result.type = GroupToken::dataTagGroup;
786   return 1;
787 }
788
789 Boolean Parser::parseDataTagTemplateGroup(unsigned nestingLevel,
790                                           unsigned declInputLevel,
791                                           GroupToken &result)
792 {
793   if (nestingLevel - 1 == syntax().grplvl())
794     message(ParserMessages::grplvl, NumberMessageArg(syntax().grplvl()));
795   unsigned groupInputLevel = inputLevel();
796   Vector<Text> &vec = result.textVector;
797   for (;;) {
798     GroupToken gt;
799     static AllowedGroupTokens allowDataTagLiteral(GroupToken::dataTagLiteral);
800     if (!parseGroupToken(allowDataTagLiteral,
801                          nestingLevel,
802                          declInputLevel,
803                          groupInputLevel,
804                          gt))
805       return 0;
806     if (vec.size() == syntax().grpcnt())
807       message(ParserMessages::groupCount, NumberMessageArg(syntax().grpcnt()));
808     vec.resize(vec.size() + 1);
809     gt.text.swap(vec.back());
810     static AllowedGroupConnectors allowOrGrpc(GroupConnector::orGC,
811                                               GroupConnector::grpcGC);
812     GroupConnector gc;
813     if (!parseGroupConnector(allowOrGrpc, declInputLevel, groupInputLevel, gc))
814       return 0;
815     if (gc.type == GroupConnector::grpcGC)
816       break;
817   }
818   return 1;
819 }
820
821 Boolean Parser::parseModelGroup(unsigned nestingLevel, unsigned declInputLevel,
822                                 ModelGroup *&group, Mode oiMode)
823 {
824   if (nestingLevel - 1 == syntax().grplvl())
825     message(ParserMessages::grplvl, NumberMessageArg(syntax().grplvl()));
826   unsigned groupInputLevel = inputLevel();
827   GroupToken gt;
828   NCVector<Owner<ContentToken> > tokenVector;
829   GroupConnector::Type connector = GroupConnector::grpcGC;
830   
831   static AllowedGroupTokens allowContentToken(GroupToken::pcdata,
832                                               GroupToken::dataTagGroup,
833                                               GroupToken::elementToken,
834                                               GroupToken::modelGroup);
835   static AllowedGroupTokens allowCommonContentToken(GroupToken::pcdata,
836                                                     GroupToken::all,
837                                                     GroupToken::implicit,
838                                                     GroupToken::dataTagGroup,
839                                                     GroupToken::elementToken,
840                                                     GroupToken::modelGroup);
841   static AllowedGroupConnectors allowAnyConnectorGrpc(GroupConnector::orGC,
842                                                       GroupConnector::andGC,
843                                                       GroupConnector::seqGC,
844                                                       GroupConnector::grpcGC);
845                             
846   static AllowedGroupConnectors allowOrGrpc(GroupConnector::orGC,
847                                             GroupConnector::grpcGC);
848   static AllowedGroupConnectors allowAndGrpc(GroupConnector::andGC,
849                                              GroupConnector::grpcGC);
850   static AllowedGroupConnectors allowSeqGrpc(GroupConnector::seqGC,
851                                              GroupConnector::grpcGC);
852   const AllowedGroupConnectors *connectorp = &allowAnyConnectorGrpc;
853
854   GroupConnector gc;
855   Boolean pcdataCheck = 0;
856   do {
857     if (!parseGroupToken(sd().www() ? allowCommonContentToken 
858                                     : allowContentToken, 
859                          nestingLevel, declInputLevel, groupInputLevel, gt))
860       return 0;
861     ContentToken *contentToken;
862     if (gt.type == GroupToken::modelGroup)
863       contentToken = gt.model.extract();
864     else
865       contentToken = gt.contentToken.extract();
866     if (tokenVector.size() == syntax().grpcnt())
867       message(ParserMessages::groupCount, NumberMessageArg(syntax().grpcnt()));
868     tokenVector.resize(tokenVector.size() + 1);
869     tokenVector.back() = contentToken;
870     if (!parseGroupConnector(*connectorp, declInputLevel, groupInputLevel, gc))
871       return 0;
872     if (options().warnMixedContentRepOrGroup && gt.type == GroupToken::pcdata) {
873       if (tokenVector.size() != 1)
874         message(ParserMessages::pcdataNotFirstInGroup);
875       else if (gc.type == GroupConnector::seqGC)
876         message(ParserMessages::pcdataInSeqGroup);
877       else
878         pcdataCheck = 1;
879       if (nestingLevel != 1)
880         message(ParserMessages::pcdataInNestedModelGroup);
881     }
882     else if (pcdataCheck) {
883       if (gt.type == GroupToken::modelGroup)
884         message(ParserMessages::pcdataGroupMemberModelGroup);
885       if (contentToken->occurrenceIndicator() != ContentToken::none)
886         message(ParserMessages::pcdataGroupMemberOccurrenceIndicator);
887     }
888     if (tokenVector.size() == 1) {
889       connector = gc.type;
890       switch (gc.type) {
891       case GroupConnector::orGC:
892         connectorp = &allowOrGrpc;
893         break;
894       case GroupConnector::seqGC:
895         connectorp = &allowSeqGrpc;
896         break;
897       case GroupConnector::andGC:
898         connectorp = &allowAndGrpc;
899         if (options().warnAndGroup)
900           message(ParserMessages::andGroup);
901         break;
902       default:
903         break;
904       }
905     }
906   } while (gc.type != GroupConnector::grpcGC);
907   ContentToken::OccurrenceIndicator oi
908     = getOccurrenceIndicator(oiMode);
909   switch (connector) {
910   case GroupConnector::orGC:
911     group = new OrModelGroup(tokenVector, oi);
912     if (pcdataCheck && oi != ContentToken::rep)
913       message(ParserMessages::pcdataGroupNotRep);
914     break;
915   case GroupConnector::grpcGC:
916     if (pcdataCheck && oi != ContentToken::rep && oi != ContentToken::none)
917       message(ParserMessages::pcdataGroupNotRep);
918     // fall through
919   case GroupConnector::seqGC:
920     group = new SeqModelGroup(tokenVector, oi);
921     break;
922   case GroupConnector::andGC:
923     group = new AndModelGroup(tokenVector, oi);
924     break;
925   default:
926     break;
927   }
928   return 1;
929 }
930
931 ContentToken::OccurrenceIndicator
932 Parser::getOccurrenceIndicator(Mode oiMode)
933 {
934   Token token = getToken(oiMode);
935   switch (token) {
936   case tokenPlus:
937     if (currentMarkup())
938       currentMarkup()->addDelim(Syntax::dPLUS);
939     return ContentToken::plus;
940   case tokenOpt: 
941     if (currentMarkup())
942       currentMarkup()->addDelim(Syntax::dOPT);
943    return ContentToken::opt;
944   case tokenRep:
945     if (currentMarkup())
946       currentMarkup()->addDelim(Syntax::dREP);
947     return ContentToken::rep;
948   default:
949     currentInput()->ungetToken();
950     return ContentToken::none;
951   }
952 }
953
954 Boolean Parser::parseMinimumLiteral(Boolean lita, Text &text)
955 {
956   return parseLiteral(lita ? mlitaMode : mlitMode, mlitMode,
957                       Syntax::referenceQuantity(Syntax::qLITLEN),
958                       ParserMessages::minimumLiteralLength,
959                       literalSingleSpace|literalMinimumData
960                       |(eventsWanted().wantPrologMarkup()
961                         ? literalDelimInfo
962                         : 0),
963                       text);
964 }
965
966 Boolean Parser::parseSystemIdentifier(Boolean lita, Text &text)
967 {
968   return parseLiteral(lita ? slitaMode : slitMode, slitMode, syntax().litlen(),
969                       ParserMessages::systemIdentifierLength,
970                       (eventsWanted().wantPrologMarkup()
971                         ? literalDelimInfo
972                         : 0), text);
973 }
974
975 Boolean Parser::parseParameterLiteral(Boolean lita, Text &text)
976 {
977   return parseLiteral(lita ? plitaMode : plitMode, pliteMode, syntax().litlen(), 
978                       ParserMessages::parameterLiteralLength,
979                       (eventsWanted().wantPrologMarkup()
980                        ? literalDelimInfo
981                        : 0),
982                       text);
983 }
984
985 Boolean Parser::parseDataTagParameterLiteral(Boolean lita, Text &text)
986 {
987   return parseLiteral(lita ? plitaMode : plitMode, pliteMode,
988                       syntax().dtemplen(), 
989                       ParserMessages::dataTagPatternLiteralLength,
990                       literalDataTag
991                       | (eventsWanted().wantPrologMarkup()
992                          ? literalDelimInfo
993                          : 0),
994                       text);
995 }
996
997 Boolean Parser::parseIndicatedReservedName(const AllowedParams &allow,
998                                            Param &parm)
999 {
1000   Syntax::ReservedName rn;
1001   if (!getIndicatedReservedName(&rn))
1002     return 0;
1003   if (!allow.reservedName(rn)) {
1004     message(ParserMessages::invalidReservedName,
1005             StringMessageArg(currentToken()));
1006     return 0;
1007   }
1008   parm.type = Param::indicatedReservedName + rn;
1009   return 1;
1010 }
1011
1012 Boolean Parser::parseReservedName(const AllowedParams &allow,
1013                                   Param &parm)
1014 {
1015   Syntax::ReservedName rn;
1016   if (!getReservedName(&rn))
1017     return 0;
1018   if (!allow.reservedName(rn)) {
1019     message(ParserMessages::invalidReservedName,
1020             StringMessageArg(syntax().reservedName(rn)));
1021     return 0;
1022   }
1023   parm.type = Param::reservedName + rn;
1024   return 1;
1025 }
1026
1027
1028 Boolean Parser::parseAttributeValueParam(Param &parm)
1029 {
1030   extendNameToken(syntax().litlen() > syntax().normsep()
1031                   ? syntax().litlen() - syntax().normsep()
1032                   : 0,
1033                   ParserMessages::attributeValueLength);
1034   parm.type = Param::attributeValue;
1035   Text text;
1036   text.addChars(currentInput()->currentTokenStart(),
1037                 currentInput()->currentTokenLength(),
1038                 currentLocation());
1039   text.swap(parm.literalText);
1040   if (currentMarkup())
1041     currentMarkup()->addAttributeValue(currentInput());
1042   return 1;
1043 }
1044
1045 Boolean Parser::getIndicatedReservedName(Syntax::ReservedName *result)
1046 {
1047   if (currentMarkup())
1048     currentMarkup()->addDelim(Syntax::dRNI);
1049   InputSource *in = currentInput();
1050   in->startToken();
1051   if (!syntax().isNameStartCharacter(in->tokenChar(messenger()))) {
1052     message(ParserMessages::rniNameStart);
1053     return 0;
1054   }
1055   extendNameToken(syntax().namelen(), ParserMessages::nameLength);
1056   StringC &buffer = nameBuffer();
1057   getCurrentToken(syntax().generalSubstTable(), buffer);
1058   if (!syntax().lookupReservedName(buffer, result)) {
1059     message(ParserMessages::noSuchReservedName, StringMessageArg(buffer));
1060     return 0;
1061   }
1062   if (currentMarkup())
1063     currentMarkup()->addReservedName(*result, currentInput());
1064   return 1;
1065 }
1066
1067 Boolean Parser::getReservedName(Syntax::ReservedName *result)
1068 {
1069   extendNameToken(syntax().namelen(), ParserMessages::nameLength);
1070   StringC &buffer = nameBuffer();
1071   getCurrentToken(syntax().generalSubstTable(), buffer);
1072   if (!syntax().lookupReservedName(buffer, result)) {
1073     message(ParserMessages::noSuchReservedName, StringMessageArg(buffer));
1074     return 0;
1075   }
1076   if (currentMarkup())
1077     currentMarkup()->addReservedName(*result, currentInput());
1078   return 1;
1079 }
1080
1081
1082 #ifdef SP_NAMESPACE
1083 }
1084 #endif