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