001    // $ANTLR 2.7.4: "schema.g" -> "AntlrSchemaParser.java"$
002    
003    /*
004     *  Licensed to the Apache Software Foundation (ASF) under one
005     *  or more contributor license agreements.  See the NOTICE file
006     *  distributed with this work for additional information
007     *  regarding copyright ownership.  The ASF licenses this file
008     *  to you under the Apache License, Version 2.0 (the
009     *  "License"); you may not use this file except in compliance
010     *  with the License.  You may obtain a copy of the License at
011     *  
012     *    http://www.apache.org/licenses/LICENSE-2.0
013     *  
014     *  Unless required by applicable law or agreed to in writing,
015     *  software distributed under the License is distributed on an
016     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     *  KIND, either express or implied.  See the License for the
018     *  specific language governing permissions and limitations
019     *  under the License. 
020     *  
021     */
022    package org.apache.directory.shared.ldap.schema.syntax;
023    
024    import java.io.StringReader;
025    import java.util.ArrayList;
026    import java.util.HashMap;
027    import java.util.List;
028    import java.util.Map;
029    
030    import org.apache.directory.shared.ldap.schema.parsers.ComparatorDescription;
031    import org.apache.directory.shared.ldap.schema.parsers.DITContentRuleDescription;
032    import org.apache.directory.shared.ldap.schema.parsers.DITStructureRuleDescription;
033    import org.apache.directory.shared.ldap.schema.parsers.LdapSyntaxDescription;
034    import org.apache.directory.shared.ldap.schema.parsers.MatchingRuleDescription;
035    import org.apache.directory.shared.ldap.schema.parsers.MatchingRuleUseDescription;
036    import org.apache.directory.shared.ldap.schema.parsers.NameFormDescription;
037    import org.apache.directory.shared.ldap.schema.parsers.NormalizerDescription;
038    import org.apache.directory.shared.ldap.schema.parsers.ParserMonitor;
039    import org.apache.directory.shared.ldap.schema.parsers.AttributeTypeDescription;
040    import org.apache.directory.shared.ldap.schema.parsers.ObjectClassDescription;
041    import org.apache.directory.shared.ldap.schema.parsers.SyntaxCheckerDescription;
042    import org.apache.directory.shared.ldap.schema.syntaxes.OpenLdapObjectIdentifierMacro;
043    import org.apache.directory.shared.ldap.schema.ObjectClassTypeEnum;
044    import org.apache.directory.shared.ldap.schema.UsageEnum;
045    
046    
047    import antlr.TokenBuffer;
048    import antlr.TokenStreamException;
049    import antlr.TokenStreamIOException;
050    import antlr.ANTLRException;
051    import antlr.LLkParser;
052    import antlr.Token;
053    import antlr.TokenStream;
054    import antlr.RecognitionException;
055    import antlr.NoViableAltException;
056    import antlr.MismatchedTokenException;
057    import antlr.SemanticException;
058    import antlr.ParserSharedInputState;
059    import antlr.collections.impl.BitSet;
060    
061    /**
062     * An antlr generated schema main parser.
063     *
064     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
065     * @version $Rev$
066     */
067    public class AntlrSchemaParser extends antlr.LLkParser       implements AntlrSchemaTokenTypes
068     {
069    
070        private ParserMonitor monitor = null;
071        private boolean isQuirksModeEnabled = false;
072        public void setParserMonitor( ParserMonitor monitor )
073        {
074            this.monitor = monitor;
075        }
076        private void matchedProduction( String msg )
077        {
078            if ( null != monitor )
079            {
080                monitor.matchedProduction( msg );
081            }
082        }
083        public void setQuirksMode( boolean enabled )
084        {
085            this.isQuirksModeEnabled = enabled;
086        }
087        public boolean isQuirksMode()
088        {
089            return this.isQuirksModeEnabled;
090        }
091        static class Extension
092        {
093            String key = "";
094            List<String> values = new ArrayList<String>();
095            
096            public void addValue( String value )
097            {
098                this.values.add( value );
099            }
100        }
101        static class NoidLen
102        {
103            String noid = "";
104            int len = 0;
105        }
106        static class ElementTracker
107        {
108            Map<String, Integer> elementMap = new HashMap<String, Integer>();
109            void track(String element, Token token) throws SemanticException 
110            {
111                if(elementMap.containsKey(element))
112                {
113                    throw new SemanticException( element + " appears twice.", token.getFilename(), token.getLine() , token.getColumn() );
114                }
115                elementMap.put(element, new Integer(1));
116            }
117            boolean contains(String element) 
118            {
119                return elementMap.containsKey(element);
120            }
121        }
122    
123    
124    protected AntlrSchemaParser(TokenBuffer tokenBuf, int k) {
125      super(tokenBuf,k);
126      tokenNames = _tokenNames;
127    }
128    
129    public AntlrSchemaParser(TokenBuffer tokenBuf) {
130      this(tokenBuf,3);
131    }
132    
133    protected AntlrSchemaParser(TokenStream lexer, int k) {
134      super(lexer,k);
135      tokenNames = _tokenNames;
136    }
137    
138    public AntlrSchemaParser(TokenStream lexer) {
139      this(lexer,3);
140    }
141    
142    public AntlrSchemaParser(ParserSharedInputState state) {
143      super(state,3);
144      tokenNames = _tokenNames;
145    }
146    
147            public final List<Object>  openLdapSchema() throws RecognitionException, TokenStreamException {
148                    List<Object> list = new ArrayList<Object>();
149                    
150                    
151                    AttributeTypeDescription atd = null;
152                    ObjectClassDescription ocd = null;
153                    OpenLdapObjectIdentifierMacro oloid = null;
154                    
155                    
156                    {
157                    _loop1280:
158                    do {
159                            switch ( LA(1)) {
160                            case OBJECTIDENTIFIER:
161                            {
162                                    oloid=openLdapObjectIdentifier();
163                                    list.add( oloid );
164                                    break;
165                            }
166                            case ATTRIBUTETYPE:
167                            {
168                                    atd=openLdapAttributeType();
169                                    list.add( atd );
170                                    break;
171                            }
172                            case OBJECTCLASS:
173                            {
174                                    ocd=openLdapObjectClass();
175                                    list.add( ocd );
176                                    break;
177                            }
178                            default:
179                            {
180                                    break _loop1280;
181                            }
182                            }
183                    } while (true);
184                    }
185                    return list;
186            }
187            
188            public final OpenLdapObjectIdentifierMacro  openLdapObjectIdentifier() throws RecognitionException, TokenStreamException {
189                    OpenLdapObjectIdentifierMacro oloid;
190                    
191                    Token  oi = null;
192                    
193                    matchedProduction( "openLdapObjectIdentifier()" );
194                    
195                    
196                    {
197                    oi = LT(1);
198                    match(OBJECTIDENTIFIER);
199                    
200                    String[] nameAndValue = oi.getText().split( " " );
201                    oloid = new OpenLdapObjectIdentifierMacro();
202                    oloid.setName( nameAndValue[0] );
203                    oloid.setRawOidOrNameSuffix( nameAndValue[1] );
204                    
205                    }
206                    return oloid;
207            }
208            
209            public final AttributeTypeDescription  openLdapAttributeType() throws RecognitionException, TokenStreamException {
210                    AttributeTypeDescription atd;
211                    
212                    
213                    matchedProduction( "openLdapAttributeType()" );
214                    
215                    
216                    {
217                    match(ATTRIBUTETYPE);
218                    {
219                    atd=attributeTypeDescription();
220                    }
221                    }
222                    return atd;
223            }
224            
225            public final ObjectClassDescription  openLdapObjectClass() throws RecognitionException, TokenStreamException {
226                    ObjectClassDescription ocd;
227                    
228                    
229                    matchedProduction( "openLdapObjectClass()" );
230                    
231                    
232                    {
233                    match(OBJECTCLASS);
234                    {
235                    ocd=objectClassDescription();
236                    }
237                    }
238                    return ocd;
239            }
240            
241    /**
242         * Production for matching object class descriptions. It is fault-tolerant
243         * against element ordering.
244         *
245         * <pre>
246         * ObjectClassDescription = LPAREN WSP
247         *     numericoid                 ; object identifier
248         *     [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
249         *     [ SP "DESC" SP qdstring ]  ; description
250         *     [ SP "OBSOLETE" ]          ; not active
251         *     [ SP "SUP" SP oids ]       ; superior object classes
252         *     [ SP kind ]                ; kind of class
253         *     [ SP "MUST" SP oids ]      ; attribute types
254         *     [ SP "MAY" SP oids ]       ; attribute types
255         *     extensions WSP RPAREN
256         *
257         * kind = "ABSTRACT" / "STRUCTURAL" / "AUXILIARY"
258         * 
259         * extensions = *( SP xstring SP qdstrings )
260         * xstring = "X" HYPHEN 1*( ALPHA / HYPHEN / USCORE ) 
261         * </pre>
262        */
263            public final ObjectClassDescription  objectClassDescription() throws RecognitionException, TokenStreamException {
264                    ObjectClassDescription ocd = new ObjectClassDescription();
265                    
266                    Token  oid = null;
267                    Token  name = null;
268                    Token  desc = null;
269                    Token  obsolete = null;
270                    Token  sup = null;
271                    Token  kind1 = null;
272                    Token  kind2 = null;
273                    Token  kind3 = null;
274                    Token  must = null;
275                    Token  may = null;
276                    Token  extension = null;
277                    
278                    matchedProduction( "objectClassDescription()" );
279                    ElementTracker et = new ElementTracker();
280                    
281                    
282                    {
283                    oid = LT(1);
284                    match(STARTNUMERICOID);
285                    ocd.setNumericOid(numericoid(oid.getText()));
286                    }
287                    {
288                    _loop1300:
289                    do {
290                            switch ( LA(1)) {
291                            case NAME:
292                            {
293                                    {
294                                    name = LT(1);
295                                    match(NAME);
296                                    et.track("NAME", name); ocd.setNames(qdescrs(name.getText()));
297                                    }
298                                    break;
299                            }
300                            case DESC:
301                            {
302                                    {
303                                    desc = LT(1);
304                                    match(DESC);
305                                    et.track("DESC", desc); ocd.setDescription(qdstring(desc.getText()));
306                                    }
307                                    break;
308                            }
309                            case OBSOLETE:
310                            {
311                                    {
312                                    obsolete = LT(1);
313                                    match(OBSOLETE);
314                                    et.track("OBSOLETE", obsolete); ocd.setObsolete( true );
315                                    }
316                                    break;
317                            }
318                            case SUP:
319                            {
320                                    {
321                                    sup = LT(1);
322                                    match(SUP);
323                                    et.track("SUP", sup); ocd.setSuperiorObjectClasses(oids(sup.getText()));
324                                    }
325                                    break;
326                            }
327                            case ABSTRACT:
328                            case STRUCTURAL:
329                            case AUXILIARY:
330                            {
331                                    {
332                                    switch ( LA(1)) {
333                                    case ABSTRACT:
334                                    {
335                                            kind1 = LT(1);
336                                            match(ABSTRACT);
337                                            et.track("KIND", kind1); ocd.setKind( ObjectClassTypeEnum.ABSTRACT );
338                                            break;
339                                    }
340                                    case STRUCTURAL:
341                                    {
342                                            kind2 = LT(1);
343                                            match(STRUCTURAL);
344                                            et.track("KIND", kind2); ocd.setKind( ObjectClassTypeEnum.STRUCTURAL );
345                                            break;
346                                    }
347                                    case AUXILIARY:
348                                    {
349                                            kind3 = LT(1);
350                                            match(AUXILIARY);
351                                            et.track("KIND", kind3); ocd.setKind( ObjectClassTypeEnum.AUXILIARY );
352                                            break;
353                                    }
354                                    default:
355                                    {
356                                            throw new NoViableAltException(LT(1), getFilename());
357                                    }
358                                    }
359                                    }
360                                    break;
361                            }
362                            case MUST:
363                            {
364                                    {
365                                    must = LT(1);
366                                    match(MUST);
367                                    et.track("MUST", must); ocd.setMustAttributeTypes(oids(must.getText()));
368                                    }
369                                    break;
370                            }
371                            case MAY:
372                            {
373                                    {
374                                    may = LT(1);
375                                    match(MAY);
376                                    et.track("MAY", may); ocd.setMayAttributeTypes(oids(may.getText()));
377                                    }
378                                    break;
379                            }
380                            case EXTENSION:
381                            {
382                                    {
383                                    extension = LT(1);
384                                    match(EXTENSION);
385                                    
386                                    Extension ex = extension(extension.getText());
387                                    et.track(ex.key, extension); 
388                                    ocd.addExtension(ex.key, ex.values); 
389                                    
390                                    }
391                                    break;
392                            }
393                            default:
394                            {
395                                    break _loop1300;
396                            }
397                            }
398                    } while (true);
399                    }
400                    match(RPAR);
401                    return ocd;
402            }
403            
404    /**
405         * Production for matching attribute type descriptions. It is fault-tolerant
406         * against element ordering.
407         *
408         * <pre>
409         * AttributeTypeDescription = LPAREN WSP
410         *     numericoid                    ; object identifier
411         *     [ SP "NAME" SP qdescrs ]      ; short names (descriptors)
412         *     [ SP "DESC" SP qdstring ]     ; description
413         *     [ SP "OBSOLETE" ]             ; not active
414         *     [ SP "SUP" SP oid ]           ; supertype
415         *     [ SP "EQUALITY" SP oid ]      ; equality matching rule
416         *     [ SP "ORDERING" SP oid ]      ; ordering matching rule
417         *     [ SP "SUBSTR" SP oid ]        ; substrings matching rule
418         *     [ SP "SYNTAX" SP noidlen ]    ; value syntax
419         *     [ SP "SINGLE-VALUE" ]         ; single-value
420         *     [ SP "COLLECTIVE" ]           ; collective
421         *     [ SP "NO-USER-MODIFICATION" ] ; not user modifiable
422         *     [ SP "USAGE" SP usage ]       ; usage
423         *     extensions WSP RPAREN         ; extensions
424         * 
425         * usage = "userApplications"     /  ; user
426         *         "directoryOperation"   /  ; directory operational
427         *         "distributedOperation" /  ; DSA-shared operational
428         *         "dSAOperation"            ; DSA-specific operational     
429         * 
430         * extensions = *( SP xstring SP qdstrings )
431         * xstring = "X" HYPHEN 1*( ALPHA / HYPHEN / USCORE ) 
432         * </pre>
433        */
434            public final AttributeTypeDescription  attributeTypeDescription() throws RecognitionException, TokenStreamException {
435                    AttributeTypeDescription atd = new AttributeTypeDescription();
436                    
437                    Token  oid = null;
438                    Token  name = null;
439                    Token  desc = null;
440                    Token  obsolete = null;
441                    Token  sup = null;
442                    Token  equality = null;
443                    Token  ordering = null;
444                    Token  substr = null;
445                    Token  syntax = null;
446                    Token  singleValue = null;
447                    Token  collective = null;
448                    Token  noUserModification = null;
449                    Token  usage1 = null;
450                    Token  usage2 = null;
451                    Token  usage3 = null;
452                    Token  usage4 = null;
453                    Token  extension = null;
454                    
455                    matchedProduction( "attributeTypeDescription()" );
456                    ElementTracker et = new ElementTracker();
457                    
458                    
459                    {
460                    oid = LT(1);
461                    match(STARTNUMERICOID);
462                    atd.setNumericOid(numericoid(oid.getText()));
463                    }
464                    {
465                    _loop1319:
466                    do {
467                            switch ( LA(1)) {
468                            case NAME:
469                            {
470                                    {
471                                    name = LT(1);
472                                    match(NAME);
473                                    et.track("NAME", name); atd.setNames(qdescrs(name.getText()));
474                                    }
475                                    break;
476                            }
477                            case DESC:
478                            {
479                                    {
480                                    desc = LT(1);
481                                    match(DESC);
482                                    et.track("DESC", desc); atd.setDescription(qdstring(desc.getText()));
483                                    }
484                                    break;
485                            }
486                            case OBSOLETE:
487                            {
488                                    {
489                                    obsolete = LT(1);
490                                    match(OBSOLETE);
491                                    et.track("OBSOLETE", obsolete); atd.setObsolete( true );
492                                    }
493                                    break;
494                            }
495                            case SUP:
496                            {
497                                    {
498                                    sup = LT(1);
499                                    match(SUP);
500                                    et.track("SUP", sup); atd.setSuperType(oid(sup.getText()));
501                                    }
502                                    break;
503                            }
504                            case EQUALITY:
505                            {
506                                    {
507                                    equality = LT(1);
508                                    match(EQUALITY);
509                                    et.track("EQUALITY", equality); atd.setEqualityMatchingRule(oid(equality.getText()));
510                                    }
511                                    break;
512                            }
513                            case ORDERING:
514                            {
515                                    {
516                                    ordering = LT(1);
517                                    match(ORDERING);
518                                    et.track("ORDERING", ordering); atd.setOrderingMatchingRule(oid(ordering.getText()));
519                                    }
520                                    break;
521                            }
522                            case SUBSTR:
523                            {
524                                    {
525                                    substr = LT(1);
526                                    match(SUBSTR);
527                                    et.track("SUBSTR", substr); atd.setSubstringsMatchingRule(oid(substr.getText()));
528                                    }
529                                    break;
530                            }
531                            case SYNTAX:
532                            {
533                                    {
534                                    syntax = LT(1);
535                                    match(SYNTAX);
536                                    
537                                    et.track("SYNTAX", syntax); 
538                                    NoidLen noidlen = noidlen(syntax.getText());
539                                    atd.setSyntax(noidlen.noid); 
540                                    atd.setSyntaxLength(noidlen.len);
541                                    
542                                    }
543                                    break;
544                            }
545                            case SINGLE_VALUE:
546                            {
547                                    {
548                                    singleValue = LT(1);
549                                    match(SINGLE_VALUE);
550                                    et.track("SINGLE_VALUE", singleValue); atd.setSingleValued( true );
551                                    }
552                                    break;
553                            }
554                            case COLLECTIVE:
555                            {
556                                    {
557                                    collective = LT(1);
558                                    match(COLLECTIVE);
559                                    et.track("COLLECTIVE", collective); atd.setCollective( true );
560                                    }
561                                    break;
562                            }
563                            case NO_USER_MODIFICATION:
564                            {
565                                    {
566                                    noUserModification = LT(1);
567                                    match(NO_USER_MODIFICATION);
568                                    et.track("NO_USER_MODIFICATION", noUserModification); atd.setUserModifiable( false );
569                                    }
570                                    break;
571                            }
572                            case USAGE:
573                            {
574                                    {
575                                    if ((LA(1)==USAGE) && (LA(2)==WHSP||LA(2)==USER_APPLICATIONS)) {
576                                            usage1 = LT(1);
577                                            match(USAGE);
578                                            {
579                                            _loop1317:
580                                            do {
581                                                    if ((LA(1)==WHSP)) {
582                                                            match(WHSP);
583                                                    }
584                                                    else {
585                                                            break _loop1317;
586                                                    }
587                                                    
588                                            } while (true);
589                                            }
590                                            match(USER_APPLICATIONS);
591                                            et.track("USAGE", usage1); atd.setUsage( UsageEnum.USER_APPLICATIONS );
592                                    }
593                                    else if ((LA(1)==USAGE) && (LA(2)==DIRECTORY_OPERATION)) {
594                                            usage2 = LT(1);
595                                            match(USAGE);
596                                            match(DIRECTORY_OPERATION);
597                                            et.track("USAGE", usage2); atd.setUsage( UsageEnum.DIRECTORY_OPERATION );
598                                    }
599                                    else if ((LA(1)==USAGE) && (LA(2)==DISTRIBUTED_OPERATION)) {
600                                            usage3 = LT(1);
601                                            match(USAGE);
602                                            match(DISTRIBUTED_OPERATION);
603                                            et.track("USAGE", usage3); atd.setUsage( UsageEnum.DISTRIBUTED_OPERATION );
604                                    }
605                                    else if ((LA(1)==USAGE) && (LA(2)==DSA_OPERATION)) {
606                                            usage4 = LT(1);
607                                            match(USAGE);
608                                            match(DSA_OPERATION);
609                                            et.track("USAGE", usage4); atd.setUsage( UsageEnum.DSA_OPERATION );
610                                    }
611                                    else {
612                                            throw new NoViableAltException(LT(1), getFilename());
613                                    }
614                                    
615                                    }
616                                    break;
617                            }
618                            case EXTENSION:
619                            {
620                                    {
621                                    extension = LT(1);
622                                    match(EXTENSION);
623                                    
624                                    Extension ex = extension(extension.getText());
625                                    et.track(ex.key, extension); 
626                                    atd.addExtension(ex.key, ex.values); 
627                                    
628                                    }
629                                    break;
630                            }
631                            default:
632                            {
633                                    break _loop1319;
634                            }
635                            }
636                    } while (true);
637                    }
638                    match(RPAR);
639                    
640                    if( !isQuirksModeEnabled )
641                    {
642                    // semantic check: required elements
643                    if( !et.contains("SYNTAX") && !et.contains("SUP") ) 
644                    {
645                    throw new SemanticException( "One of SYNTAX or SUP is required", null, 0, 0 );
646                    }
647                    
648                    // COLLECTIVE requires USAGE userApplications
649                    if ( atd.isCollective() && ( atd.getUsage() != UsageEnum.USER_APPLICATIONS ) )
650                    {
651                    throw new SemanticException( "COLLECTIVE requires USAGE userApplications", null, 0, 0 );
652                    }
653                    
654                    // NO-USER-MODIFICATION requires an operational USAGE.
655                    if ( !atd.isUserModifiable() && ( atd.getUsage() == UsageEnum.USER_APPLICATIONS ) )
656                    {
657                    throw new SemanticException( "NO-USER-MODIFICATION requires an operational USAGE", null, 0, 0 );
658                    }
659                    }
660                    
661                    return atd;
662            }
663            
664    /**
665         * Production for matching ldap syntax descriptions. It is fault-tolerant
666         * against element ordering.
667         *
668         * <pre>
669         * SyntaxDescription = LPAREN WSP
670         *    numericoid                 ; object identifier
671         *    [ SP "DESC" SP qdstring ]  ; description
672         *    extensions WSP RPAREN      ; extensions
673         * </pre>
674        */
675            public final LdapSyntaxDescription  ldapSyntaxDescription() throws RecognitionException, TokenStreamException {
676                    LdapSyntaxDescription lsd = new LdapSyntaxDescription();
677                    
678                    Token  oid = null;
679                    Token  name = null;
680                    Token  desc = null;
681                    Token  extension = null;
682                    
683                    matchedProduction( "ldapSyntaxDescription()" );
684                    ElementTracker et = new ElementTracker();
685                    
686                    
687                    {
688                    oid = LT(1);
689                    match(STARTNUMERICOID);
690                    lsd.setNumericOid(numericoid(oid.getText()));
691                    }
692                    {
693                    _loop1326:
694                    do {
695                            switch ( LA(1)) {
696                            case NAME:
697                            {
698                                    {
699                                    name = LT(1);
700                                    match(NAME);
701                                    et.track("NAME", name); lsd.setNames(qdescrs(name.getText()));
702                                    }
703                                    break;
704                            }
705                            case DESC:
706                            {
707                                    {
708                                    desc = LT(1);
709                                    match(DESC);
710                                    et.track("DESC", desc); lsd.setDescription(qdstring(desc.getText()));
711                                    }
712                                    break;
713                            }
714                            case EXTENSION:
715                            {
716                                    {
717                                    extension = LT(1);
718                                    match(EXTENSION);
719                                    
720                                    Extension ex = extension(extension.getText());
721                                    et.track(ex.key, extension); 
722                                    lsd.addExtension(ex.key, ex.values); 
723                                    
724                                    }
725                                    break;
726                            }
727                            default:
728                            {
729                                    break _loop1326;
730                            }
731                            }
732                    } while (true);
733                    }
734                    match(RPAR);
735                    return lsd;
736            }
737            
738    /**
739         * Production for matching rule descriptions. It is fault-tolerant
740         * against element ordering.
741         *
742         * <pre>
743         * MatchingRuleDescription = LPAREN WSP
744         *    numericoid                 ; object identifier
745         *    [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
746         *    [ SP "DESC" SP qdstring ]  ; description
747         *    [ SP "OBSOLETE" ]          ; not active
748         *    SP "SYNTAX" SP numericoid  ; assertion syntax
749         *    extensions WSP RPAREN      ; extensions
750         * </pre>
751        */
752            public final MatchingRuleDescription  matchingRuleDescription() throws RecognitionException, TokenStreamException {
753                    MatchingRuleDescription mrd = new MatchingRuleDescription();
754                    
755                    Token  oid = null;
756                    Token  name = null;
757                    Token  desc = null;
758                    Token  obsolete = null;
759                    Token  syntax = null;
760                    Token  extension = null;
761                    
762                    matchedProduction( "matchingRuleDescription()" );
763                    ElementTracker et = new ElementTracker();
764                    
765                    
766                    {
767                    oid = LT(1);
768                    match(STARTNUMERICOID);
769                    mrd.setNumericOid(numericoid(oid.getText()));
770                    }
771                    {
772                    _loop1335:
773                    do {
774                            switch ( LA(1)) {
775                            case NAME:
776                            {
777                                    {
778                                    name = LT(1);
779                                    match(NAME);
780                                    et.track("NAME", name); mrd.setNames(qdescrs(name.getText()));
781                                    }
782                                    break;
783                            }
784                            case DESC:
785                            {
786                                    {
787                                    desc = LT(1);
788                                    match(DESC);
789                                    et.track("DESC", desc); mrd.setDescription(qdstring(desc.getText()));
790                                    }
791                                    break;
792                            }
793                            case OBSOLETE:
794                            {
795                                    {
796                                    obsolete = LT(1);
797                                    match(OBSOLETE);
798                                    et.track("OBSOLETE", obsolete); mrd.setObsolete( true );
799                                    }
800                                    break;
801                            }
802                            case SYNTAX:
803                            {
804                                    {
805                                    syntax = LT(1);
806                                    match(SYNTAX);
807                                    et.track("SYNTAX", syntax); mrd.setSyntax(numericoid(syntax.getText()));
808                                    }
809                                    break;
810                            }
811                            case EXTENSION:
812                            {
813                                    {
814                                    extension = LT(1);
815                                    match(EXTENSION);
816                                    
817                                    Extension ex = extension(extension.getText());
818                                    et.track(ex.key, extension); 
819                                    mrd.addExtension(ex.key, ex.values); 
820                                    
821                                    }
822                                    break;
823                            }
824                            default:
825                            {
826                                    break _loop1335;
827                            }
828                            }
829                    } while (true);
830                    }
831                    match(RPAR);
832                    
833                    if( !isQuirksModeEnabled )
834                    {    
835                    // semantic check: required elements
836                    if( !et.contains("SYNTAX") ) {
837                    throw new SemanticException( "SYNTAX is required", null, 0, 0 );
838                    }
839                    }
840                    
841                    return mrd;
842            }
843            
844    /**
845         * Production for matching rule use descriptions. It is fault-tolerant
846         * against element ordering.
847         *
848         * <pre>
849         * MatchingRuleUseDescription = LPAREN WSP
850         *    numericoid                 ; object identifier
851         *    [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
852         *    [ SP "DESC" SP qdstring ]  ; description
853         *    [ SP "OBSOLETE" ]          ; not active
854         *    SP "APPLIES" SP oids       ; attribute types
855         *    extensions WSP RPAREN      ; extensions
856         * </pre>
857        */
858            public final MatchingRuleUseDescription  matchingRuleUseDescription() throws RecognitionException, TokenStreamException {
859                    MatchingRuleUseDescription mrud = new MatchingRuleUseDescription();
860                    
861                    Token  oid = null;
862                    Token  name = null;
863                    Token  desc = null;
864                    Token  obsolete = null;
865                    Token  applies = null;
866                    Token  extension = null;
867                    
868                    matchedProduction( "matchingRuleUseDescription()" );
869                    ElementTracker et = new ElementTracker();
870                    
871                    
872                    {
873                    oid = LT(1);
874                    match(STARTNUMERICOID);
875                    mrud.setNumericOid(numericoid(oid.getText()));
876                    }
877                    {
878                    _loop1344:
879                    do {
880                            switch ( LA(1)) {
881                            case NAME:
882                            {
883                                    {
884                                    name = LT(1);
885                                    match(NAME);
886                                    et.track("NAME", name); mrud.setNames(qdescrs(name.getText()));
887                                    }
888                                    break;
889                            }
890                            case DESC:
891                            {
892                                    {
893                                    desc = LT(1);
894                                    match(DESC);
895                                    et.track("DESC", desc); mrud.setDescription(qdstring(desc.getText()));
896                                    }
897                                    break;
898                            }
899                            case OBSOLETE:
900                            {
901                                    {
902                                    obsolete = LT(1);
903                                    match(OBSOLETE);
904                                    et.track("OBSOLETE", obsolete); mrud.setObsolete( true );
905                                    }
906                                    break;
907                            }
908                            case APPLIES:
909                            {
910                                    {
911                                    applies = LT(1);
912                                    match(APPLIES);
913                                    et.track("APPLIES", applies); mrud.setApplicableAttributes(oids(applies.getText()));
914                                    }
915                                    break;
916                            }
917                            case EXTENSION:
918                            {
919                                    {
920                                    extension = LT(1);
921                                    match(EXTENSION);
922                                    
923                                    Extension ex = extension(extension.getText());
924                                    et.track(ex.key, extension); 
925                                    mrud.addExtension(ex.key, ex.values); 
926                                    
927                                    }
928                                    break;
929                            }
930                            default:
931                            {
932                                    break _loop1344;
933                            }
934                            }
935                    } while (true);
936                    }
937                    match(RPAR);
938                    
939                    if( !isQuirksModeEnabled )
940                    {
941                    // semantic check: required elements
942                    if( !et.contains("APPLIES") ) {
943                    throw new SemanticException( "APPLIES is required", null, 0, 0 );
944                    }
945                    }
946                    
947                    return mrud;
948            }
949            
950    /**
951         * Production for DIT content rule descriptions. It is fault-tolerant
952         * against element ordering.
953         *
954         * <pre>
955         * DITContentRuleDescription = LPAREN WSP
956         *    numericoid                 ; object identifier
957         *    [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
958         *    [ SP "DESC" SP qdstring ]  ; description
959         *    [ SP "OBSOLETE" ]          ; not active
960         *    [ SP "AUX" SP oids ]       ; auxiliary object classes
961         *    [ SP "MUST" SP oids ]      ; attribute types
962         *    [ SP "MAY" SP oids ]       ; attribute types
963         *    [ SP "NOT" SP oids ]       ; attribute types
964         *    extensions WSP RPAREN      ; extensions
965         * </pre>
966        */
967            public final DITContentRuleDescription  ditContentRuleDescription() throws RecognitionException, TokenStreamException {
968                    DITContentRuleDescription dcrd = new DITContentRuleDescription();
969                    
970                    Token  oid = null;
971                    Token  name = null;
972                    Token  desc = null;
973                    Token  obsolete = null;
974                    Token  aux = null;
975                    Token  must = null;
976                    Token  may = null;
977                    Token  not = null;
978                    Token  extension = null;
979                    
980                    matchedProduction( "ditContentRuleDescription()" );
981                    ElementTracker et = new ElementTracker();
982                    
983                    
984                    {
985                    oid = LT(1);
986                    match(STARTNUMERICOID);
987                    dcrd.setNumericOid(numericoid(oid.getText()));
988                    }
989                    {
990                    _loop1356:
991                    do {
992                            switch ( LA(1)) {
993                            case NAME:
994                            {
995                                    {
996                                    name = LT(1);
997                                    match(NAME);
998                                    et.track("NAME", name); dcrd.setNames(qdescrs(name.getText()));
999                                    }
1000                                    break;
1001                            }
1002                            case DESC:
1003                            {
1004                                    {
1005                                    desc = LT(1);
1006                                    match(DESC);
1007                                    et.track("DESC", desc); dcrd.setDescription(qdstring(desc.getText()));
1008                                    }
1009                                    break;
1010                            }
1011                            case OBSOLETE:
1012                            {
1013                                    {
1014                                    obsolete = LT(1);
1015                                    match(OBSOLETE);
1016                                    et.track("OBSOLETE", obsolete); dcrd.setObsolete( true );
1017                                    }
1018                                    break;
1019                            }
1020                            case AUX:
1021                            {
1022                                    {
1023                                    aux = LT(1);
1024                                    match(AUX);
1025                                    et.track("AUX", aux); dcrd.setAuxiliaryObjectClasses(oids(aux.getText()));
1026                                    }
1027                                    break;
1028                            }
1029                            case MUST:
1030                            {
1031                                    {
1032                                    must = LT(1);
1033                                    match(MUST);
1034                                    et.track("MUST", must); dcrd.setMustAttributeTypes(oids(must.getText()));
1035                                    }
1036                                    break;
1037                            }
1038                            case MAY:
1039                            {
1040                                    {
1041                                    may = LT(1);
1042                                    match(MAY);
1043                                    et.track("MAY", may); dcrd.setMayAttributeTypes(oids(may.getText()));
1044                                    }
1045                                    break;
1046                            }
1047                            case NOT:
1048                            {
1049                                    {
1050                                    not = LT(1);
1051                                    match(NOT);
1052                                    et.track("NOT", not); dcrd.setNotAttributeTypes(oids(not.getText()));
1053                                    }
1054                                    break;
1055                            }
1056                            case EXTENSION:
1057                            {
1058                                    {
1059                                    extension = LT(1);
1060                                    match(EXTENSION);
1061                                    
1062                                    Extension ex = extension(extension.getText());
1063                                    et.track(ex.key, extension); 
1064                                    dcrd.addExtension(ex.key, ex.values); 
1065                                    
1066                                    }
1067                                    break;
1068                            }
1069                            default:
1070                            {
1071                                    break _loop1356;
1072                            }
1073                            }
1074                    } while (true);
1075                    }
1076                    match(RPAR);
1077                    return dcrd;
1078            }
1079            
1080    /**
1081         * Production for DIT structure rules descriptions. It is fault-tolerant
1082         * against element ordering.
1083         *
1084         * <pre>
1085         * DITStructureRuleDescription = LPAREN WSP
1086         *   ruleid                     ; rule identifier
1087         *   [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
1088         *   [ SP "DESC" SP qdstring ]  ; description
1089         *   [ SP "OBSOLETE" ]          ; not active
1090         *   SP "FORM" SP oid           ; NameForm
1091         *   [ SP "SUP" ruleids ]       ; superior rules
1092         *   extensions WSP RPAREN      ; extensions
1093         *
1094         * ruleids = ruleid / ( LPAREN WSP ruleidlist WSP RPAREN )
1095         * ruleidlist = ruleid *( SP ruleid )
1096         * ruleid = number
1097         * </pre>
1098        */
1099            public final DITStructureRuleDescription  ditStructureRuleDescription() throws RecognitionException, TokenStreamException {
1100                    DITStructureRuleDescription dsrd = new DITStructureRuleDescription();
1101                    
1102                    Token  ruleid = null;
1103                    Token  name = null;
1104                    Token  desc = null;
1105                    Token  obsolete = null;
1106                    Token  form = null;
1107                    Token  sup = null;
1108                    Token  extension = null;
1109                    
1110                    matchedProduction( "ditStructureRuleDescription()" );
1111                    ElementTracker et = new ElementTracker();
1112                    
1113                    
1114                    {
1115                    ruleid = LT(1);
1116                    match(STARTNUMERICOID);
1117                    dsrd.setRuleId(ruleid(ruleid.getText()));
1118                    }
1119                    {
1120                    _loop1366:
1121                    do {
1122                            switch ( LA(1)) {
1123                            case NAME:
1124                            {
1125                                    {
1126                                    name = LT(1);
1127                                    match(NAME);
1128                                    et.track("NAME", name); dsrd.setNames(qdescrs(name.getText()));
1129                                    }
1130                                    break;
1131                            }
1132                            case DESC:
1133                            {
1134                                    {
1135                                    desc = LT(1);
1136                                    match(DESC);
1137                                    et.track("DESC", desc); dsrd.setDescription(qdstring(desc.getText()));
1138                                    }
1139                                    break;
1140                            }
1141                            case OBSOLETE:
1142                            {
1143                                    {
1144                                    obsolete = LT(1);
1145                                    match(OBSOLETE);
1146                                    et.track("OBSOLETE", obsolete); dsrd.setObsolete( true );
1147                                    }
1148                                    break;
1149                            }
1150                            case FORM:
1151                            {
1152                                    {
1153                                    form = LT(1);
1154                                    match(FORM);
1155                                    et.track("FORM", form); dsrd.setForm(oid(form.getText()));
1156                                    }
1157                                    break;
1158                            }
1159                            case SUP:
1160                            {
1161                                    {
1162                                    sup = LT(1);
1163                                    match(SUP);
1164                                    et.track("SUP", sup); dsrd.setSuperRules(ruleids(sup.getText()));
1165                                    }
1166                                    break;
1167                            }
1168                            case EXTENSION:
1169                            {
1170                                    {
1171                                    extension = LT(1);
1172                                    match(EXTENSION);
1173                                    
1174                                    Extension ex = extension(extension.getText());
1175                                    et.track(ex.key, extension); 
1176                                    dsrd.addExtension(ex.key, ex.values); 
1177                                    
1178                                    }
1179                                    break;
1180                            }
1181                            default:
1182                            {
1183                                    break _loop1366;
1184                            }
1185                            }
1186                    } while (true);
1187                    }
1188                    match(RPAR);
1189                    
1190                    if( !isQuirksModeEnabled )
1191                    {
1192                    // semantic check: required elements
1193                    if( !et.contains("FORM") ) {
1194                    throw new SemanticException( "FORM is required", null, 0, 0 );
1195                    }
1196                    }
1197                    
1198                    return dsrd;
1199            }
1200            
1201    /**
1202         * Production for name form descriptions. It is fault-tolerant
1203         * against element ordering.
1204         *
1205         * <pre>
1206         * NameFormDescription = LPAREN WSP
1207         *    numericoid                 ; object identifier
1208         *    [ SP "NAME" SP qdescrs ]   ; short names (descriptors)
1209         *    [ SP "DESC" SP qdstring ]  ; description
1210         *    [ SP "OBSOLETE" ]          ; not active
1211         *    SP "OC" SP oid             ; structural object class
1212         *    SP "MUST" SP oids          ; attribute types
1213         *    [ SP "MAY" SP oids ]       ; attribute types
1214         *    extensions WSP RPAREN      ; extensions
1215         * </pre>
1216        */
1217            public final NameFormDescription  nameFormDescription() throws RecognitionException, TokenStreamException {
1218                    NameFormDescription nfd = new NameFormDescription();
1219                    
1220                    Token  oid = null;
1221                    Token  name = null;
1222                    Token  desc = null;
1223                    Token  obsolete = null;
1224                    Token  oc = null;
1225                    Token  must = null;
1226                    Token  may = null;
1227                    Token  extension = null;
1228                    
1229                    matchedProduction( "nameFormDescription()" );
1230                    ElementTracker et = new ElementTracker();
1231                    
1232                    
1233                    {
1234                    oid = LT(1);
1235                    match(STARTNUMERICOID);
1236                    nfd.setNumericOid(numericoid(oid.getText()));
1237                    }
1238                    {
1239                    _loop1377:
1240                    do {
1241                            switch ( LA(1)) {
1242                            case NAME:
1243                            {
1244                                    {
1245                                    name = LT(1);
1246                                    match(NAME);
1247                                    et.track("NAME", name); nfd.setNames(qdescrs(name.getText()));
1248                                    }
1249                                    break;
1250                            }
1251                            case DESC:
1252                            {
1253                                    {
1254                                    desc = LT(1);
1255                                    match(DESC);
1256                                    et.track("DESC", desc); nfd.setDescription(qdstring(desc.getText()));
1257                                    }
1258                                    break;
1259                            }
1260                            case OBSOLETE:
1261                            {
1262                                    {
1263                                    obsolete = LT(1);
1264                                    match(OBSOLETE);
1265                                    et.track("OBSOLETE", obsolete); nfd.setObsolete( true );
1266                                    }
1267                                    break;
1268                            }
1269                            case OC:
1270                            {
1271                                    {
1272                                    oc = LT(1);
1273                                    match(OC);
1274                                    et.track("OC", oc); nfd.setStructuralObjectClass(oid(oc.getText()));
1275                                    }
1276                                    break;
1277                            }
1278                            case MUST:
1279                            {
1280                                    {
1281                                    must = LT(1);
1282                                    match(MUST);
1283                                    et.track("MUST", must); nfd.setMustAttributeTypes(oids(must.getText()));
1284                                    }
1285                                    break;
1286                            }
1287                            case MAY:
1288                            {
1289                                    {
1290                                    may = LT(1);
1291                                    match(MAY);
1292                                    et.track("MAY", may); nfd.setMayAttributeTypes(oids(may.getText()));
1293                                    }
1294                                    break;
1295                            }
1296                            case EXTENSION:
1297                            {
1298                                    {
1299                                    extension = LT(1);
1300                                    match(EXTENSION);
1301                                    
1302                                    Extension ex = extension(extension.getText());
1303                                    et.track(ex.key, extension); 
1304                                    nfd.addExtension(ex.key, ex.values); 
1305                                    
1306                                    }
1307                                    break;
1308                            }
1309                            default:
1310                            {
1311                                    break _loop1377;
1312                            }
1313                            }
1314                    } while (true);
1315                    }
1316                    match(RPAR);
1317                    
1318                    if( !isQuirksModeEnabled )
1319                    {
1320                    // semantic check: required elements
1321                    if( !et.contains("MUST") ) {
1322                    throw new SemanticException( "MUST is required", null, 0, 0 );
1323                    }
1324                    if( !et.contains("OC") ) {
1325                    throw new SemanticException( "OC is required", null, 0, 0 );
1326                    }
1327                    
1328                    // semantic check: MUST and MAY must be disjoint
1329                    //List<String> aList = new ArrayList<String>( nfd.getMustAttributeTypes() );
1330                    //aList.retainAll( nfd.getMayAttributeTypes() );
1331                    //if( !aList.isEmpty() ) 
1332                    //{
1333                    //    throw new SemanticException( "MUST and MAY must be disjoint, "+aList.get( 0 )+" appears in both", null, 0, 0 );
1334                    //}
1335                    }
1336                    
1337                    return nfd;
1338            }
1339            
1340    /**
1341         * Production for comparator descriptions. It is fault-tolerant
1342         * against element ordering.
1343         *
1344         * <pre>
1345         * ComparatorDescription = LPAREN WSP
1346         *       numericoid                           ; object identifier
1347         *       [ SP "DESC" SP qdstring ]            ; description
1348         *       SP "FQCN" SP fqcn                    ; fully qualified class name
1349         *       [ SP "BYTECODE" SP base64 ]          ; optional base64 encoded bytecode
1350         *       extensions WSP RPAREN                ; extensions
1351         * 
1352         * base64          = *(4base64-char)
1353         * base64-char     = ALPHA / DIGIT / "+" / "/"
1354         * fqcn = fqcnComponent 1*( DOT fqcnComponent )
1355         * fqcnComponent = ???
1356         * </pre>
1357        */
1358            public final ComparatorDescription  comparatorDescription() throws RecognitionException, TokenStreamException {
1359                    ComparatorDescription cd = new ComparatorDescription();
1360                    
1361                    Token  oid = null;
1362                    Token  desc = null;
1363                    Token  fqcn = null;
1364                    Token  bytecode = null;
1365                    Token  extension = null;
1366                    
1367                    matchedProduction( "comparatorDescription()" );
1368                    ElementTracker et = new ElementTracker();
1369                    
1370                    
1371                    {
1372                    oid = LT(1);
1373                    match(STARTNUMERICOID);
1374                    cd.setNumericOid(numericoid(oid.getText()));
1375                    }
1376                    {
1377                    _loop1385:
1378                    do {
1379                            switch ( LA(1)) {
1380                            case DESC:
1381                            {
1382                                    {
1383                                    desc = LT(1);
1384                                    match(DESC);
1385                                    et.track("DESC", desc); cd.setDescription(qdstring(desc.getText()));
1386                                    }
1387                                    break;
1388                            }
1389                            case FQCN:
1390                            {
1391                                    {
1392                                    fqcn = LT(1);
1393                                    match(FQCN);
1394                                    et.track("FQCN", fqcn); cd.setFqcn(fqcn.getText());
1395                                    }
1396                                    break;
1397                            }
1398                            case BYTECODE:
1399                            {
1400                                    {
1401                                    bytecode = LT(1);
1402                                    match(BYTECODE);
1403                                    et.track("BYTECODE", bytecode); cd.setBytecode(bytecode.getText());
1404                                    }
1405                                    break;
1406                            }
1407                            case EXTENSION:
1408                            {
1409                                    {
1410                                    extension = LT(1);
1411                                    match(EXTENSION);
1412                                    
1413                                    Extension ex = extension(extension.getText());
1414                                    et.track(ex.key, extension); 
1415                                    cd.addExtension(ex.key, ex.values); 
1416                                    
1417                                    }
1418                                    break;
1419                            }
1420                            default:
1421                            {
1422                                    break _loop1385;
1423                            }
1424                            }
1425                    } while (true);
1426                    }
1427                    match(RPAR);
1428                    
1429                    if( !isQuirksModeEnabled )
1430                    {
1431                    // semantic check: required elements
1432                    if( !et.contains("FQCN") ) {
1433                    throw new SemanticException( "FQCN is required", null, 0, 0 );
1434                    }
1435                    
1436                    // semantic check: length should be divisible by 4
1437                    if( cd.getBytecode() != null && ( cd.getBytecode().length() % 4 != 0 ) ) {
1438                    throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
1439                    }
1440                    }
1441                    
1442                    return cd;
1443            }
1444            
1445    /**
1446         * Production for normalizer descriptions. It is fault-tolerant
1447         * against element ordering.
1448         *
1449         * <pre>
1450         * NormalizerDescription = LPAREN WSP
1451         *       numericoid                           ; object identifier
1452         *       [ SP "DESC" SP qdstring ]            ; description
1453         *       SP "FQCN" SP fqcn                    ; fully qualified class name
1454         *       [ SP "BYTECODE" SP base64 ]          ; optional base64 encoded bytecode
1455         *       extensions WSP RPAREN                ; extensions
1456         * 
1457         * base64          = *(4base64-char)
1458         * base64-char     = ALPHA / DIGIT / "+" / "/"
1459         * fqcn = fqcnComponent 1*( DOT fqcnComponent )
1460         * fqcnComponent = ???
1461         * </pre>
1462        */
1463            public final NormalizerDescription  normalizerDescription() throws RecognitionException, TokenStreamException {
1464                    NormalizerDescription nd = new NormalizerDescription();
1465                    
1466                    Token  oid = null;
1467                    Token  desc = null;
1468                    Token  fqcn = null;
1469                    Token  bytecode = null;
1470                    Token  extension = null;
1471                    
1472                    matchedProduction( "normalizerDescription()" );
1473                    ElementTracker et = new ElementTracker();
1474                    
1475                    
1476                    {
1477                    oid = LT(1);
1478                    match(STARTNUMERICOID);
1479                    nd.setNumericOid(numericoid(oid.getText()));
1480                    }
1481                    {
1482                    _loop1393:
1483                    do {
1484                            switch ( LA(1)) {
1485                            case DESC:
1486                            {
1487                                    {
1488                                    desc = LT(1);
1489                                    match(DESC);
1490                                    et.track("DESC", desc); nd.setDescription(qdstring(desc.getText()));
1491                                    }
1492                                    break;
1493                            }
1494                            case FQCN:
1495                            {
1496                                    {
1497                                    fqcn = LT(1);
1498                                    match(FQCN);
1499                                    et.track("FQCN", fqcn); nd.setFqcn(fqcn.getText());
1500                                    }
1501                                    break;
1502                            }
1503                            case BYTECODE:
1504                            {
1505                                    {
1506                                    bytecode = LT(1);
1507                                    match(BYTECODE);
1508                                    et.track("BYTECODE", bytecode); nd.setBytecode(bytecode.getText());
1509                                    }
1510                                    break;
1511                            }
1512                            case EXTENSION:
1513                            {
1514                                    {
1515                                    extension = LT(1);
1516                                    match(EXTENSION);
1517                                    
1518                                    Extension ex = extension(extension.getText());
1519                                    et.track(ex.key, extension); 
1520                                    nd.addExtension(ex.key, ex.values); 
1521                                    
1522                                    }
1523                                    break;
1524                            }
1525                            default:
1526                            {
1527                                    break _loop1393;
1528                            }
1529                            }
1530                    } while (true);
1531                    }
1532                    match(RPAR);
1533                    
1534                    if( !isQuirksModeEnabled )
1535                    {
1536                    // semantic check: required elements
1537                    if( !et.contains("FQCN") ) {
1538                    throw new SemanticException( "FQCN is required", null, 0, 0 );
1539                    }
1540                    
1541                    // semantic check: length should be divisible by 4
1542                    if( nd.getBytecode() != null && ( nd.getBytecode().length() % 4 != 0 ) ) {
1543                    throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
1544                    }     
1545                    }   
1546                    
1547                    return nd;
1548            }
1549            
1550    /**
1551         * Production for syntax checker descriptions. It is fault-tolerant
1552         * against element ordering.
1553         *
1554         * <pre>
1555         * SyntaxCheckerDescription = LPAREN WSP
1556         *       numericoid                           ; object identifier
1557         *       [ SP "DESC" SP qdstring ]            ; description
1558         *       SP "FQCN" SP fqcn                    ; fully qualified class name
1559         *       [ SP "BYTECODE" SP base64 ]          ; optional base64 encoded bytecode
1560         *       extensions WSP RPAREN                ; extensions
1561         * 
1562         * base64          = *(4base64-char)
1563         * base64-char     = ALPHA / DIGIT / "+" / "/"
1564         * fqcn = fqcnComponent 1*( DOT fqcnComponent )
1565         * fqcnComponent = ???
1566         * </pre>
1567        */
1568            public final SyntaxCheckerDescription  syntaxCheckerDescription() throws RecognitionException, TokenStreamException {
1569                    SyntaxCheckerDescription scd = new SyntaxCheckerDescription();
1570                    
1571                    Token  oid = null;
1572                    Token  desc = null;
1573                    Token  fqcn = null;
1574                    Token  bytecode = null;
1575                    Token  extension = null;
1576                    
1577                    matchedProduction( "syntaxCheckerDescription()" );
1578                    ElementTracker et = new ElementTracker();
1579                    
1580                    
1581                    {
1582                    oid = LT(1);
1583                    match(STARTNUMERICOID);
1584                    scd.setNumericOid(numericoid(oid.getText()));
1585                    }
1586                    {
1587                    _loop1401:
1588                    do {
1589                            switch ( LA(1)) {
1590                            case DESC:
1591                            {
1592                                    {
1593                                    desc = LT(1);
1594                                    match(DESC);
1595                                    et.track("DESC", desc); scd.setDescription(qdstring(desc.getText()));
1596                                    }
1597                                    break;
1598                            }
1599                            case FQCN:
1600                            {
1601                                    {
1602                                    fqcn = LT(1);
1603                                    match(FQCN);
1604                                    et.track("FQCN", fqcn); scd.setFqcn(fqcn.getText());
1605                                    }
1606                                    break;
1607                            }
1608                            case BYTECODE:
1609                            {
1610                                    {
1611                                    bytecode = LT(1);
1612                                    match(BYTECODE);
1613                                    et.track("BYTECODE", bytecode); scd.setBytecode(bytecode.getText());
1614                                    }
1615                                    break;
1616                            }
1617                            case EXTENSION:
1618                            {
1619                                    {
1620                                    extension = LT(1);
1621                                    match(EXTENSION);
1622                                    
1623                                    Extension ex = extension(extension.getText());
1624                                    et.track(ex.key, extension); 
1625                                    scd.addExtension(ex.key, ex.values); 
1626                                    
1627                                    }
1628                                    break;
1629                            }
1630                            default:
1631                            {
1632                                    break _loop1401;
1633                            }
1634                            }
1635                    } while (true);
1636                    }
1637                    match(RPAR);
1638                    
1639                    if( !isQuirksModeEnabled )
1640                    {
1641                    // semantic check: required elements
1642                    if( !et.contains("FQCN") ) {
1643                    throw new SemanticException( "FQCN is required", null, 0, 0 );
1644                    }
1645                    
1646                    // semantic check: length should be divisible by 4
1647                    if( scd.getBytecode() != null && ( scd.getBytecode().length() % 4 != 0 ) ) {
1648                    throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
1649                    }  
1650                    }      
1651                    
1652                    return scd;
1653            }
1654            
1655            public final NoidLen  noidlen(
1656                    String s
1657            ) throws RecognitionException, TokenStreamException {
1658                    NoidLen noidlen;
1659                    
1660                    
1661                    matchedProduction( "noidlen()" );
1662                    AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
1663                    AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
1664                    parser.setParserMonitor(monitor);
1665                    noidlen = isQuirksModeEnabled ? parser.quirksNoidlen() : parser.noidlen();
1666                    
1667                    
1668                    return noidlen;
1669            }
1670            
1671            public final Extension  extension(
1672                    String s
1673            ) throws RecognitionException, TokenStreamException {
1674                    Extension extension;
1675                    
1676                    
1677                    matchedProduction( "extension()" );
1678                    AntlrSchemaExtensionLexer lexer = new AntlrSchemaExtensionLexer(new StringReader(s));
1679                    AntlrSchemaExtensionParser parser = new AntlrSchemaExtensionParser(lexer);
1680                    extension = parser.extension();
1681                    
1682                    
1683                    return extension;
1684            }
1685            
1686            public final String  numericoid(
1687                    String s
1688            ) throws RecognitionException, TokenStreamException {
1689                    String numericoid;
1690                    
1691                    
1692                    matchedProduction( "numericoid()");
1693                    if(isQuirksModeEnabled)
1694                    {
1695                    numericoid = oid(s);
1696                    }
1697                    else
1698                    {
1699                                    AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
1700                                    AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
1701                                    parser.setParserMonitor(monitor);
1702                                    numericoid = parser.numericoid();
1703                    }
1704                    
1705                    
1706                    return numericoid;
1707            }
1708            
1709            public final String  oid(
1710                    String s
1711            ) throws RecognitionException, TokenStreamException {
1712                    String oid;
1713                    
1714                    
1715                    matchedProduction( "oid()" );
1716                    List<String> oids = oids(s);
1717                    if( oids.size() != 1 ) 
1718                    {
1719                    throw new SemanticException( "Exactly one OID expected", null, 0, 0 );
1720                    }
1721                    oid = oids.get(0);
1722                    
1723                    
1724                    return oid;
1725            }
1726            
1727            public final List<String>  oids(
1728                    String s
1729            ) throws RecognitionException, TokenStreamException {
1730                    List<String> oids;
1731                    
1732                    
1733                    matchedProduction( "oids()" );
1734                    if(isQuirksModeEnabled)
1735                    {
1736                    oids = qdescrs(s);
1737                    }
1738                    else
1739                    {
1740                                    AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
1741                                    AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
1742                                    parser.setParserMonitor(monitor);
1743                                    oids = parser.oids();
1744                                }
1745                    
1746                    
1747                    return oids;
1748            }
1749            
1750            public final String  qdescr(
1751                    String s
1752            ) throws RecognitionException, TokenStreamException {
1753                    String qdescr;
1754                    
1755                    
1756                    matchedProduction( "qdescr()" );
1757                    List<String> qdescrs = qdescrs(s);
1758                    if( qdescrs.size() != 1 ) 
1759                    {
1760                    throw new SemanticException( "Exactly one qdescrs expected", null, 0, 0 );
1761                    }
1762                    qdescr = qdescrs.get(0);
1763                    
1764                    
1765                    return qdescr;
1766            }
1767            
1768            public final List<String>  qdescrs(
1769                    String s
1770            ) throws RecognitionException, TokenStreamException {
1771                    List<String> qdescrs;
1772                    
1773                    
1774                    matchedProduction( "qdescrs()" );
1775                    AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
1776                    AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
1777                    parser.setParserMonitor(monitor);
1778                    qdescrs = isQuirksModeEnabled ? parser.quirksQdescrs() : parser.qdescrs();
1779                    
1780                    
1781                    return qdescrs;
1782            }
1783            
1784            public final String  qdstring(
1785                    String s
1786            ) throws RecognitionException, TokenStreamException {
1787                    String qdstring;
1788                    
1789                    
1790                    matchedProduction( "qdstring()" );
1791                    List<String> qdstrings = qdstrings(s);
1792                    if( qdstrings.size() != 1 ) 
1793                    {
1794                    throw new SemanticException( "Exactly one qdstrings expected", null, 0, 0 );
1795                    }
1796                    qdstring = qdstrings.get(0);
1797                    
1798                    
1799                    return qdstring;
1800            }
1801            
1802            public final List<String>  qdstrings(
1803                    String s
1804            ) throws RecognitionException, TokenStreamException {
1805                    List<String> qdstrings;
1806                    
1807                    
1808                    matchedProduction( "qdstrings()" );
1809                    AntlrSchemaQdstringLexer lexer = new AntlrSchemaQdstringLexer(new StringReader(s));
1810                    AntlrSchemaQdstringParser parser = new AntlrSchemaQdstringParser(lexer);
1811                    parser.setParserMonitor(monitor);
1812                    qdstrings = parser.qdstrings();
1813                    
1814                    
1815                    return qdstrings;
1816            }
1817            
1818            public final Integer  ruleid(
1819                    String s
1820            ) throws RecognitionException, TokenStreamException {
1821                    Integer ruleid;
1822                    
1823                    
1824                    matchedProduction( "ruleid()" );
1825                    AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
1826                    AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
1827                    parser.setParserMonitor(monitor);
1828                    ruleid = parser.ruleid();
1829                    
1830                    
1831                    return ruleid;
1832            }
1833            
1834            public final List<Integer>  ruleids(
1835                    String s
1836            ) throws RecognitionException, TokenStreamException {
1837                    List<Integer> ruleids;
1838                    
1839                    
1840                    matchedProduction( "ruleids()" );
1841                    AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
1842                    AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
1843                    parser.setParserMonitor(monitor);
1844                    ruleids = parser.ruleids();
1845                    
1846                    
1847                    return ruleids;
1848            }
1849            
1850            
1851            public static final String[] _tokenNames = {
1852                    "<0>",
1853                    "EOF",
1854                    "<2>",
1855                    "NULL_TREE_LOOKAHEAD",
1856                    "WHSP",
1857                    "LPAR",
1858                    "RPAR",
1859                    "QUOTE",
1860                    "DOLLAR",
1861                    "LBRACKET",
1862                    "RBRACKET",
1863                    "LEN",
1864                    "SINGLE_VALUE",
1865                    "COLLECTIVE",
1866                    "NO_USER_MODIFICATION",
1867                    "OBSOLETE",
1868                    "ABSTRACT",
1869                    "STRUCTURAL",
1870                    "AUXILIARY",
1871                    "OBJECTIDENTIFIER",
1872                    "OBJECTCLASS",
1873                    "ATTRIBUTETYPE",
1874                    "STARTNUMERICOID",
1875                    "NAME",
1876                    "DESC",
1877                    "SUP",
1878                    "MUST",
1879                    "MAY",
1880                    "AUX",
1881                    "NOT",
1882                    "FORM",
1883                    "OC",
1884                    "EQUALITY",
1885                    "ORDERING",
1886                    "SUBSTR",
1887                    "SYNTAX",
1888                    "APPLIES",
1889                    "EXTENSION",
1890                    "FQCN",
1891                    "BYTECODE",
1892                    "AUX_OR_AUXILIARY",
1893                    "VALUES",
1894                    "VALUE",
1895                    "UNQUOTED_STRING",
1896                    "QUOTED_STRING",
1897                    "FQCN_VALUE",
1898                    "FQCN_IDENTIFIER",
1899                    "FQCN_LETTER",
1900                    "FQCN_LETTERORDIGIT",
1901                    "BYTECODE_VALUE",
1902                    "USAGE",
1903                    "USER_APPLICATIONS",
1904                    "DIRECTORY_OPERATION",
1905                    "DISTRIBUTED_OPERATION",
1906                    "DSA_OPERATION"
1907            };
1908            
1909            
1910            }