/**
 * Redistribution and use of this software and associated documentation
 * ("Software"), with or without modification, are permitted provided
 * that the following conditions are met:
 *
 * 1. Redistributions of source code must retain copyright
 *    statements and notices.  Redistributions must also contain a
 *    copy of this document.
 *
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. The name "Exolab" must not be used to endorse or promote
 *    products derived from this Software without prior written
 *    permission of Intalio, Inc.  For written permission,
 *    please contact info@exolab.org.
 *
 * 4. Products derived from this Software may not be called "Exolab"
 *    nor may "Exolab" appear in their names without prior written
 *    permission of Intalio, Inc. Exolab is a registered
 *    trademark of Intalio, Inc.
 *
 * 5. Due credit should be given to the Exolab Project
 *    (http://www.exolab.org/).
 *
 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Copyright 2000 (C) Intalio Inc. All Rights Reserved.
 *
 * $Id: DTDParser.jj 3636 2003-03-03 08:05:44 +0100 (Mo, 03 Mrz 2003) kvisco $
 */

options {
   LOOKAHEAD = 3;
   CHOICE_AMBIGUITY_CHECK = 2;
   OTHER_AMBIGUITY_CHECK = 1;
   STATIC = false;
   DEBUG_PARSER = false;
   DEBUG_LOOKAHEAD = false;
   DEBUG_TOKEN_MANAGER = false;
   ERROR_REPORTING = true;
   JAVA_UNICODE_ESCAPE = false;
   UNICODE_INPUT = false;
   IGNORE_CASE = false;
   USER_TOKEN_MANAGER = false;
   USER_CHAR_STREAM = true;
   BUILD_PARSER = true;
   BUILD_TOKEN_MANAGER = true;
   SANITY_CHECK = true;
   FORCE_LA_CHECK = false;
}

PARSER_BEGIN(DTDParser)

package org.exolab.castor.xml.dtd.parser;

import org.exolab.castor.xml.dtd.*;

import java.io.*;

/**
 * Main XML DTD parser. Parses DTD documents with <b>parameter entity
 * references</b> already substituted by corresponding <b>replacement text</b>.
 * Constructs DTD document object.
 * @author <a href="mailto:totok@intalio.com">Alexander Totok</a>
 * @version $Revision: 3636 $ $Date: 2003-03-03 08:05:44 +0100 (Mo, 03 Mrz 2003) $
 */
public class DTDParser {
}

PARSER_END(DTDParser)

TOKEN :
{
     < #LETTER: ["\u0041"-"\u005A", "\u0061"-"\u007A", "\u00C0"-"\u00D6",
                 "\u00D8"-"\u00F6", "\u00F8"-"\u00FF", "\u0100"-"\u0131",
                 "\u0134"-"\u013E", "\u0141"-"\u0148", "\u014A"-"\u017E",
                 "\u0180"-"\u01C3", "\u01CD"-"\u01F0", "\u01F4"-"\u01F5",
                 "\u01FA"-"\u0217", "\u0250"-"\u02A8", "\u02BB"-"\u02C1",
                 "\u0386", "\u0388"-"\u038A", "\u038C", "\u038E"-"\u03A1",
                 "\u03A3"-"\u03CE", "\u03D0"-"\u03D6", "\u03DA", "\u03DC",
                 "\u03DE", "\u03E0", "\u03E2"-"\u03F3", "\u0401"-"\u040C",
                 "\u040E"-"\u044F", "\u0451"-"\u045C", "\u045E"-"\u0481",
                 "\u0490"-"\u04C4", "\u04C7"-"\u04C8", "\u04CB"-"\u04CC",
                 "\u04D0"-"\u04EB", "\u04EE"-"\u04F5", "\u04F8"-"\u04F9",
                 "\u0531"-"\u0556", "\u0559", "\u0561"-"\u0586",
                 "\u05D0"-"\u05EA", "\u05F0"-"\u05F2", "\u0621"-"\u063A",
                 "\u0641"-"\u064A", "\u0671"-"\u06B7", "\u06BA"-"\u06BE",
                 "\u06C0"-"\u06CE", "\u06D0"-"\u06D3", "\u06D5",
                 "\u06E5"-"\u06E6", "\u0905"-"\u0939", "\u093D",
                 "\u0958"-"\u0961", "\u0985"-"\u098C", "\u098F"-"\u0990",
                 "\u0993"-"\u09A8", "\u09AA"-"\u09B0", "\u09B2",
                 "\u09B6"-"\u09B9", "\u09DC"-"\u09DD", "\u09DF"-"\u09E1",
                 "\u09F0"-"\u09F1", "\u0A05"-"\u0A0A", "\u0A0F"-"\u0A10",
                 "\u0A13"-"\u0A28", "\u0A2A"-"\u0A30", "\u0A32"-"\u0A33",
                 "\u0A35"-"\u0A36", "\u0A38"-"\u0A39", "\u0A59"-"\u0A5C",
                 "\u0A5E", "\u0A72"-"\u0A74", "\u0A85"-"\u0A8B", "\u0A8D",
                 "\u0A8F"-"\u0A91", "\u0A93"-"\u0AA8", "\u0AAA"-"\u0AB0",
                 "\u0AB2"-"\u0AB3", "\u0AB5"-"\u0AB9", "\u0ABD", "\u0AE0",
                 "\u0B05"-"\u0B0C", "\u0B0F"-"\u0B10", "\u0B13"-"\u0B28",
                 "\u0B2A"-"\u0B30", "\u0B32"-"\u0B33", "\u0B36"-"\u0B39",
                 "\u0B3D", "\u0B5C"-"\u0B5D", "\u0B5F"-"\u0B61",
                 "\u0B85"-"\u0B8A", "\u0B8E"-"\u0B90", "\u0B92"-"\u0B95",
                 "\u0B99"-"\u0B9A", "\u0B9C", "\u0B9E"-"\u0B9F",
                 "\u0BA3"-"\u0BA4", "\u0BA8"-"\u0BAA", "\u0BAE"-"\u0BB5",
                 "\u0BB7"-"\u0BB9", "\u0C05"-"\u0C0C", "\u0C0E"-"\u0C10",
                 "\u0C12"-"\u0C28", "\u0C2A"-"\u0C33", "\u0C35"-"\u0C39",
                 "\u0C60"-"\u0C61", "\u0C85"-"\u0C8C", "\u0C8E"-"\u0C90",
                 "\u0C92"-"\u0CA8", "\u0CAA"-"\u0CB3", "\u0CB5"-"\u0CB9",
                 "\u0CDE", "\u0CE0"-"\u0CE1", "\u0D05"-"\u0D0C",
                 "\u0D0E"-"\u0D10", "\u0D12"-"\u0D28", "\u0D2A"-"\u0D39",
                 "\u0D60"-"\u0D61", "\u0E01"-"\u0E2E", "\u0E30",
                 "\u0E32"-"\u0E33", "\u0E40"-"\u0E45", "\u0E81"-"\u0E82",
                 "\u0E84", "\u0E87"-"\u0E88", "\u0E8A", "\u0E8D",
                 "\u0E94"-"\u0E97", "\u0E99"-"\u0E9F", "\u0EA1"-"\u0EA3",
                 "\u0EA5", "\u0EA7", "\u0EAA"-"\u0EAB", "\u0EAD"-"\u0EAE",
                 "\u0EB0", "\u0EB2"-"\u0EB3", "\u0EBD", "\u0EC0"-"\u0EC4",
                 "\u0F40"-"\u0F47", "\u0F49"-"\u0F69", "\u10A0"-"\u10C5",
                 "\u10D0"-"\u10F6", "\u1100", "\u1102"-"\u1103",
                 "\u1105"-"\u1107", "\u1109", "\u110B"-"\u110C",
                 "\u110E"-"\u1112", "\u113C", "\u113E", "\u1140", "\u114C",
                 "\u114E", "\u1150", "\u1154"-"\u1155", "\u1159",
                 "\u115F"-"\u1161", "\u1163", "\u1165", "\u1167", "\u1169",
                 "\u116D"-"\u116E", "\u1172"-"\u1173", "\u1175", "\u119E",
                 "\u11A8", "\u11AB", "\u11AE"-"\u11AF", "\u11B7"-"\u11B8",
                 "\u11BA", "\u11BC"-"\u11C2", "\u11EB", "\u11F0", "\u11F9",
                 "\u1E00"-"\u1E9B", "\u1EA0"-"\u1EF9", "\u1F00"-"\u1F15",
                 "\u1F18"-"\u1F1D", "\u1F20"-"\u1F45", "\u1F48"-"\u1F4D",
                 "\u1F50"-"\u1F57", "\u1F59", "\u1F5B", "\u1F5D",
                 "\u1F5F"-"\u1F7D", "\u1F80"-"\u1FB4", "\u1FB6"-"\u1FBC",
                 "\u1FBE", "\u1FC2"-"\u1FC4", "\u1FC6"-"\u1FCC",
                 "\u1FD0"-"\u1FD3", "\u1FD6"-"\u1FDB", "\u1FE0"-"\u1FEC",
                 "\u1FF2"-"\u1FF4", "\u1FF6"-"\u1FFC", "\u2126",
                 "\u212A"-"\u212B", "\u212E", "\u2180"-"\u2182",
                 "\u3041"-"\u3094", "\u30A1"-"\u30FA", "\u3105"-"\u312C",
                 "\uAC00"-"\uD7A3", "\u4E00"-"\u9FA5", "\u3007",
                 "\u3021"-"\u3029"] >

   | < #DIGIT: ["\u0030"-"\u0039", "\u0660"-"\u0669", "\u06F0"-"\u06F9",
                "\u0966"-"\u096F", "\u09E6"-"\u09EF", "\u0A66"-"\u0A6F",
                "\u0AE6"-"\u0AEF", "\u0B66"-"\u0B6F", "\u0BE7"-"\u0BEF",
                "\u0C66"-"\u0C6F", "\u0CE6"-"\u0CEF", "\u0D66"-"\u0D6F",
                "\u0E50"-"\u0E59", "\u0ED0"-"\u0ED9", "\u0F20"-"\u0F29"] >

   | < #COMBINING_CHAR: ["\u0300"-"\u0345", "\u0360"-"\u0361", "\u0483"-"\u0486",
                         "\u0591"-"\u05A1", "\u05A3"-"\u05B9", "\u05BB"-"\u05BD",
                         "\u05BF", "\u05C1"-"\u05C2", "\u05C4", "\u064B"-"\u0652",
                         "\u0670", "\u06D6"-"\u06DC", "\u06DD"-"\u06DF",
                         "\u06E0"-"\u06E4", "\u06E7"-"\u06E8", "\u06EA"-"\u06ED",
                         "\u0901"-"\u0903", "\u093C", "\u093E"-"\u094C", "\u094D",
                         "\u0951"-"\u0954", "\u0962"-"\u0963", "\u0981"-"\u0983",
                         "\u09BC", "\u09BE", "\u09BF", "\u09C0"-"\u09C4",
                         "\u09C7"-"\u09C8", "\u09CB"-"\u09CD", "\u09D7",
                         "\u09E2"-"\u09E3", "\u0A02", "\u0A3C", "\u0A3E",
                         "\u0A3F", "\u0A40"-"\u0A42", "\u0A47"-"\u0A48",
                         "\u0A4B"-"\u0A4D", "\u0A70"-"\u0A71", "\u0A81"-"\u0A83",
                         "\u0ABC", "\u0ABE"-"\u0AC5", "\u0AC7"-"\u0AC9",
                         "\u0ACB"-"\u0ACD", "\u0B01"-"\u0B03", "\u0B3C",
                         "\u0B3E"-"\u0B43", "\u0B47"-"\u0B48", "\u0B4B"-"\u0B4D",
                         "\u0B56"-"\u0B57", "\u0B82"-"\u0B83", "\u0BBE"-"\u0BC2",
                         "\u0BC6"-"\u0BC8", "\u0BCA"-"\u0BCD", "\u0BD7",
                         "\u0C01"-"\u0C03", "\u0C3E"-"\u0C44", "\u0C46"-"\u0C48",
                         "\u0C4A"-"\u0C4D", "\u0C55"-"\u0C56", "\u0C82"-"\u0C83",
                         "\u0CBE"-"\u0CC4", "\u0CC6"-"\u0CC8", "\u0CCA"-"\u0CCD",
                         "\u0CD5"-"\u0CD6", "\u0D02"-"\u0D03", "\u0D3E"-"\u0D43",
                         "\u0D46"-"\u0D48", "\u0D4A"-"\u0D4D", "\u0D57", "\u0E31",
                         "\u0E34"-"\u0E3A", "\u0E47"-"\u0E4E", "\u0EB1",
                         "\u0EB4"-"\u0EB9", "\u0EBB"-"\u0EBC", "\u0EC8"-"\u0ECD",
                         "\u0F18"-"\u0F19", "\u0F35", "\u0F37", "\u0F39", "\u0F3E",
                         "\u0F3F", "\u0F71"-"\u0F84", "\u0F86"-"\u0F8B",
                         "\u0F90"-"\u0F95", "\u0F97", "\u0F99"-"\u0FAD",
                         "\u0FB1"-"\u0FB7", "\u0FB9", "\u20D0"-"\u20DC", "\u20E1",
                         "\u302A"-"\u302F", "\u3099", "\u309A"] >

   | < #EXTENDER: ["\u00B7", "\u02D0", "\u02D1", "\u0387", "\u0640", "\u0E46",
                   "\u0EC6", "\u3005", "\u3031"-"\u3035", "\u309D"-"\u309E",
                   "\u30FC"-"\u30FE"] >

   | < #NAMECHAR: <LETTER> | <DIGIT> | <COMBINING_CHAR> | <EXTENDER> |
                   [".","-","_",":"] >
}

<DEFAULT> TOKEN :
{
     < S: ( ["\t","\r","\n"," "] )+ >
   | < LEFT_PAREN: "(" >
   | < RIGHT_PAREN: ")" >
   | < OR: "|" >
   | < AND: "," >
   | < STAR: "*" >
   | < QUESTION: "?" >
   | < PLUS: "+" >
   | < ANY: "ANY" >
   | < EMPTY: "EMPTY" >
   | < BEGIN_ELEMENT_DECL: "<!ELEMENT" >
   | < END_ELEMENT_DECL: ">" >
   | < PCDATA: "#PCDATA">
   | < BEGIN_ATTR_DECL: "<!ATTLIST" > : WithinAttrDecl
   | < BEGIN_COMMENT: "<!--" > : WithinComment
   | < BEGIN_GE_DECL: "<!ENTITY" > : WithinGEDecl
   | < BEGIN_NOTATION_DECL: "<!NOTATION" > : WithinNotationDecl
   | < NAME: ( <LETTER> | ["_",":"] ) ( <NAMECHAR> )* >
}

<WithinComment> TOKEN :
{
     < COMMENT_CHAR: ["\t","\r","\n","\u0020"-"\u002c","\u002e"-"\uD7ff",
                      "\uE000"-"\uFFFD"] >
   | < DASH: "-" >
   | < END_COMMENT: "-->" > : DEFAULT
}

<WithinAttrDecl> TOKEN :
{
     < S_ATTR: ( ["\t","\r","\n"," "] )+ >
   | < LEFT_PAREN_ATTR: "(" >
   | < RIGHT_PAREN_ATTR: ")" >
   | < OR_ATTR: "|" >
   | < CDATA: "CDATA" >
   | < ID: "ID" >
   | < IDREF: "IDREF" >
   | < IDREFS: "IDREFS" >
   | < ENTITY: "ENTITY" >
   | < ENTITIES: "ENTITIES" >
   | < NMTOKEN: "NMTOKEN" >
   | < NMTOKENS: "NMTOKENS" >
   | < NOTATION: "NOTATION" >
   | < REQUIRED: "#REQUIRED" >
   | < IMPLIED: "#IMPLIED" >
   | < FIXED: "#FIXED" >
   | < START_DQ_ATTR: "\"" > : WithinAttrValueDQ
   | < START_SQ_ATTR: "'"  > : WithinAttrValueSQ
   | < END_ATTR_DECL: ">" > : DEFAULT
   | < NAME_ATTR: ( <LETTER> | ["_",":"] ) ( <NAMECHAR> )* >
   | < NMTOKEN_ATTR: ( <NAMECHAR> )+ >
}

<WithinAttrValueDQ> TOKEN :
{
     < ATTR_VALUE_CHAR_DQ: ~["\"","<"] >
   | < END_DQ_ATTR: "\"" > : WithinAttrDecl
}

<WithinAttrValueSQ> TOKEN :
{
     < ATTR_VALUE_CHAR_SQ: ~["'","<"] >
   | < END_SQ_ATTR: "'" > : WithinAttrDecl
}

<WithinGEDecl> TOKEN :
{
     < S_GE: ( ["\t","\r","\n"," "] )+ >
   | < END_GE_DECL: ">" > : DEFAULT
   | < START_DQ_GE: "\"" > : WithinGEValueDQ
   | < START_SQ_GE: "'" > : WithinGEValueSQ
   | < PUBLIC_GE: "PUBLIC" ( ["\t","\r","\n"," "] )+ > : Public_GE
   | < SYSTEM_GE: "SYSTEM" ( ["\t","\r","\n"," "] )+ > : System_GE
   | < NDATA: "NDATA" >
   | < NAME_GE: ( <LETTER> | ["_",":"] ) ( <NAMECHAR> )* >
}

<System_GE> TOKEN :
{
   < SYSLITER_GE: ( "\"" ( ~["\""] )* "\""
                  | "'"  ( ~["'"]  )* "'"  ) > : WithinGEDecl
}

<Public_GE> TOKEN :
{
     < #PUBIDCHAR_GE: [" ","\r","\n","a"-"z","A"-"Z","!","#"-"%","("-";","=","?"-"@","_"] >
   | < PUBLITER_GE: ( "\"" ( <PUBIDCHAR_GE> | "'"  )* "\""
                    | "'"  ( <PUBIDCHAR_GE> | "\"" )* "'"  ) >
   | < S_GE_PUB: ( ["\t","\r","\n"," "] )+ > : System_GE
}

<WithinGEValueDQ> TOKEN :
{
     < GE_VAlUE_CHAR_DQ: ~["%","\""] >
   | < END_DQ_GE: "\"" > : WithinGEDecl
}

<WithinGEValueSQ> TOKEN :
{
     < GE_VAlUE_CHAR_SQ: ~["%","'"] >
   | < END_SQ_GE: "'" > : WithinGEDecl
}

<WithinNotationDecl> TOKEN:
{
     < S_NOT: ( ["\t","\r","\n"," "] )+ >
   | < PUBLIC_NOT: "PUBLIC" ( ["\t","\r","\n"," "] )+ > : Public_NOT
   | < SYSTEM_NOT: "SYSTEM" ( ["\t","\r","\n"," "] )+ > : System_NOT
   | < NAME_NOT: ( <LETTER> | ["_",":"] ) ( <NAMECHAR> )* >
}

<System_NOT> TOKEN:
{
     < SYSLITER_NOT: ( "\"" ( ~["\""] )* "\""
                     | "'"  ( ~["'"]  )* "'"  ) >
   | < S_NOT_SYS: ( ["\t","\r","\n"," "] )+ >
   | < END_NOTATION_DECL: ">" > : DEFAULT
}

<Public_NOT> TOKEN:
{
     < #PUBIDCHAR_NOT: [" ","\r","\n","a"-"z","A"-"Z","!","#"-"%","("-";","=","?"-"@","_"] >
   | < PUBLITER_NOT: ( "\"" ( <PUBIDCHAR_NOT> | "'"  )* "\""
                    | "'"  ( <PUBIDCHAR_NOT> | "\"" )* "'"  ) > : System_NOT
}

/**
 * Main parsing method that starts parsing process.
 * @return corresponding DTD document object.
 */
DTDdocument Input() throws DTDException :
{
   DTDdocument document = new DTDdocument();
}
{
   (<S>)?
   (
      ElementDecl(document) (<S>)?
   |
      AttlistDecl(document) (<S>)?
   |
      GEntityDecl(document) (<S>)?
   |
      NotationDecl(document) (<S>)?
   |
      Comment() (<S>)?
   )*
   <EOF>

   { return document; }
}

/**
 * Parsing procedure corresponding to the <b>Element Declaration</b> nonterminal.
 * @param document DTD document to add this <b>Element Declaration</b> to.
 */
void ElementDecl(DTDdocument document) throws DTDException :
{
   Token token;
   Element element = new Element(document);
   ContentParticle cp;
}
{
   <BEGIN_ELEMENT_DECL> <S>
   token = <NAME> { element.setName(token.image); }
   <S>
   (
      <ANY> { element.setAnyContent(); }
   |
      <EMPTY> { element.setEmptyContent(); }
   |
      (
         Mixed(element)
      |
         cp = SeqOrChoiceContPart()
         (OccuranceSpecification(cp))?
         { element.setElemOnlyContent(cp); }
      )
   )
   (<S>)? <END_ELEMENT_DECL>

   { document.addElement(element); }
}

/**
 * Parsing procedure corresponding to the <b>Mixed Element Content</b>
 * nonterminal.
 * @param element <b>Element</b> which content is being defined.
 */
void Mixed(Element element) throws DTDException :
{
   Token token;
}
{
   <LEFT_PAREN> (<S>)? <PCDATA> (<S>)?  { element.setMixedContent(); }
   (
      (
         <OR> (<S>)? token = <NAME> (<S>)?
         { element.addMixedContentChild(token.image); }
      )+
      <RIGHT_PAREN> <STAR>
   |
      <RIGHT_PAREN>
   )
}

/**
 * Parsing procedure corresponding to the <b>Content Particle</b> nonterminal.
 * @return corresponding <b>Content Particle</b> object.
 */
ContentParticle ContPart() :
{
   ContentParticle cp;
   Token token;
}
{
   (
      token = <NAME> { cp = new ContentParticle(token.image); }
   |
      cp = SeqOrChoiceContPart()
   )
   (OccuranceSpecification(cp))?

   { return cp; }
}

/**
 * Parsing procedure corresponding to the <b>Content Particle</b> nonterminal
 * of the partial form: choice list of content particles, or sequence list
 * of content particles.
 * @return corresponding <b>Content Particle</b> object.
 */
ContentParticle SeqOrChoiceContPart() :
{
   ContentParticle cp = new ContentParticle();
   ContentParticle auxilCP;
}
{
   <LEFT_PAREN> (<S>)? auxilCP = ContPart() (<S>)?
   (
      (
         <OR> { cp.addChild(auxilCP); }
         (<S>)? auxilCP = ContPart() (<S>)?
      )+
      { cp.addChild(auxilCP); cp.setChoiceType(); }
      <RIGHT_PAREN>
   |
      (
         <AND> { cp.addChild(auxilCP); }
         (<S>)? auxilCP = ContPart() (<S>)?
      )+
      { cp.addChild(auxilCP); cp.setSeqType(); }
      <RIGHT_PAREN>
   |
      <RIGHT_PAREN> { cp = auxilCP; }
   )

   { return cp; }
}

/**
 * Method to parse occurance specification of a <b>Content Particle</b>,
 * that is "?", "*" or "+".
 * @param cp <b>Content Particle</b> being processed.
 */
void OccuranceSpecification(ContentParticle cp) :
{}
{
   (
      <STAR> { cp.setZeroOrMoreOccurances(); }
   |
      <PLUS>
      {
         if (cp.isOneOccurance() || cp.isOneOrMoreOccurances())
         cp.setOneOrMoreOccurances();
         else cp.setZeroOrMoreOccurances();
      }
   |
      <QUESTION>
      {
         if (cp.isOneOccurance() || cp.isZeroOrOneOccurance())
         cp.setZeroOrOneOccurance();
         else cp.setZeroOrMoreOccurances();
      }
   )
}

/**
 * Parsing procedure corresponding to the <b>Attribute Declaration</b> nonterminal.
 * @param document DTD document to add this <b>Attribute Declaration</b> to.
 */
void AttlistDecl(DTDdocument document) throws DTDException :
{
   Token token;
   Element element;
   Attribute attribute;
   String str;
}
{
   <BEGIN_ATTR_DECL> <S_ATTR> token = <NAME_ATTR>
   {
      element = document.getElement(token.image);
      if (element == null) {
         String err = "Main parser: element \"" + token.image + "\" has not been";
         err += " defined, while its attribute is being defined...";
         throw new DTDException(err);
      }
   }
   (
      <S_ATTR> token = <NAME_ATTR> <S_ATTR>
      { attribute = new Attribute(element, token.image); }
      (
         <CDATA>
         { attribute.setStringType(); }
      |
         <ID>
         { attribute.setIDType(); }
      |
         <IDREF>
         { attribute.setIDREFType(); }
      |
         <IDREFS>
         { attribute.setIDREFSType(); }
      |
         <ENTITY>
         { attribute.setENTITYType(); }
      |
         <ENTITIES>
         { attribute.setENTITIESType(); }
      |
         <NMTOKEN>
         { attribute.setNMTOKENType(); }
      |
         <NMTOKENS>
         { attribute.setNMTOKENSType(); }
      |
         <NOTATION> <S_ATTR>
         { attribute.setNOTATIONType(); }
         <LEFT_PAREN_ATTR> (<S_ATTR>)? token = <NAME_ATTR> (<S_ATTR>)?
         { attribute.addValue(token.image); }
         (
            <OR_ATTR> (<S_ATTR>)? token = <NAME_ATTR> (<S_ATTR>)?
            { attribute.addValue(token.image); }
         )*
         <RIGHT_PAREN_ATTR>
      |
         <LEFT_PAREN_ATTR> (<S_ATTR>)?
         ( token = <NAME_ATTR> | token = <NMTOKEN_ATTR> )
         (<S_ATTR>)?
         { attribute.addValue(token.image); }
         (
            <OR_ATTR> (<S_ATTR>)?
            ( token = <NAME_ATTR> | token = <NMTOKEN_ATTR> )
            (<S_ATTR>)?
            { attribute.addValue(token.image); }
         )*
         <RIGHT_PAREN_ATTR>
         { attribute.setEnumerationType(); }
      )
      <S_ATTR>
      (
         <REQUIRED>
         { attribute.setREQUIRED(); }
      |
         <IMPLIED>
         { attribute.setIMPLIED(); }
      |
         <FIXED> <S_ATTR>
         str = AttrValue()
         {
            attribute.setDefaultValue(str);
            attribute.setFIXED();
         }
      |
         str = AttrValue()
         { attribute.setDefaultValue(str); }
      )
      { element.addAttribute(attribute); }
   )+
   (<S_ATTR>)? <END_ATTR_DECL>
}

/**
 * Parsing procedure corresponding to the <b>Attribute Value</b> nonterminal.
 * @return String containing parsed value.
 */
String AttrValue() :
{
   Token token;
   String value = "";
}
{
   (
      <START_DQ_ATTR>
      (
         token = <ATTR_VALUE_CHAR_DQ>
         { value += token.image; }
      )*
      <END_DQ_ATTR>
   |
      <START_SQ_ATTR>
      (
         token = <ATTR_VALUE_CHAR_SQ>
         { value += token.image; }
      )*
      <END_SQ_ATTR>
   )
   { return value; }
}

/**
 * Parsing procedure corresponding to the <b>General Entity
 * Declaration</b> nonterminal.
 * @param document DTD document to add this <b>General Entity Declaration</b> to.
 */
void GEntityDecl(DTDdocument document) :
{
   Token token;
   GeneralEntity ge;
   String str;
   String pubLit;
   String sysLit;
}
{
   <BEGIN_GE_DECL> <S_GE> token = <NAME_GE> <S_GE>
   { ge = new GeneralEntity(document, token.image); }
   (
      str = GEValue()
      { ge.setValue(str); }
   |
      (
         <PUBLIC_GE>
         token = <PUBLITER_GE>
         {
            str = token.image;
            pubLit = str.substring(1,str.length()-1);
         }
         <S_GE_PUB>
         token = <SYSLITER_GE>
         {
            str = token.image;
            sysLit = str.substring(1,str.length()-1);
            ge.setExternalPublic(pubLit,sysLit);
         }
      |
         <SYSTEM_GE>
         token = <SYSLITER_GE>
         {
            str = token.image;
            sysLit = str.substring(1,str.length()-1);
            ge.setExternalSystem(sysLit);
         }
      )
      (
        <S_GE> <NDATA> <S_GE>
        token = <NAME_GE>
        { ge.setNDATA(token.image); }
      )?
   )
   (<S_GE>)? <END_GE_DECL>

   { document.addGeneralEntity(ge); }
}

/**
 * Parsing procedure corresponding to the <b>General Entity Value</b> nonterminal.
 * @return String containing parsed value.
 */
String GEValue() :
{
   Token token;
   String value = "";
}
{
   (
      <START_DQ_GE>
      (
         token = <GE_VAlUE_CHAR_DQ>
         { value += token.image; }
      )*
      <END_DQ_GE>
   |
      <START_SQ_GE>
      (
         token = <GE_VAlUE_CHAR_SQ>
         { value += token.image; }
      )*
      <END_SQ_GE>
   )
   { return value; }
}


/**
 * Parsing procedure corresponding to the <b>Notation Declaration</b> nonterminal.
 * @param document DTD document to add this <b>Notation Declaration</b> to.
 */
void NotationDecl(DTDdocument document) throws DTDException :
{
   Token token;
   Notation notation;
   String str;
   String pubLit;
   String sysLit = "";
}
{
   <BEGIN_NOTATION_DECL> <S_NOT>
   token = <NAME_NOT> <S_NOT>
   { notation = new Notation(document, token.image); }
   (
      <PUBLIC_NOT>
      token = <PUBLITER_NOT>
      {
         str = token.image;
         pubLit = str.substring(1,str.length()-1);
      }
      (<S_NOT_SYS>)?
      (
         token = <SYSLITER_NOT>
         {
            str = token.image;
            sysLit = str.substring(1,str.length()-1);
         }
      )?
      { notation.setPublic(pubLit,sysLit); }
   |
      <SYSTEM_NOT>
      token = <SYSLITER_NOT>
      {
         str = token.image;
         sysLit = str.substring(1,str.length()-1);
         notation.setSystem(sysLit);
      }
   )
   (<S_NOT_SYS>)? <END_NOTATION_DECL>

   { document.addNotation(notation); }
}

/**
 * Parsing procedure corresponding to the <b>Comment</b> nonterminal.
 */
void Comment () :
{}
{
   <BEGIN_COMMENT>
   (
      <COMMENT_CHAR>
   |
      <DASH> <COMMENT_CHAR>
   )*
   <END_COMMENT>
}
