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