View Javadoc
1   // $ANTLR 2.7.7 (20060906): "distinguishedName.g" -> "AntlrDnParser.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.name;
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.exception.LdapInvalidDnException;
31  import javax.naming.NameParser;
32  import org.apache.directory.api.ldap.model.entry.StringValue;
33  import org.apache.directory.api.ldap.model.entry.BinaryValue;
34  import org.apache.directory.api.ldap.model.schema.parsers.ParserMonitor;
35  import org.apache.directory.api.util.Strings;
36  
37  
38  import antlr.TokenBuffer;
39  import antlr.TokenStreamException;
40  import antlr.TokenStreamIOException;
41  import antlr.ANTLRException;
42  import antlr.LLkParser;
43  import antlr.Token;
44  import antlr.TokenStream;
45  import antlr.RecognitionException;
46  import antlr.NoViableAltException;
47  import antlr.MismatchedTokenException;
48  import antlr.SemanticException;
49  import antlr.ParserSharedInputState;
50  import antlr.collections.impl.BitSet;
51  
52  /**
53   * An antlr generated Dn parser.
54   *
55   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
56   */
57  public class AntlrDnParser extends antlr.LLkParser       implements AntlrDnTokenTypes
58   {
59  
60      private ParserMonitor monitor = null;
61      public void setParserMonitor( ParserMonitor monitor )
62      {
63          this.monitor = monitor;
64      }
65      private void matchedProduction( String msg )
66      {
67          if ( null != monitor )
68          {
69              monitor.matchedProduction( msg );
70          }
71      }
72      static class UpAndNormValue
73      {
74          Object value = "";
75          String rawValue = "";
76  		int lastEscapedSpace = -1;
77      }
78  
79  protected AntlrDnParser(TokenBuffer tokenBuf, int k) {
80    super(tokenBuf,k);
81    tokenNames = _tokenNames;
82  }
83  
84  public AntlrDnParser(TokenBuffer tokenBuf) {
85    this(tokenBuf,3);
86  }
87  
88  protected AntlrDnParser(TokenStream lexer, int k) {
89    super(lexer,k);
90    tokenNames = _tokenNames;
91  }
92  
93  public AntlrDnParser(TokenStream lexer) {
94    this(lexer,3);
95  }
96  
97  public AntlrDnParser(ParserSharedInputState state) {
98    super(state,3);
99    tokenNames = _tokenNames;
100 }
101 
102 /**
103      * Parses an Dn string.
104      *
105      * RFC 4514, Section 3
106      * distinguishedName = [ relativeDistinguishedName
107      *     *( COMMA relativeDistinguishedName ) ]
108      *
109      * RFC 2253, Section 3
110      * distinguishedName = [name] 
111      * name       = name-component *("," name-component)
112      *
113      * RFC 1779, Section 2.3
114      * &lt;name&gt; ::= &lt;name-component&gt; ( &lt;spaced-separator&gt; )
115      *        | &lt;name-component&gt; &lt;spaced-separator&gt; &lt;name&gt;
116      * &lt;spaced-separator&gt; ::= &lt;optional-space&gt;
117      *             &lt;separator&gt;
118      *             &lt;optional-space&gt;
119      * &lt;separator&gt; ::=  "," | ";"
120      * &lt;optional-space&gt; ::= ( &lt;CR&gt; ) *( " " )
121      *
122      */
123 	public final void distinguishedName(
124 		Dn dn
125 	) throws RecognitionException, TokenStreamException {
126 		
127 		
128 		matchedProduction( "distinguishedName()" );
129 		Rdn rdn = null;
130 		
131 		
132 		{
133 		switch ( LA(1)) {
134 		case SPACE:
135 		case NUMERICOID:
136 		case ALPHA:
137 		{
138 			rdn=relativeDistinguishedName(new Rdn());
139 			
140 			try
141 			{ 
142 			dn.add( rdn ); 
143 			}
144 			catch ( LdapInvalidDnException lide )
145 			{
146 			// Do nothing, can't get an exception here
147 			} 
148 			
149 			rdn=null; 
150 			
151 			{
152 			_loop53:
153 			do {
154 				if ((LA(1)==COMMA||LA(1)==SEMI)) {
155 					{
156 					switch ( LA(1)) {
157 					case COMMA:
158 					{
159 						match(COMMA);
160 						break;
161 					}
162 					case SEMI:
163 					{
164 						match(SEMI);
165 						break;
166 					}
167 					default:
168 					{
169 						throw new NoViableAltException(LT(1), getFilename());
170 					}
171 					}
172 					}
173 					rdn=relativeDistinguishedName(new Rdn());
174 					
175 					try
176 					{ 
177 					dn.add( rdn ); 
178 					}
179 					catch ( LdapInvalidDnException lide )
180 					{
181 					// Do nothing, can't get an exception here
182 					} 
183 					
184 					rdn=null;
185 					
186 				}
187 				else {
188 					break _loop53;
189 				}
190 				
191 			} while (true);
192 			}
193 			match(Token.EOF_TYPE);
194 			break;
195 		}
196 		case EOF:
197 		{
198 			break;
199 		}
200 		default:
201 		{
202 			throw new NoViableAltException(LT(1), getFilename());
203 		}
204 		}
205 		}
206 	}
207 	
208 /**
209      * Parses an Rdn string.
210      *
211      * RFC 4514, Section 3
212      * relativeDistinguishedName = attributeTypeAndValue
213      *     *( PLUS attributeTypeAndValue )
214      *
215      * RFC 2253, Section 3
216      * name-component = attributeTypeAndValue *("+" attributeTypeAndValue)
217      *
218      * RFC 1779, Section 2.3
219      * &lt;name-component&gt; ::= &lt;attribute&gt;
220      *     | &lt;attribute&gt; &lt;optional-space&gt; "+"
221      *       &lt;optional-space&gt; &lt;name-component&gt;
222      *
223      */
224 	public final Rdn  relativeDistinguishedName(
225 		Rdn initialRdn
226 	) throws RecognitionException, TokenStreamException {
227 		Rdn rdn;
228 		
229 		
230 		matchedProduction( "relativeDistinguishedName()" );
231 		rdn = initialRdn;
232 		String tmp;
233 		String upName = "";
234 		
235 		
236 		{
237 		tmp=attributeTypeAndValue(rdn);
238 		
239 		upName += tmp;
240 		
241 		{
242 		_loop62:
243 		do {
244 			if ((LA(1)==PLUS)) {
245 				match(PLUS);
246 				upName += "+";
247 				tmp=attributeTypeAndValue(rdn);
248 				
249 				upName += tmp;
250 				
251 			}
252 			else {
253 				break _loop62;
254 			}
255 			
256 		} while (true);
257 		}
258 		}
259 		
260 		rdn.normalize();
261 		rdn.setUpName( upName );
262 		
263 		return rdn;
264 	}
265 	
266 /**
267      * Parses an Dn string.
268      *
269      * RFC 4514, Section 3
270      * distinguishedName = [ relativeDistinguishedName
271      *     *( COMMA relativeDistinguishedName ) ]
272      *
273      * RFC 2253, Section 3
274      * distinguishedName = [name] 
275      * name       = name-component *("," name-component)
276      *
277      * RFC 1779, Section 2.3
278      * &lt;name&gt; ::= &lt;name-component&gt; ( &lt;spaced-separator&gt; )
279      *        | &lt;name-component&gt; &lt;spaced-separator&gt; &lt;name&gt;
280      * &lt;spaced-separator&gt; ::= &lt;optional-space&gt;
281      *             &lt;separator&gt;
282      *             &lt;optional-space&gt;
283      * &lt;separator&gt; ::=  "," | ";"
284      * &lt;optional-space&gt; ::= ( &lt;CR&gt; ) *( " " )
285      *
286      */
287 	public final void relativeDistinguishedNames(
288 		List<Rdn> rdns
289 	) throws RecognitionException, TokenStreamException {
290 		
291 		
292 		matchedProduction( "relativeDistinguishedNames()" );
293 		Rdn rdn = null;
294 		
295 		
296 		{
297 		switch ( LA(1)) {
298 		case SPACE:
299 		case NUMERICOID:
300 		case ALPHA:
301 		{
302 			rdn=relativeDistinguishedName(new Rdn());
303 			
304 			rdns.add( rdn );
305 			
306 			{
307 			_loop58:
308 			do {
309 				if ((LA(1)==COMMA||LA(1)==SEMI)) {
310 					{
311 					switch ( LA(1)) {
312 					case COMMA:
313 					{
314 						match(COMMA);
315 						break;
316 					}
317 					case SEMI:
318 					{
319 						match(SEMI);
320 						break;
321 					}
322 					default:
323 					{
324 						throw new NoViableAltException(LT(1), getFilename());
325 					}
326 					}
327 					}
328 					rdn=relativeDistinguishedName(new Rdn());
329 					
330 					rdns.add( rdn ); 
331 					
332 				}
333 				else {
334 					break _loop58;
335 				}
336 				
337 			} while (true);
338 			}
339 			match(Token.EOF_TYPE);
340 			break;
341 		}
342 		case EOF:
343 		{
344 			break;
345 		}
346 		default:
347 		{
348 			throw new NoViableAltException(LT(1), getFilename());
349 		}
350 		}
351 		}
352 	}
353 	
354 /**
355      * RFC 4514, Section 3
356      * attributeTypeAndValue = attributeType EQUALS attributeValue
357      *
358      * RFC 2253, Section 3
359      * attributeTypeAndValue = attributeType "=" attributeValue
360      *
361      */
362 	public final String  attributeTypeAndValue(
363 		Rdn rdn
364 	) throws RecognitionException, TokenStreamException {
365 		String upName = "";
366 		
367 		
368 		matchedProduction( "attributeTypeAndValue()" );
369 		String type = null;
370 		UpAndNormValue value = new UpAndNormValue();
371 		String upValue = null;
372 		
373 		
374 		{
375 		{
376 		_loop66:
377 		do {
378 			if ((LA(1)==SPACE)) {
379 				match(SPACE);
380 				upName += " ";
381 			}
382 			else {
383 				break _loop66;
384 			}
385 			
386 		} while (true);
387 		}
388 		type=attributeType();
389 		upName += type;
390 		{
391 		_loop68:
392 		do {
393 			if ((LA(1)==SPACE)) {
394 				match(SPACE);
395 				upName += " ";
396 			}
397 			else {
398 				break _loop68;
399 			}
400 			
401 		} while (true);
402 		}
403 		match(EQUALS);
404 		upName += "=";
405 		{
406 		_loop70:
407 		do {
408 			if ((LA(1)==SPACE)) {
409 				match(SPACE);
410 				
411 				upName += " "; 
412 				
413 				if ( upValue == null )
414 				{
415 				upValue = " ";
416 				}
417 				else
418 				{
419 				upValue += " "; 
420 				} 
421 				
422 			}
423 			else {
424 				break _loop70;
425 			}
426 			
427 		} while (true);
428 		}
429 		attributeValue(value);
430 		
431 		try
432 		{
433 		upName += value.rawValue;
434 		Ava ava = null;
435 		
436 		if ( value.value instanceof String )
437 		{
438 		if ( upValue != null )
439 		{
440 		value.rawValue = upValue + value.rawValue;
441 		}
442 		
443 							int start = 0;
444 				
445 							for ( int pos = 0; pos < value.rawValue.length(); pos++ )
446 							{
447 							    if ( value.rawValue.charAt( pos ) == ' ' )
448 							    {
449 							        start++;
450 							    }
451 							    else
452 							    {
453 							        break;
454 							    }
455 							}
456 				
457 							boolean escape = false;
458 							int lastEscapedSpace = -1;
459 							
460 							for ( int pos = start; pos< value.rawValue.length(); pos++ )
461 							{
462 							    if ( escape )
463 							    {
464 							        escape = false;
465 				        
466 							        if ( value.rawValue.charAt( pos ) == ' ' )
467 							        {
468 							            lastEscapedSpace = pos;
469 							        }
470 							    }
471 							    else if ( value.rawValue.charAt( pos ) == '\\' )
472 							    {
473 							        escape = true;
474 							    }
475 							}
476 				
477 							// Remove spaces from the right if needed
478 							int pos = value.rawValue.length() - 1;
479 				
480 							while ( ( value.rawValue.charAt( pos ) == ' ' ) && ( pos > lastEscapedSpace ) )
481 							{
482 							    pos--;
483 							}
484 							
485 							String trimmedValue = value.rawValue;
486 							
487 							if ( ( start > 0 ) || ( pos + 1 < value.rawValue.length() ) )
488 							{
489 								trimmedValue = value.rawValue.substring( start, pos + 1 );
490 							}
491 							
492 							Object unescapedValue = Rdn.unescapeValue( trimmedValue );
493 		
494 		if ( unescapedValue instanceof String )
495 		{
496 		ava = new Ava(
497 		type,
498 		type,
499 		new StringValue( trimmedValue, (String)unescapedValue ),
500 		upName
501 		);
502 		}
503 		else
504 		{
505 		ava = new Ava(
506 		type,
507 		type,
508 		new BinaryValue( (byte[])unescapedValue ),
509 		upName
510 		);
511 		}
512 		}
513 		else
514 		{
515 		ava = new Ava(
516 		type,
517 		type,
518 		new BinaryValue( (byte[])value.value ), 
519 		upName
520 		);
521 		}
522 		
523 		rdn.addAVA( null, ava );
524 		}
525 		catch ( LdapInvalidDnException e )
526 		{
527 		throw new SemanticException( e.getMessage() );
528 		} 
529 		
530 		}
531 		return upName;
532 	}
533 	
534 /**
535      * RFC 4514 Section 3
536      *
537      * attributeType = descr / numericoid
538      *
539      */
540 	public final String  attributeType() throws RecognitionException, TokenStreamException {
541 		String attributeType;
542 		
543 		
544 		matchedProduction( "attributeType()" );
545 		
546 		
547 		{
548 		switch ( LA(1)) {
549 		case ALPHA:
550 		{
551 			attributeType=descr();
552 			break;
553 		}
554 		case NUMERICOID:
555 		{
556 			attributeType=numericoid();
557 			break;
558 		}
559 		default:
560 		{
561 			throw new NoViableAltException(LT(1), getFilename());
562 		}
563 		}
564 		}
565 		return attributeType;
566 	}
567 	
568 /**
569      * RFC 4514, Section 3
570      * attributeValue = string / hexstring
571      *
572      * RFC 2253, Section 3
573      * attributeValue = string
574      * string     = *( stringchar / pair )
575      *              / "#" hexstring
576      *              / QUOTATION *( quotechar / pair ) QUOTATION ; only from v2
577      * 
578      */
579 	public final void attributeValue(
580 		UpAndNormValue value
581 	) throws RecognitionException, TokenStreamException {
582 		
583 		
584 		matchedProduction( "attributeValue()" );
585 		
586 		
587 		{
588 		switch ( LA(1)) {
589 		case DQUOTE:
590 		{
591 			{
592 			quotestring(value);
593 			{
594 			_loop81:
595 			do {
596 				if ((LA(1)==SPACE)) {
597 					match(SPACE);
598 					value.rawValue += " ";
599 				}
600 				else {
601 					break _loop81;
602 				}
603 				
604 			} while (true);
605 			}
606 			}
607 			break;
608 		}
609 		case EQUALS:
610 		case HYPHEN:
611 		case UNDERSCORE:
612 		case NUMERICOID:
613 		case DIGIT:
614 		case ALPHA:
615 		case HEXPAIR:
616 		case ESC:
617 		case ESCESC:
618 		case ESCSHARP:
619 		case UTFMB:
620 		case LUTF1_REST:
621 		{
622 			string(value);
623 			break;
624 		}
625 		case HEXVALUE:
626 		{
627 			{
628 			hexstring(value);
629 			{
630 			_loop84:
631 			do {
632 				if ((LA(1)==SPACE)) {
633 					match(SPACE);
634 					value.rawValue += " ";
635 				}
636 				else {
637 					break _loop84;
638 				}
639 				
640 			} while (true);
641 			}
642 			}
643 			break;
644 		}
645 		case EOF:
646 		case COMMA:
647 		case PLUS:
648 		case SEMI:
649 		{
650 			break;
651 		}
652 		default:
653 		{
654 			throw new NoViableAltException(LT(1), getFilename());
655 		}
656 		}
657 		}
658 	}
659 	
660 /**
661      * RFC 4512 Section 1.4
662      *
663      * descr = keystring
664      * keystring = leadkeychar *keychar
665      * leadkeychar = ALPHA
666      * keychar = ALPHA / DIGIT / HYPHEN
667      *
668      * We additionally add UNDERSCORE because some servers allow them.
669      *
670      */
671 	public final String  descr() throws RecognitionException, TokenStreamException {
672 		String descr;
673 		
674 		Token  leadkeychar = null;
675 		Token  alpha = null;
676 		Token  digit = null;
677 		Token  hyphen = null;
678 		Token  underscore = null;
679 		
680 		matchedProduction( "descr()" );
681 		
682 		
683 		leadkeychar = LT(1);
684 		match(ALPHA);
685 		descr = leadkeychar.getText();
686 		{
687 		_loop75:
688 		do {
689 			switch ( LA(1)) {
690 			case ALPHA:
691 			{
692 				alpha = LT(1);
693 				match(ALPHA);
694 				descr += alpha.getText();
695 				break;
696 			}
697 			case DIGIT:
698 			{
699 				digit = LT(1);
700 				match(DIGIT);
701 				descr += digit.getText();
702 				break;
703 			}
704 			case HYPHEN:
705 			{
706 				hyphen = LT(1);
707 				match(HYPHEN);
708 				descr += hyphen.getText();
709 				break;
710 			}
711 			case UNDERSCORE:
712 			{
713 				underscore = LT(1);
714 				match(UNDERSCORE);
715 				descr += underscore.getText();
716 				break;
717 			}
718 			default:
719 			{
720 				break _loop75;
721 			}
722 			}
723 		} while (true);
724 		}
725 		return descr;
726 	}
727 	
728 /**
729      * RFC 4512 Section 1.4
730      *
731      * numericoid = number 1*( DOT number )
732      * number  = DIGIT / ( LDIGIT 1*DIGIT )
733      * DIGIT   = %x30 / LDIGIT       ; "0"-"9"
734      * LDIGIT  = %x31-39             ; "1"-"9"
735      *
736      */
737 	public final String  numericoid() throws RecognitionException, TokenStreamException {
738 		String numericoid = "";
739 		
740 		Token  noid = null;
741 		
742 		matchedProduction( "numericoid()" );
743 		
744 		
745 		noid = LT(1);
746 		match(NUMERICOID);
747 		numericoid += noid.getText();
748 		return numericoid;
749 	}
750 	
751 /**
752      * RFC 2253, Section 3
753      *              / QUOTATION *( quotechar / pair ) QUOTATION ; only from v2
754      * quotechar     = &lt;any character except "\" or QUOTATION &gt;
755      *
756      */
757 	public final void quotestring(
758 		UpAndNormValue value
759 	) throws RecognitionException, TokenStreamException {
760 		
761 		Token  dq1 = null;
762 		Token  s = null;
763 		Token  dq2 = null;
764 		
765 		matchedProduction( "quotestring()" );
766 		org.apache.directory.api.util.ByteBuffer bb = new org.apache.directory.api.util.ByteBuffer();
767 		byte[] bytes;
768 		
769 		
770 		{
771 		dq1 = LT(1);
772 		match(DQUOTE);
773 		value.rawValue += dq1.getText();
774 		{
775 		_loop90:
776 		do {
777 			switch ( LA(1)) {
778 			case COMMA:
779 			case EQUALS:
780 			case PLUS:
781 			case HYPHEN:
782 			case UNDERSCORE:
783 			case SEMI:
784 			case LANGLE:
785 			case RANGLE:
786 			case SPACE:
787 			case NUMERICOID_OR_ALPHA_OR_DIGIT:
788 			case NUMERICOID:
789 			case DOT:
790 			case NUMBER:
791 			case LDIGIT:
792 			case DIGIT:
793 			case ALPHA:
794 			case HEXPAIR_OR_ESCESC_ESCSHARP_OR_ESC:
795 			case HEX:
796 			case HEXVALUE_OR_SHARP:
797 			case HEXVALUE:
798 			case SHARP:
799 			case UTFMB:
800 			case LUTF1_REST:
801 			{
802 				{
803 				{
804 				s = LT(1);
805 				match(_tokenSet_0);
806 				}
807 				
808 				value.rawValue += s.getText();
809 				bb.append( Strings.getBytesUtf8( s.getText() ) );
810 				
811 				}
812 				break;
813 			}
814 			case HEXPAIR:
815 			case ESC:
816 			case ESCESC:
817 			case ESCSHARP:
818 			{
819 				bytes=pair(value);
820 				bb.append( bytes );
821 				break;
822 			}
823 			default:
824 			{
825 				break _loop90;
826 			}
827 			}
828 		} while (true);
829 		}
830 		dq2 = LT(1);
831 		match(DQUOTE);
832 		value.rawValue += dq2.getText();
833 		}
834 		
835 		String string = Strings.utf8ToString( bb.copyOfUsedBytes() );
836 		value.value = string;
837 		
838 	}
839 	
840 /**
841      * RFC 4514 Section 3
842      *
843      * ; The following characters are to be escaped when they appear
844      * ; in the value to be encoded: ESC, one of &lt;escaped&gt;, leading
845      * ; SHARP or SPACE, trailing SPACE, and NULL.
846      * string =   [ ( leadchar / pair ) [ *( stringchar / pair )
847      *    ( trailchar / pair ) ] ]
848      *
849      */
850 	public final void string(
851 		UpAndNormValue value
852 	) throws RecognitionException, TokenStreamException {
853 		
854 		
855 		matchedProduction( "string()" );
856 		org.apache.directory.api.util.ByteBuffer bb = new org.apache.directory.api.util.ByteBuffer();
857 		String tmp;
858 		byte[] bytes;
859 		
860 		
861 		{
862 		{
863 		switch ( LA(1)) {
864 		case EQUALS:
865 		case HYPHEN:
866 		case UNDERSCORE:
867 		case NUMERICOID:
868 		case DIGIT:
869 		case ALPHA:
870 		case LUTF1_REST:
871 		{
872 			tmp=lutf1();
873 			
874 			value.rawValue += tmp;
875 			bb.append( Strings.getBytesUtf8( tmp ) );
876 			
877 			break;
878 		}
879 		case UTFMB:
880 		{
881 			tmp=utfmb();
882 			
883 			value.rawValue += tmp;
884 			bb.append( Strings.getBytesUtf8( tmp ) );
885 			
886 			break;
887 		}
888 		case HEXPAIR:
889 		case ESC:
890 		case ESCESC:
891 		case ESCSHARP:
892 		{
893 			bytes=pair(value);
894 			
895 							bb.append( bytes );
896 						
897 			break;
898 		}
899 		default:
900 		{
901 			throw new NoViableAltException(LT(1), getFilename());
902 		}
903 		}
904 		}
905 		{
906 		_loop96:
907 		do {
908 			switch ( LA(1)) {
909 			case EQUALS:
910 			case HYPHEN:
911 			case UNDERSCORE:
912 			case SPACE:
913 			case NUMERICOID:
914 			case DIGIT:
915 			case ALPHA:
916 			case HEXVALUE:
917 			case SHARP:
918 			case LUTF1_REST:
919 			{
920 				tmp=sutf1();
921 				
922 				value.rawValue += tmp;
923 				bb.append( Strings.getBytesUtf8( tmp ) );
924 				
925 				break;
926 			}
927 			case UTFMB:
928 			{
929 				tmp=utfmb();
930 				
931 				value.rawValue += tmp;
932 				bb.append( Strings.getBytesUtf8( tmp ) );
933 				
934 				break;
935 			}
936 			case HEXPAIR:
937 			case ESC:
938 			case ESCESC:
939 			case ESCSHARP:
940 			{
941 				bytes=pair(value);
942 				
943 								bb.append( bytes ); 
944 							
945 				break;
946 			}
947 			default:
948 			{
949 				break _loop96;
950 			}
951 			}
952 		} while (true);
953 		}
954 		}
955 		
956 				/*
957 		String string = Strings.utf8ToString( bb.copyOfUsedBytes() );
958 		
959 		// trim trailing space characters manually
960 		// don't know how to tell antlr that the last char mustn't be a space.
961 		int rawIndex = value.rawValue.length();
962 		while ( string.length() > 0 && rawIndex > 1 
963 		&& value.rawValue.charAt( rawIndex - 1 ) == ' ' 
964 		&& value.rawValue.charAt( rawIndex - 2 ) != '\\' )
965 		{
966 		string = string.substring( 0, string.length() - 1 );
967 		rawIndex--;
968 		}
969 		
970 		value.value = string;
971 				*/
972 		
973 	}
974 	
975 /**
976      * RFC 4514 Section 3
977      *
978      * hexstring = SHARP 1*hexpair
979      *
980      * If in &lt;hexstring&gt; form, a BER representation can be obtained from
981      * converting each &lt;hexpair&gt; of the &lt;hexstring&gt; to the octet indicated
982      * by the &lt;hexpair&gt;.
983      *
984      */
985 	public final void hexstring(
986 		UpAndNormValue value
987 	) throws RecognitionException, TokenStreamException {
988 		
989 		Token  hexValue = null;
990 		
991 		matchedProduction( "hexstring()" );
992 		
993 		
994 		hexValue = LT(1);
995 		match(HEXVALUE);
996 		
997 		// convert to byte[]
998 		value.rawValue = "#" + hexValue.getText();
999 		value.value = Strings.toByteArray( hexValue.getText() ); 
1000 		
1001 	}
1002 	
1003 /**
1004      * RFC 4514, Section 3
1005      * pair = ESC ( ESC / special / hexpair )
1006      * special = escaped / SPACE / SHARP / EQUALS
1007      * escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
1008      * hexpair = HEX HEX
1009      *
1010      * If in &lt;string&gt; form, a LDAP string representation asserted value can
1011      * be obtained by replacing (left to right, non-recursively) each &lt;pair&gt;
1012      * appearing in the &lt;string&gt; as follows:
1013      *   replace &lt;ESC&gt;&lt;ESC&gt; with &lt;ESC&gt;;
1014      *   replace &lt;ESC&gt;&lt;special&gt; with &lt;special&gt;;
1015      *   replace &lt;ESC&gt;&lt;hexpair&gt; with the octet indicated by the &lt;hexpair&gt;.
1016      * 
1017      * RFC 2253, Section 3
1018      * pair       = "\" ( special / "\" / QUOTATION / hexpair )
1019      * special    = "," / "=" / "+" / "&lt;" /  "&gt;" / "#" / ";"
1020      * 
1021      * RFC 1779, Section 2.3
1022      * &lt;pair&gt; ::= "\" ( &lt;special&gt; | "\" | '"')
1023      * &lt;special&gt; ::= "," | "=" | &lt;CR&gt; | "+" | "&lt;" |  "&gt;"
1024      *           | "#" | ";"
1025      * 
1026      */
1027 	public final byte[]  pair(
1028 		UpAndNormValue value
1029 	) throws RecognitionException, TokenStreamException {
1030 		byte[] pair;
1031 		
1032 		Token  hexpair = null;
1033 		
1034 		matchedProduction( "pair()" );
1035 		String tmp;
1036 		
1037 		
1038 		switch ( LA(1)) {
1039 		case ESCESC:
1040 		{
1041 			{
1042 			match(ESCESC);
1043 			
1044 			value.rawValue += "\\\\";
1045 			pair = Strings.getBytesUtf8( "\\" );
1046 			
1047 			}
1048 			break;
1049 		}
1050 		case ESCSHARP:
1051 		{
1052 			{
1053 			match(ESCSHARP);
1054 			
1055 			value.rawValue += "\\#";
1056 			pair = Strings.getBytesUtf8( "#" );
1057 			
1058 			}
1059 			break;
1060 		}
1061 		case ESC:
1062 		{
1063 			{
1064 			match(ESC);
1065 			tmp=special();
1066 			
1067 			value.rawValue += "\\" + tmp;
1068 			pair = Strings.getBytesUtf8( tmp );
1069 			
1070 			}
1071 			break;
1072 		}
1073 		case HEXPAIR:
1074 		{
1075 			{
1076 			hexpair = LT(1);
1077 			match(HEXPAIR);
1078 			
1079 			value.rawValue += "\\" + hexpair.getText();
1080 			pair = Strings.toByteArray( hexpair.getText() ); 
1081 			
1082 			}
1083 			break;
1084 		}
1085 		default:
1086 		{
1087 			throw new NoViableAltException(LT(1), getFilename());
1088 		}
1089 		}
1090 		return pair;
1091 	}
1092 	
1093 /**
1094  * RFC 4514, Section 3:
1095  * LUTF1 = %x01-1F / %x21 / %x24-2A / %x2D-3A /
1096  *    %x3D / %x3F-5B / %x5D-7F
1097  *
1098  * The rule LUTF1_REST doesn't contain the following charcters,
1099  * so we must check them additionally
1100  *   EQUALS (0x3D)
1101  *   HYPHEN (0x2D)
1102  *   UNDERSCORE (0x5F)
1103  *   DIGIT (0x30-0x39)
1104  *   ALPHA (0x41-0x5A and 0x61-0x7A)
1105  */
1106 	public final String  lutf1() throws RecognitionException, TokenStreamException {
1107 		String lutf1="";
1108 		
1109 		Token  rest = null;
1110 		Token  equals = null;
1111 		Token  hyphen = null;
1112 		Token  underscore = null;
1113 		Token  digit = null;
1114 		Token  alpha = null;
1115 		Token  numericoid = null;
1116 		
1117 		matchedProduction( "lutf1()" );
1118 		
1119 		
1120 		switch ( LA(1)) {
1121 		case LUTF1_REST:
1122 		{
1123 			rest = LT(1);
1124 			match(LUTF1_REST);
1125 			lutf1 = rest.getText();
1126 			break;
1127 		}
1128 		case EQUALS:
1129 		{
1130 			equals = LT(1);
1131 			match(EQUALS);
1132 			lutf1 = equals.getText();
1133 			break;
1134 		}
1135 		case HYPHEN:
1136 		{
1137 			hyphen = LT(1);
1138 			match(HYPHEN);
1139 			lutf1 = hyphen.getText();
1140 			break;
1141 		}
1142 		case UNDERSCORE:
1143 		{
1144 			underscore = LT(1);
1145 			match(UNDERSCORE);
1146 			lutf1 = underscore.getText();
1147 			break;
1148 		}
1149 		case DIGIT:
1150 		{
1151 			digit = LT(1);
1152 			match(DIGIT);
1153 			lutf1 = digit.getText();
1154 			break;
1155 		}
1156 		case ALPHA:
1157 		{
1158 			alpha = LT(1);
1159 			match(ALPHA);
1160 			lutf1 = alpha.getText();
1161 			break;
1162 		}
1163 		case NUMERICOID:
1164 		{
1165 			numericoid = LT(1);
1166 			match(NUMERICOID);
1167 			lutf1 = numericoid.getText();
1168 			break;
1169 		}
1170 		default:
1171 		{
1172 			throw new NoViableAltException(LT(1), getFilename());
1173 		}
1174 		}
1175 		return lutf1;
1176 	}
1177 	
1178 	public final String  utfmb() throws RecognitionException, TokenStreamException {
1179 		String utfmb;
1180 		
1181 		Token  s = null;
1182 		
1183 		matchedProduction( "utfmb()" );
1184 		
1185 		
1186 		s = LT(1);
1187 		match(UTFMB);
1188 		utfmb = s.getText();
1189 		return utfmb;
1190 	}
1191 	
1192 /**
1193  * RFC 4514, Section 3:
1194  * SUTF1 = %x01-21 / %x23-2A / %x2D-3A /
1195  *    %x3D / %x3F-5B / %x5D-7F
1196  *
1197  * The rule LUTF1_REST doesn't contain the following charcters,
1198  * so we must check them additionally
1199  *   EQUALS (0x3D)
1200  *   HYPHEN (0x2D)
1201  *   UNDERSCORE (0x5F)
1202  *   DIGIT (0x30-0x39)
1203  *   ALPHA (0x41-0x5A and 0x61-0x7A)
1204  *   SHARP
1205  *   SPACE
1206  */
1207 	public final String  sutf1() throws RecognitionException, TokenStreamException {
1208 		String sutf1="";
1209 		
1210 		Token  rest = null;
1211 		Token  equals = null;
1212 		Token  hyphen = null;
1213 		Token  underscore = null;
1214 		Token  digit = null;
1215 		Token  alpha = null;
1216 		Token  sharp = null;
1217 		Token  space = null;
1218 		Token  hex = null;
1219 		Token  numericoid = null;
1220 		
1221 		matchedProduction( "sutf1()" );
1222 		
1223 		
1224 		switch ( LA(1)) {
1225 		case LUTF1_REST:
1226 		{
1227 			rest = LT(1);
1228 			match(LUTF1_REST);
1229 			sutf1 = rest.getText();
1230 			break;
1231 		}
1232 		case EQUALS:
1233 		{
1234 			equals = LT(1);
1235 			match(EQUALS);
1236 			sutf1 = equals.getText();
1237 			break;
1238 		}
1239 		case HYPHEN:
1240 		{
1241 			hyphen = LT(1);
1242 			match(HYPHEN);
1243 			sutf1 = hyphen.getText();
1244 			break;
1245 		}
1246 		case UNDERSCORE:
1247 		{
1248 			underscore = LT(1);
1249 			match(UNDERSCORE);
1250 			sutf1 = underscore.getText();
1251 			break;
1252 		}
1253 		case DIGIT:
1254 		{
1255 			digit = LT(1);
1256 			match(DIGIT);
1257 			sutf1 = digit.getText();
1258 			break;
1259 		}
1260 		case ALPHA:
1261 		{
1262 			alpha = LT(1);
1263 			match(ALPHA);
1264 			sutf1 = alpha.getText();
1265 			break;
1266 		}
1267 		case SHARP:
1268 		{
1269 			sharp = LT(1);
1270 			match(SHARP);
1271 			sutf1 = sharp.getText();
1272 			break;
1273 		}
1274 		case SPACE:
1275 		{
1276 			space = LT(1);
1277 			match(SPACE);
1278 			sutf1 = space.getText();
1279 			break;
1280 		}
1281 		case HEXVALUE:
1282 		{
1283 			hex = LT(1);
1284 			match(HEXVALUE);
1285 			sutf1 = "#" + hex.getText();
1286 			break;
1287 		}
1288 		case NUMERICOID:
1289 		{
1290 			numericoid = LT(1);
1291 			match(NUMERICOID);
1292 			sutf1 = numericoid.getText();
1293 			break;
1294 		}
1295 		default:
1296 		{
1297 			throw new NoViableAltException(LT(1), getFilename());
1298 		}
1299 		}
1300 		return sutf1;
1301 	}
1302 	
1303 /**
1304      * RFC 4514 Section 3
1305      * 
1306      * special = escaped / SPACE / SHARP / EQUALS
1307      * escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
1308      *
1309      */
1310 	public final String  special() throws RecognitionException, TokenStreamException {
1311 		String special;
1312 		
1313 		Token  dquote = null;
1314 		Token  plus = null;
1315 		Token  comma = null;
1316 		Token  semi = null;
1317 		Token  langle = null;
1318 		Token  rangle = null;
1319 		Token  space = null;
1320 		Token  sharp = null;
1321 		Token  equals = null;
1322 		
1323 		matchedProduction( "special()" );
1324 		
1325 		
1326 		{
1327 		switch ( LA(1)) {
1328 		case DQUOTE:
1329 		{
1330 			dquote = LT(1);
1331 			match(DQUOTE);
1332 			special = dquote.getText();
1333 			break;
1334 		}
1335 		case PLUS:
1336 		{
1337 			plus = LT(1);
1338 			match(PLUS);
1339 			special = plus.getText();
1340 			break;
1341 		}
1342 		case COMMA:
1343 		{
1344 			comma = LT(1);
1345 			match(COMMA);
1346 			special = comma.getText();
1347 			break;
1348 		}
1349 		case SEMI:
1350 		{
1351 			semi = LT(1);
1352 			match(SEMI);
1353 			special = semi.getText();
1354 			break;
1355 		}
1356 		case LANGLE:
1357 		{
1358 			langle = LT(1);
1359 			match(LANGLE);
1360 			special = langle.getText();
1361 			break;
1362 		}
1363 		case RANGLE:
1364 		{
1365 			rangle = LT(1);
1366 			match(RANGLE);
1367 			special = rangle.getText();
1368 			break;
1369 		}
1370 		case SPACE:
1371 		{
1372 			space = LT(1);
1373 			match(SPACE);
1374 			special = space.getText();
1375 			break;
1376 		}
1377 		case SHARP:
1378 		{
1379 			sharp = LT(1);
1380 			match(SHARP);
1381 			special = sharp.getText();
1382 			break;
1383 		}
1384 		case EQUALS:
1385 		{
1386 			equals = LT(1);
1387 			match(EQUALS);
1388 			special = equals.getText();
1389 			break;
1390 		}
1391 		default:
1392 		{
1393 			throw new NoViableAltException(LT(1), getFilename());
1394 		}
1395 		}
1396 		}
1397 		return special;
1398 	}
1399 	
1400 	
1401 	public static final String[] _tokenNames = {
1402 		"<0>",
1403 		"EOF",
1404 		"<2>",
1405 		"NULL_TREE_LOOKAHEAD",
1406 		"COMMA",
1407 		"EQUALS",
1408 		"PLUS",
1409 		"HYPHEN",
1410 		"UNDERSCORE",
1411 		"DQUOTE",
1412 		"SEMI",
1413 		"LANGLE",
1414 		"RANGLE",
1415 		"SPACE",
1416 		"NUMERICOID_OR_ALPHA_OR_DIGIT",
1417 		"NUMERICOID",
1418 		"DOT",
1419 		"NUMBER",
1420 		"LDIGIT",
1421 		"DIGIT",
1422 		"ALPHA",
1423 		"HEXPAIR_OR_ESCESC_ESCSHARP_OR_ESC",
1424 		"HEXPAIR",
1425 		"ESC",
1426 		"ESCESC",
1427 		"ESCSHARP",
1428 		"HEX",
1429 		"HEXVALUE_OR_SHARP",
1430 		"HEXVALUE",
1431 		"SHARP",
1432 		"UTFMB",
1433 		"LUTF1_REST"
1434 	};
1435 	
1436 	private static final long[] mk_tokenSet_0() {
1437 		long[] data = { 4232052208L, 0L, 0L, 0L};
1438 		return data;
1439 	}
1440 	public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
1441 	
1442 	}