KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jacorb > idl > lexer


1 /*
2  * JacORB - a free Java ORB
3  *
4  * Copyright (C) 1997-2004 Gerald Brose.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */

20
21 package org.jacorb.idl;
22
23 import org.jacorb.idl.runtime.*;
24
25 import java.util.*;
26
27 /**
28  * This class implements a scanner (aka lexical analyzer or
29  * lexer) for IDL. The scanner reads characters from a global input
30  * stream and returns integers corresponding to the terminal number
31  * of the next token. Once the end of input is reached the EOF token
32  * is returned on every subsequent call.<p>
33  *
34  * All symbol constants are defined in sym.java which is generated by
35  * JavaCup from parser.cup.<p>
36  *
37  * In addition to the scanner proper (called first via init() then
38  * with next_token() to get each token) this class provides simple
39  * error and warning routines and keeps a count of errors and
40  * warnings that is publicly accessible. It also provides basic
41  * preprocessing facilties, i.e. it does handle preprocessor
42  * directives such as #define, #undef, #include, etc. although it
43  * does not provide full C++ preprocessing
44  *
45  * This class is "static" (i.e., it has only static members and methods).
46  *
47  * @version $Id: lexer.java,v 1.48 2004/05/06 12:39:59 nicolas Exp $
48  * @author Gerald Brose
49  *
50  */

51
52 public class lexer
53 {
54     private static org.apache.log.Logger logger = parser.getLogger();
55
56     /** First and second character of lookahead. */
57     protected static int next_char;
58     protected static int next_char2;
59
60     /** EOF constant. */
61     protected static final int EOF_CHAR = -1;
62
63     /**
64      * Table of keywords. Keywords are initially treated as
65      * identifiers. Just before they are returned we look them up in
66      * this table to see if they match one of the keywords. The
67      * string of the name is the key here, which indexes Integer
68      * objects holding the symbol number.
69      */

70
71     protected static Hashtable keywords = new Hashtable();
72
73     /** Table of keywords, stored in lower case. Keys are the
74      * lower case version of the keywords used as keys for the keywords
75      * hash above, and the values are the case sensitive versions of
76      * the keywords. This table is used for detecting collisions of
77      * identifiers with keywords.
78      */

79     protected static Hashtable keywords_lower_case = new Hashtable();
80
81
82     /** Table of Java reserved names.
83      */

84
85     protected static Hashtable java_keywords = new Hashtable();
86
87     /** Table of single character symbols. For ease of implementation, we
88      * store all unambiguous single character tokens in this table of Integer
89      * objects keyed by Integer objects with the numerical value of the
90      * appropriate char (currently Character objects have a bug which precludes
91      * their use in tables).
92      */

93     protected static Hashtable char_symbols = new Hashtable( 25 );
94
95
96     /** Defined symbols (preprocessor) */
97
98     protected static Hashtable defines = new Hashtable();
99     protected static boolean conditionalCompilation = true;
100
101     /** nested #ifdefs are pushed on this stack by the "preprocessor" */
102     private static java.util.Stack JavaDoc ifStack = new Stack();
103
104     private static java.util.Stack JavaDoc tokenStack = new Stack();
105
106     /** Current line number for use in error messages. */
107     protected static int current_line = 1;
108
109     /** Current line for use in error messages. */
110     protected static StringBuffer JavaDoc line = new StringBuffer JavaDoc();
111
112     /** Character position in current line. */
113     protected static int current_position = 1;
114
115     /** Have we already read a '"' ? */
116     protected static boolean in_string = false;
117
118     /** Are we processing a wide char or string ? */
119     protected static boolean wide = false;
120
121     /** Count of total errors detected so far. */
122     static int error_count = 0;
123
124     /** Count of warnings issued so far */
125     public static int warning_count = 0;
126
127     /** currently active pragma prefix */
128     public static String JavaDoc currentPragmaPrefix = "";
129
130     /** current file name */
131     public static String JavaDoc currentFile = "";
132
133     /** reset the scanner state */
134
135     public static void reset()
136     {
137         current_position = 1;
138         error_count = 0;
139         warning_count = 0;
140         currentPragmaPrefix = "";
141         line = new StringBuffer JavaDoc();
142         ifStack.removeAllElements();
143         tokenStack.removeAllElements();
144         defines.clear();
145     }
146
147     /**
148      * Initialize the scanner. This sets up the keywords and char_symbols
149      * tables and reads the first two characters of lookahead.
150      *
151      * "Object" is listed as reserved in the OMG spec.
152      * "int" is not, but I reserved it to bar its usage as a legal integer
153      * type.
154      */

155
156     public static void init()
157         throws java.io.IOException JavaDoc
158     {
159         /* set up standard symbols */
160         defines.put( "JACORB_IDL_1_4", "" );
161
162         /* set up the keyword table */
163
164         keywords.put( "abstract", new Integer JavaDoc( sym.ABSTRACT ) );
165         keywords.put( "any", new Integer JavaDoc( sym.ANY ) );
166         keywords.put( "attribute", new Integer JavaDoc( sym.ATTRIBUTE ) );
167         keywords.put( "boolean", new Integer JavaDoc( sym.BOOLEAN ) );
168         keywords.put( "case", new Integer JavaDoc( sym.CASE ) );
169         keywords.put( "char", new Integer JavaDoc( sym.CHAR ) );
170         keywords.put( "const", new Integer JavaDoc( sym.CONST ) );
171         keywords.put( "context", new Integer JavaDoc( sym.CONTEXT ) );
172         keywords.put( "custom", new Integer JavaDoc( sym.CUSTOM ) );
173         keywords.put( "default", new Integer JavaDoc( sym.DEFAULT ) );
174         keywords.put( "double", new Integer JavaDoc( sym.DOUBLE ) );
175         keywords.put( "enum", new Integer JavaDoc( sym.ENUM ) );
176         keywords.put( "exception", new Integer JavaDoc( sym.EXCEPTION ) );
177         keywords.put( "factory", new Integer JavaDoc( sym.FACTORY ) );
178         keywords.put( "FALSE", new Integer JavaDoc( sym.FALSE ) );
179         keywords.put( "fixed", new Integer JavaDoc( sym.FIXED ) );
180         keywords.put( "float", new Integer JavaDoc( sym.FLOAT ) );
181         keywords.put( "in", new Integer JavaDoc( sym.IN ) );
182         keywords.put( "inout", new Integer JavaDoc( sym.INOUT ) );
183         keywords.put( "interface", new Integer JavaDoc( sym.INTERFACE ) );
184         keywords.put( "local", new Integer JavaDoc( sym.LOCAL ) );
185         keywords.put( "long", new Integer JavaDoc( sym.LONG ) );
186         keywords.put( "module", new Integer JavaDoc( sym.MODULE ) );
187         keywords.put( "native", new Integer JavaDoc( sym.NATIVE ) );
188         keywords.put( "Object", new Integer JavaDoc( sym.OBJECT ) );
189         keywords.put( "octet", new Integer JavaDoc( sym.OCTET ) );
190         keywords.put( "oneway", new Integer JavaDoc( sym.ONEWAY ) );
191         keywords.put( "out", new Integer JavaDoc( sym.OUT ) );
192         keywords.put( "private", new Integer JavaDoc( sym.PRIVATE ) );
193         keywords.put( "public", new Integer JavaDoc( sym.PUBLIC ) );
194         keywords.put( "pseudo", new Integer JavaDoc( sym.PSEUDO ) );
195         keywords.put( "raises", new Integer JavaDoc( sym.RAISES ) );
196         keywords.put( "readonly", new Integer JavaDoc( sym.READONLY ) );
197         keywords.put( "sequence", new Integer JavaDoc( sym.SEQUENCE ) );
198         keywords.put( "short", new Integer JavaDoc( sym.SHORT ) );
199         keywords.put( "string", new Integer JavaDoc( sym.STRING ) );
200         keywords.put( "struct", new Integer JavaDoc( sym.STRUCT ) );
201         keywords.put( "supports", new Integer JavaDoc( sym.SUPPORTS ) );
202         keywords.put( "switch", new Integer JavaDoc( sym.SWITCH ) );
203         keywords.put( "TRUE", new Integer JavaDoc( sym.TRUE ) );
204         keywords.put( "truncatable", new Integer JavaDoc( sym.TRUNCATABLE ) );
205         keywords.put( "typedef", new Integer JavaDoc( sym.TYPEDEF ) );
206         keywords.put( "unsigned", new Integer JavaDoc( sym.UNSIGNED ) );
207         keywords.put( "union", new Integer JavaDoc( sym.UNION ) );
208         keywords.put( "ValueBase", new Integer JavaDoc( sym.VALUEBASE ) );
209         keywords.put( "valuetype", new Integer JavaDoc( sym.VALUETYPE ) );
210         keywords.put( "void", new Integer JavaDoc( sym.VOID ) );
211         keywords.put( "wchar", new Integer JavaDoc( sym.WCHAR ) );
212         keywords.put( "wstring", new Integer JavaDoc( sym.WSTRING ) );
213
214         keywords.put( "::", new Integer JavaDoc( sym.DBLCOLON ) );
215         keywords.put( "<<", new Integer JavaDoc( sym.LSHIFT ) );
216         keywords.put( ">>", new Integer JavaDoc( sym.RSHIFT ) );
217         keywords.put( "L\"", new Integer JavaDoc( sym.LDBLQUOTE ) );
218
219         // setup the mapping of lower case keywords to case sensitive
220
// keywords
221

222         for( java.util.Enumeration JavaDoc e = keywords.keys(); e.hasMoreElements(); )
223         {
224             String JavaDoc keyword = (String JavaDoc)e.nextElement();
225             String JavaDoc keyword_lower_case = keyword.toLowerCase();
226             keywords_lower_case.put( keyword_lower_case, keyword );
227         }
228
229         /* set up the table of single character symbols */
230         char_symbols.put( new Integer JavaDoc( ';' ), new Integer JavaDoc( sym.SEMI ) );
231         char_symbols.put( new Integer JavaDoc( ',' ), new Integer JavaDoc( sym.COMMA ) );
232         char_symbols.put( new Integer JavaDoc( '*' ), new Integer JavaDoc( sym.STAR ) );
233         char_symbols.put( new Integer JavaDoc( '.' ), new Integer JavaDoc( sym.DOT ) );
234         char_symbols.put( new Integer JavaDoc( ':' ), new Integer JavaDoc( sym.COLON ) );
235         char_symbols.put( new Integer JavaDoc( '=' ), new Integer JavaDoc( sym.EQUALS ) );
236         char_symbols.put( new Integer JavaDoc( '+' ), new Integer JavaDoc( sym.PLUS ) );
237         char_symbols.put( new Integer JavaDoc( '-' ), new Integer JavaDoc( sym.MINUS ) );
238         char_symbols.put( new Integer JavaDoc( '{' ), new Integer JavaDoc( sym.LCBRACE ) );
239         char_symbols.put( new Integer JavaDoc( '}' ), new Integer JavaDoc( sym.RCBRACE ) );
240         char_symbols.put( new Integer JavaDoc( '(' ), new Integer JavaDoc( sym.LPAREN ) );
241         char_symbols.put( new Integer JavaDoc( ')' ), new Integer JavaDoc( sym.RPAREN ) );
242         char_symbols.put( new Integer JavaDoc( '[' ), new Integer JavaDoc( sym.LSBRACE ) );
243         char_symbols.put( new Integer JavaDoc( ']' ), new Integer JavaDoc( sym.RSBRACE ) );
244         char_symbols.put( new Integer JavaDoc( '<' ), new Integer JavaDoc( sym.LESSTHAN ) );
245         char_symbols.put( new Integer JavaDoc( '>' ), new Integer JavaDoc( sym.GREATERTHAN ) );
246         char_symbols.put( new Integer JavaDoc( '\'' ), new Integer JavaDoc( sym.QUOTE ) );
247         char_symbols.put( new Integer JavaDoc( '\"' ), new Integer JavaDoc( sym.DBLQUOTE ) );
248         char_symbols.put( new Integer JavaDoc( '\\' ), new Integer JavaDoc( sym.BSLASH ) );
249         char_symbols.put( new Integer JavaDoc( '^' ), new Integer JavaDoc( sym.CIRCUM ) );
250         char_symbols.put( new Integer JavaDoc( '&' ), new Integer JavaDoc( sym.AMPERSAND ) );
251         char_symbols.put( new Integer JavaDoc( '/' ), new Integer JavaDoc( sym.SLASH ) );
252         char_symbols.put( new Integer JavaDoc( '%' ), new Integer JavaDoc( sym.PERCENT ) );
253         char_symbols.put( new Integer JavaDoc( '~' ), new Integer JavaDoc( sym.TILDE ) );
254         char_symbols.put( new Integer JavaDoc( '|' ), new Integer JavaDoc( sym.BAR ) );
255         char_symbols.put( new Integer JavaDoc( ' ' ), new Integer JavaDoc( sym.SPACE ) );
256
257         /* set up reserved Java names */
258
259         java_keywords.put( "abstract", "" );
260         java_keywords.put( "boolean", "" );
261         java_keywords.put( "break", "" );
262         java_keywords.put( "byte", "" );
263         java_keywords.put( "case", "" );
264         java_keywords.put( "catch", "" );
265         java_keywords.put( "char", "" );
266         java_keywords.put( "class", "" );
267         java_keywords.put( "const", "" );
268         java_keywords.put( "continue", "" );
269         java_keywords.put( "default", "" );
270         java_keywords.put( "do", "" );
271         java_keywords.put( "double", "" );
272         java_keywords.put( "else", "" );
273         java_keywords.put( "extends", "" );
274         java_keywords.put( "false", "" );
275         java_keywords.put( "final", "" );
276         java_keywords.put( "finally", "" );
277         java_keywords.put( "float", "" );
278         java_keywords.put( "for", "" );
279         java_keywords.put( "goto", "" );
280         java_keywords.put( "if", "" );
281         java_keywords.put( "implements", "" );
282         java_keywords.put( "import", "" );
283         java_keywords.put( "instanceof", "" );
284         java_keywords.put( "int", "" );
285         java_keywords.put( "interface", "" );
286         java_keywords.put( "long", "" );
287         java_keywords.put( "native", "" );
288         java_keywords.put( "new", "" );
289         java_keywords.put( "null", "" );
290         java_keywords.put( "package", "" );
291         java_keywords.put( "private", "" );
292         java_keywords.put( "protected", "" );
293         java_keywords.put( "public", "" );
294         java_keywords.put( "return", "" );
295         java_keywords.put( "short", "" );
296         java_keywords.put( "static", "" );
297         java_keywords.put( "super", "" );
298         java_keywords.put( "switch", "" );
299         java_keywords.put( "synchronized", "" );
300         java_keywords.put( "true", "" );
301         java_keywords.put( "this", "" );
302         java_keywords.put( "throw", "" );
303         java_keywords.put( "throws", "" );
304         java_keywords.put( "transient", "" );
305         java_keywords.put( "try", "" );
306         java_keywords.put( "void", "" );
307         java_keywords.put( "volatile", "" );
308         java_keywords.put( "while", "" );
309
310         java_keywords.put( "clone", "" );
311         java_keywords.put( "equals", "" );
312         java_keywords.put( "finalize", "" );
313         java_keywords.put( "getClass", "" );
314         java_keywords.put( "hashCode", "" );
315         java_keywords.put( "notify", "" );
316         java_keywords.put( "notifyAll", "" );
317         java_keywords.put( "toString", "" );
318         java_keywords.put( "wait", "" );
319
320
321
322         /* stack needs a topmost value */
323         ifStack.push( new Boolean JavaDoc( true ) );
324
325         /* read two characters of lookahead */
326
327         try
328         {
329             next_char = GlobalInputStream.read();
330         }
331         catch( Exception JavaDoc e )
332         {
333             org.jacorb.idl.parser.fatal_error( "Cannot read from file " +
334                     GlobalInputStream.currentFile().getAbsolutePath() +
335                     ", please check file name.", null );
336         }
337
338         if( next_char == EOF_CHAR )
339             next_char2 = EOF_CHAR;
340         else
341             next_char2 = GlobalInputStream.read();
342     }
343
344
345     public static void define( String JavaDoc symbol, String JavaDoc value )
346     {
347         if( logger.isDebugEnabled() )
348             logger.debug( "Defining: " + symbol + " as " + value );
349         defines.put( symbol, value );
350     }
351
352     public static void undefine( String JavaDoc symbol )
353     {
354         if( logger.isDebugEnabled() )
355             logger.debug( "Un-defining: " + symbol );
356         defines.remove( symbol );
357     }
358
359     public static String JavaDoc defined( String JavaDoc symbol )
360     {
361         return (String JavaDoc)defines.get( symbol );
362     }
363
364     /**
365      * record information about the last lexical scope so that it can be
366      * restored later
367      */

368
369     public static int currentLine()
370     {
371         return current_line;
372     }
373
374     /**
375      * return the current reading position
376      */

377
378     public static PositionInfo getPosition()
379     {
380         return new PositionInfo( current_line,
381                                  current_position,
382                                  currentPragmaPrefix,
383                                  line.toString(),
384                                  GlobalInputStream.currentFile() );
385     }
386
387     public static void restorePosition( PositionInfo p )
388     {
389         current_line = p.line_no;
390         currentPragmaPrefix = p.pragma_prefix;
391         current_position = 0;
392     }
393
394     /**
395      * Advance the scanner one character in the input stream. This moves
396      * next_char2 to next_char and then reads a new next_char2.
397      */

398
399     protected static void advance()
400         throws java.io.IOException JavaDoc
401     {
402         int old_char;
403
404         old_char = next_char;
405         next_char = next_char2;
406         next_char2 = GlobalInputStream.read();
407
408         line.append( (char)old_char );
409
410         /* count this */
411
412         current_position++;
413         if( old_char == '\n' )
414         {
415             current_line++;
416             current_position = 1;
417             line = new StringBuffer JavaDoc();
418         }
419     }
420
421
422     /**
423      * Emit an error message. The message will be marked with both the
424      * current line number and the position in the line. Error messages
425      * are printed on standard error (System.err).
426      * @param message the message to print.
427      * @param p_info an optional PositionInfo object
428      */

429
430     public static void emit_error( String JavaDoc message )
431     {
432         if (parser.getLogger().isErrorEnabled())
433         {
434             logger.error( GlobalInputStream.currentFile().getAbsolutePath() +
435                            ", line: " + current_line +
436                            "(" + current_position + "): " +
437                            message + "\n\t" +
438                            line.toString() );
439         }
440         error_count++;
441     }
442
443     public static void emit_error( String JavaDoc message, str_token t )
444     {
445         if( t == null )
446         {
447             emit_error( message );
448         }
449         else
450         {
451             if (parser.getLogger().isErrorEnabled())
452             {
453                 logger.error( t.fileName + ", line:" + t.line_no +
454                               "(" + t.char_pos + "): " + message +
455                               "\n\t" + t.line_val );
456             }
457             error_count++;
458         }
459     }
460
461
462     /**
463      * Emit a warning message. The message will be marked with both the
464      * current line number and the position in the line. Messages are
465      * printed on standard error (System.err).
466      *
467      * @param message the message to print.
468      */

469
470     public static void emit_warn( String JavaDoc message )
471     {
472         if (parser.getLogger().isWarnEnabled())
473         {
474             logger.warn( message + " at " + current_line + "(" + current_position +
475                          "): \"" + line.toString() + "\"" );
476         }
477         warning_count++;
478     }
479
480
481     public static void emit_warn( String JavaDoc message, str_token t )
482     {
483         if( t == null )
484         {
485             emit_warn( message );
486         }
487         else
488         {
489             if (parser.getLogger().isWarnEnabled())
490             {
491                 logger.warn( " at " + t.fileName + ", line:" + t.line_no + "(" +
492                              t.char_pos + "): " + message + "\n\t" + t.line_val );
493             }
494
495             warning_count++;
496         }
497     }
498
499
500     /**
501      * Determine if a character is ok to start an id.
502      * @param ch the character in question.
503      */

504     protected static boolean id_start_char( int ch )
505     {
506         return
507                 ( ch >= 'a' && ch <= 'z' ) ||
508                 ( ch >= 'A' && ch <= 'Z' ) ||
509                 ( ch == '_' );
510     }
511
512
513     /**
514      * Determine if a character is ok for the middle of an id.
515      * @param ch the character in question.
516      */

517     protected static boolean id_char( int ch )
518     {
519         return id_start_char( ch ) || ( ch == '_' ) || ( ch >= '0' && ch <= '9' );
520     }
521
522
523     /**
524      * Try to look up a single character symbol, returns -1 for not found.
525      * @param ch the character in question.
526      */

527
528     protected static int find_single_char( int ch )
529     {
530         Integer JavaDoc result;
531
532         result = (Integer JavaDoc)char_symbols.get( new Integer JavaDoc( (char)ch ) );
533         if( result == null )
534             return -1;
535         else
536             return result.intValue();
537     }
538
539     /**
540      * Handle swallowing up a comment. Both old style C and new style C++
541      * comments are handled.
542      */

543     protected static void swallow_comment()
544             throws java.io.IOException JavaDoc
545     {
546         /* next_char == '/' at this point */
547
548         /* is it a traditional comment */
549         if( next_char2 == '*' )
550         {
551             /* swallow the opener */
552             advance();
553             advance();
554
555             /* swallow the comment until end of comment or EOF */
556             for( ; ; )
557             {
558                 /* if its EOF we have an error */
559                 if( next_char == EOF_CHAR )
560                 {
561                     emit_error( "Specification file ends inside a comment", null );
562                     return;
563                 }
564
565                 /* if we can see the closer we are done */
566                 if( next_char == '*' && next_char2 == '/' )
567                 {
568                     advance();
569                     advance();
570                     return;
571                 }
572
573                 /* otherwise swallow char and move on */
574                 advance();
575             }
576         }
577
578         /* is its a new style comment */
579         if( next_char2 == '/' )
580         {
581             /* swallow the opener */
582             advance();
583             advance();
584
585             /* swallow to '\n', '\f', or EOF */
586             while( next_char != '\n' && next_char != '\f' && next_char != '\r' && next_char != EOF_CHAR )
587             {
588                 advance();
589             }
590
591             return;
592         }
593
594         /* shouldn't get here, but... if we get here we have an error */
595         emit_error( "Malformed comment in specification -- ignored", null );
596         advance();
597     }
598
599
600     /**
601      * Preprocessor directives are handled here.
602      */

603
604     protected static void preprocess()
605         throws java.io.IOException JavaDoc
606     {
607         for( ; ; )
608         {
609             /* if its EOF we have an error */
610             if( next_char == EOF_CHAR )
611             {
612                 emit_error( "Specification file ends inside a preprocessor directive", null );
613                 return;
614             }
615             else if( next_char != '#' )
616             {
617                 emit_error( "expected #, got " + (char)next_char + " instead!", null );
618             }
619             else
620                 advance(); // skip '#'
621

622             // the following is done to allow for # ifdef sloppiness
623
while( ( ' ' == next_char ) || ( '\t' == next_char ) )
624                 advance();
625
626             String JavaDoc dir = get_string();
627
628             if( dir.equals( "include" ) )
629             {
630                 if( !conditionalCompilation )
631                     return;
632                 advance(); // skip ' '
633
boolean useIncludePath = ( next_char == '<' );
634                 advance(); // skip `\"' or '<'
635

636                 String JavaDoc fname = get_string();
637
638                 if( useIncludePath && ( next_char != '>' ) )
639                     emit_error( "Syntax error in #include directive, expecting '>'" );
640                 else if( !useIncludePath && ( next_char != '\"' ) )
641                     emit_error( "Syntax error in #include directive, expecting \"" );
642
643                 /* swallow to '\n', '\f', or EOF */
644                 while( next_char != '\n' && next_char != '\f' && next_char != '\r' &&
645                         next_char != EOF_CHAR )
646                 {
647                     advance();
648                 }
649                 GlobalInputStream.include( fname, next_char2, useIncludePath );
650                 current_line = 0;
651                 advance();
652                 advance();
653                 return;
654             }
655             else if( dir.equals( "define" ) )
656             {
657                 if( !conditionalCompilation )
658                     return;
659                 swallow_whitespace();
660                 String JavaDoc name = get_string();
661                 StringBuffer JavaDoc text = new StringBuffer JavaDoc();
662                 if( next_char == ' ' )
663                 {
664                     advance();
665                 }
666                 while( next_char != '\n' )
667                 {
668                     if( next_char == '\\' )
669                     {
670                         advance();
671                         advance();
672                     }
673                     text.append( (char)next_char );
674                     advance();
675                 }
676                 define( name, text.toString() );
677             }
678             else if( dir.equals( "error" ) )
679             {
680                 if( !conditionalCompilation )
681                     return;
682                 advance(); // skip ' '
683
String JavaDoc name = get_string();
684                 emit_error( name );
685             }
686             else if( dir.equals( "undef" ) )
687             {
688                 // Undefining symbol
689
if( !conditionalCompilation )
690                     return;
691                 swallow_whitespace();
692                 String JavaDoc name = get_string();
693                 undefine( name );
694             }
695             else if( dir.equals( "if" ) || dir.equals( "elif" ) )
696             {
697                 if (! dir.equals( "elif" ) )
698                 {
699                     ifStack.push( new Boolean JavaDoc( conditionalCompilation ) );
700                     if( !conditionalCompilation )
701                         return;
702                 }
703
704                 swallow_whitespace();
705
706                 // the following snippet distinguishes between #if defined
707
// and #if !defined
708

709                 boolean straightDefined = true;
710                 if( '!' == next_char )
711                 {
712                     advance();
713                     straightDefined = false;
714                 }
715
716                 String JavaDoc defineStr = get_string_no_paren();
717
718                 if (defineStr.equals ("defined"))
719                 {
720                     swallow_whitespace();
721
722                     boolean brackets = ( '(' == next_char );
723                     if( brackets )
724                     {
725                         advance(); // skip '('
726
swallow_whitespace(); // any whitespace after ( ? skip it
727
}
728
729                     String JavaDoc name = get_string_no_paren();
730
731                     if( brackets )
732                     {
733                         swallow_whitespace();
734                         if( logger.isDebugEnabled() )
735                             logger.debug( "next char: " + next_char );
736
737                         if( ')' != next_char )
738                         {
739                             emit_error( "Expected ) terminating #if defined", null );
740                             return;
741                         }
742                         advance();
743                     }
744
745                     if( straightDefined )
746                         conditionalCompilation = ( null != defined( name ) );
747                     else
748                         conditionalCompilation = ( null == defined( name ) );
749                 }
750                 else if (defineStr.equals("0"))
751                 {
752                     conditionalCompilation = false;
753                 }
754                 else if (defineStr.equals("1"))
755                 {
756                     conditionalCompilation = true;
757                 }
758                 else
759                 {
760                     emit_error( "Expected \"defined\" following #if: " +
761                                 dir, null );
762                     return;
763                 }
764             }
765             else if( dir.equals( "ifdef" ) )
766             {
767                 ifStack.push( new Boolean JavaDoc( conditionalCompilation ) );
768                 if( !conditionalCompilation )
769                     return;
770                 swallow_whitespace();
771                 String JavaDoc name = get_string();
772                 conditionalCompilation = ( defined( name ) != null );
773             }
774             else if( dir.equals( "ifndef" ) )
775             {
776                 ifStack.push( new Boolean JavaDoc( conditionalCompilation ) );
777                 if( !conditionalCompilation )
778                     return;
779                 swallow_whitespace();
780                 String JavaDoc name = get_string();
781                 conditionalCompilation = ( defined( name ) == null );
782             }
783             else if( dir.equals( "else" ) )
784             {
785                 if( ( (Boolean JavaDoc)ifStack.peek() ).booleanValue() )
786                     conditionalCompilation = !conditionalCompilation;
787             }
788             else if( dir.equals( "endif" ) )
789             {
790                 boolean b = ( (Boolean JavaDoc)ifStack.pop() ).booleanValue();
791                 conditionalCompilation = b;
792             }
793             else if( dir.equals( "pragma" ) )
794             {
795                 if( !conditionalCompilation )
796                     return;
797                 swallow_whitespace();
798
799                 String JavaDoc name = get_string();
800                 if( name.equals( "prefix" ) )
801                 {
802                     advance();
803                     currentPragmaPrefix = get_string();
804                 }
805                 else if( name.equals( "version" ) )
806                 {
807                     advance(); // skip ' '
808
String JavaDoc vname = get_string();
809                     advance(); // skip ' '
810
String JavaDoc version = get_string();
811                     String JavaDoc existingVersion = (String JavaDoc) parser.currentScopeData().versionMap.get (vname);
812                     if (existingVersion == null)
813                     {
814                         // Set version
815
parser.currentScopeData().versionMap.put (vname, version);
816                     }
817                     else
818                     {
819                         // Check for version change
820
if (! existingVersion.equals (version))
821                         {
822                             emit_error
823                             (
824                                 "Version re-declaration with different value: #pragma version " +
825                                 version,
826                                 null
827                             );
828                         }
829                     }
830                     String JavaDoc iname = (String JavaDoc)parser.currentScopeData().idMap.get (vname);
831                     if (iname != null)
832                     {
833                         if (version.equals (iname.substring (1 + iname.lastIndexOf (':'))) == false)
834                         {
835                             emit_error ("Declaring version with different version to already declared ID for " + name, null);
836                         }
837                     }
838                 }
839                 else if( name.equals( "ID" ) )
840                 {
841                     advance(); // skip ' '
842
String JavaDoc iname = get_string();
843                     advance(); // skip ' '
844
String JavaDoc id = get_string();
845                     String JavaDoc existingID = (String JavaDoc) parser.currentScopeData().idMap.get (iname);
846                     if (existingID == null)
847                     {
848                         // Set id
849
parser.currentScopeData().idMap.put (iname, id);
850                     }
851                     else
852                     {
853                         // Check for id change
854
if (! existingID.equals (id))
855                         {
856                             emit_error
857                             (
858                                 "ID re-declaration with different value: #pragma id " +
859                                 id,
860                                 null
861                             );
862                         }
863                     }
864                     if( parser.currentScopeData().versionMap.get( iname ) != null )
865                     {
866                         if( ((String JavaDoc)parser.currentScopeData().versionMap.get( iname )).equals
867                             ( id.substring (1 + id.lastIndexOf (':'))) == false )
868                         {
869                             emit_error ("Declaring ID with different version to already declared version for " + name, null);
870                         }
871                     }
872                 }
873                 else if( name.equals( "inhibit_code_generation" ) )
874                 {
875                     /* proprietary pragma of the JacORB IDL compiler */
876                     parser.setInhibitionState( true );
877                     // do something with it
878
}
879                 else
880                 {
881                     emit_warn( "Unknown pragma, ignoring: #pragma " + name, null );
882                 }
883             }
884             else
885             {
886                 emit_error( "Unrecognized preprocessor directive " + dir, null );
887             }
888
889
890             /* swallow to '\n', '\f', or EOF */
891             while( next_char != '\n' && next_char != '\f' && next_char != '\r' &&
892                     next_char != EOF_CHAR )
893             {
894                 advance();
895             }
896             return;
897         }
898     }
899
900
901     // the following is used for parsing the #if defined(...) construct
902

903     private static String JavaDoc get_string_no_paren()
904             throws java.io.IOException JavaDoc
905     {
906         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
907         char c = (char)next_char;
908         while( c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != '\f' && c != EOF_CHAR
909                 && c != '\"' && c != '<' && c != '>' && c != '(' && c != ')' )
910         {
911             sb.append( c );
912             advance();
913             c = (char)next_char;
914         }
915         return sb.toString();
916     }
917
918
919     private static String JavaDoc get_string()
920             throws java.io.IOException JavaDoc
921     {
922
923         StringBuffer JavaDoc sb = new StringBuffer JavaDoc( "" );
924
925         if( next_char == '\"' )
926         {
927             advance();
928             while( next_char != '\"' )
929             {
930                 if( next_char == EOF_CHAR )
931                     emit_error( "Unexpected EOF in string" );
932                 sb.append( (char)next_char );
933                 advance();
934             }
935         }
936         else
937         {
938             while( next_char != ' ' && next_char != '\t' && next_char != '\r' &&
939                     next_char != '\n' && next_char != '\f' && next_char != EOF_CHAR &&
940                     next_char != '\"' && next_char != '<' && next_char != '>' )
941             {
942                 sb.append( (char)next_char );
943                 advance();
944             }
945         }
946         return sb.toString();
947     }
948
949
950     /**
951      * Process an identifier.
952      * <P>
953      * Identifiers begin with a letter, underscore, or dollar sign,
954      * which is followed by zero or more letters, numbers,
955      * underscores or dollar signs. This routine returns a str_token
956      * suitable for return by the scanner or null, if the string that
957      * was read expanded to a symbol that was #defined. In this case,
958      * the symbol is expanded in place
959      */

960
961     protected static token do_symbol()
962             throws java.io.IOException JavaDoc
963     {
964         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
965         String JavaDoc result_str;
966         Integer JavaDoc keyword_num = null;
967         char buffer[] = new char[ 1 ];
968
969         /* next_char holds first character of id */
970         buffer[ 0 ] = (char)next_char;
971         result.append( buffer, 0, 1 );
972         advance();
973
974         /* collect up characters while they fit in id */
975         while( id_char( next_char ) )
976         {
977             buffer[ 0 ] = (char)next_char;
978             result.append( buffer, 0, 1 );
979             advance();
980         }
981
982         /* extract a string */
983         result_str = result.toString();
984
985         /* try to look it up as a defined symbol... */
986
987         String JavaDoc text = defined( result_str );
988         if( text != null )
989         {
990             char[] next = {(char)next_char, (char)next_char2};
991             GlobalInputStream.insert( text + ( new String JavaDoc( next ) ) );
992             advance(); // restore lookahead
993
advance(); // restore lookahead
994
return null;
995         }
996
997         // check if it's a keyword
998
keyword_num = (Integer JavaDoc)keywords.get( result_str );
999         if( keyword_num != null )
1000        {
1001            if( isScope( result_str ) )
1002            {
1003                parser.openScope();
1004            }
1005            return new token( keyword_num.intValue() );
1006        }
1007
1008        // not a keyword, so treat as identifier after verifying
1009
// case sensitivity rules and prefacing with an _
1010
// if it collides with a Java keyword.
1011

1012        result_str = checkIdentifier( result_str );
1013        if( null != result_str )
1014            return new str_token( sym.ID, result_str, getPosition(),
1015                    GlobalInputStream.currentFile().getName() );
1016        else
1017            return null;
1018    }
1019
1020    private static boolean isScope( String JavaDoc keyword )
1021    {
1022        return ( keyword.equals( "module" ) ||
1023                keyword.equals( "interface" ) ||
1024                keyword.equals( "struct" ) ||
1025                keyword.equals( "exception" ) ||
1026                keyword.equals( "union" )
1027                // keyword.equals("valuetype")
1028
);
1029    }
1030
1031
1032    /**
1033     * Checks whether Identifier str is legal and returns it. If the
1034     * identifier is escaped with a leading underscore, that
1035     * underscore is removed. If a the legal IDL identifier clashes
1036     * with a Java reserved word, an underscore is prepended.
1037     * <BR>
1038     * @param str - the IDL identifier <BR>
1039     * <BR>
1040     * Prints an error msg if the identifier collides with an IDL
1041     * keyword.
1042     */

1043
1044    public static String JavaDoc checkIdentifier( String JavaDoc str )
1045    {
1046
1047        if( logger.isInfoEnabled() )
1048            logger.info( "checking identifier " + str );
1049
1050        /* if it is an escaped identifier, look it up as a keyword,
1051           otherwise remove the underscore. */

1052
1053        if( str.charAt( 0 ) == '_' )
1054        {
1055            str = str.substring( 1 );
1056        }
1057        else
1058        {
1059            String JavaDoc colliding_keyword = null;
1060
1061            if (org.jacorb.idl.parser.strict_names)
1062            {
1063                // check for name clashes strictly (i.e. case insensitive)
1064
colliding_keyword =
1065                    (String JavaDoc)keywords_lower_case.get(str.toLowerCase());
1066            }
1067            else
1068            {
1069                // check for name clashes only loosely (i.e. case sensitive)
1070
colliding_keyword =
1071                    (String JavaDoc)keywords.get(str);
1072            }
1073
1074            if( colliding_keyword != null )
1075            {
1076                emit_error( "Identifier " + str + " collides with keyword " +
1077                            colliding_keyword + "." );
1078                return null;
1079            }
1080
1081
1082        }
1083
1084        /* clashes with a Java reserved word? */
1085        if( needsJavaEscape( str ) )
1086        {
1087            str = "_" + str;
1088        }
1089
1090        return str;
1091    }
1092
1093    /**
1094     * Only the most general name clashes with Java keywords
1095     * are caught here. Identifiers need to be checked again
1096     * at different other places in the compiler!
1097     */

1098
1099    private static boolean needsJavaEscape( String JavaDoc s )
1100    {
1101        return ( java_keywords.containsKey( s ) );
1102    }
1103
1104    /**
1105     * called during the parse phase to catch clashes with
1106     * Java reserved words.
1107     */

1108
1109    public static boolean strictJavaEscapeCheck( String JavaDoc s )
1110    {
1111        return ( ( !s.equals( "Helper" ) && s.endsWith( "Helper" ) ) ||
1112                ( !s.equals( "Holder" ) && s.endsWith( "Holder" ) ) ||
1113                ( !s.equals( "Operations" ) && s.endsWith( "Operations" ) ) ||
1114                ( !s.equals( "Package" ) && s.endsWith( "Package" ) ) ||
1115                ( !s.equals( "POA" ) && s.endsWith( "POA" ) ) ||
1116                ( !s.equals( "POATie" ) && s.endsWith( "POATie" ) ) );
1117    }
1118
1119    public static boolean needsJavaEscape( Module m )
1120    {
1121        String JavaDoc s = m.pack_name;
1122        if( logger.isDebugEnabled() )
1123            logger.debug( "checking module name " + s );
1124        return ( strictJavaEscapeCheck( s ) );
1125    }
1126
1127
1128    /**
1129     * Return one token. This is the main external interface to the scanner.
1130     * It consumes sufficient characters to determine the next input token
1131     * and returns it.
1132     */

1133
1134    public static token next_token()
1135        throws java.io.IOException JavaDoc
1136    {
1137        parser.set_included( GlobalInputStream.includeState() );
1138        token result = real_next_token();
1139        return result;
1140    }
1141
1142    private static void swallow_whitespace()
1143        throws java.io.IOException JavaDoc
1144    {
1145        /* look for white space */
1146        while( next_char == ' ' || next_char == '\t' || next_char == '\n' ||
1147                next_char == '\f' || next_char == '\r' )
1148        {
1149            /* advance past it and try the next character */
1150            advance();
1151        }
1152    }
1153
1154    /**
1155     * The actual routine to return one token.
1156     *
1157     * @return token
1158     * @throws java.io.IOException
1159     */

1160
1161    protected static token real_next_token()
1162        throws java.io.IOException JavaDoc
1163    {
1164        int sym_num;
1165
1166        /* if we found more than a single token last time, these
1167           tokens were remembered on the tokenStack - return the first
1168           one here */

1169
1170        if( !tokenStack.empty() )
1171            return (token)tokenStack.pop();
1172
1173        /* else */
1174
1175        for( ; ; )
1176        {
1177            /* scan input until we return something */
1178            if( !in_string )
1179            {
1180                swallow_whitespace();
1181
1182                /* look for preprocessor directives */
1183                if( (char)next_char == '#' )
1184                {
1185                    preprocess();
1186                    continue;
1187                }
1188
1189                /* look for a comment */
1190                if( next_char == '/' && ( next_char2 == '*' || next_char2 == '/' ) )
1191                {
1192                    /* swallow then continue the scan */
1193                    swallow_comment();
1194                    continue;
1195                }
1196
1197                if( !conditionalCompilation )
1198                {
1199                    advance();
1200                    if( next_char == EOF_CHAR )
1201                    {
1202                        emit_error( "EOF in conditional compilation!", null );
1203                        return null;
1204                    }
1205                    else
1206                        continue;
1207                }
1208
1209                /* look for COLON or DBLCOLON */
1210                if( next_char == ':' )
1211                {
1212                    if( next_char2 == ':' )
1213                    {
1214                        advance();
1215                        advance();
1216                        return new token( sym.DBLCOLON );
1217                    }
1218                    else
1219                    {
1220                        advance();
1221                        return new token( sym.COLON );
1222                    }
1223                }
1224
1225                /* leading L for wide strings */
1226                if( next_char == 'L' && ( next_char2 =='\"' || next_char2 =='\'') )
1227                {
1228                    wide = true;
1229                    advance();
1230                    if( next_char2 == '\"' )
1231                    {
1232                        advance();
1233                        in_string = true;
1234                        return new token( sym.LDBLQUOTE );
1235                    }
1236                    // wide char literal may follow, but detecting that
1237
// is done below.
1238
}
1239
1240                /* look for Shifts */
1241                if( next_char == '<' )
1242                {
1243                    if( next_char2 == '<' )
1244                    {
1245                        advance();
1246                        advance();
1247                        return new token( sym.LSHIFT );
1248                    }
1249                    else
1250                    {
1251                        advance();
1252                        return new token( sym.LESSTHAN );
1253                    }
1254                }
1255                if( next_char == '>' )
1256                {
1257                    if( next_char2 == '>' )
1258                    {
1259                        advance();
1260                        advance();
1261                        return new token( sym.RSHIFT );
1262                    }
1263                    else
1264                    {
1265                        advance();
1266                        return new token( sym.GREATERTHAN );
1267                    }
1268                }
1269
1270
1271                /* leading 0: */
1272                /* Try to scan octal/hexadecimal numbers, might even find a float */
1273                if( next_char == '0' )
1274                {
1275                    long l_val = 0;
1276                    long l_val_old = 0;
1277                    int radix = 8;
1278                    int digit = 0;
1279                    advance();
1280
1281                    if( next_char == '.' )
1282                    {
1283                        StringBuffer JavaDoc f_string = new StringBuffer JavaDoc( "0." );
1284                        advance();
1285
1286                        while( next_char >= '0' && next_char <= '9' )
1287                        {
1288                            f_string.append( (char)next_char );
1289                            advance();
1290                        }
1291
1292                        float f_val = ( new Float JavaDoc( f_string.toString() ) ).floatValue();
1293                        return new float_token( sym.FLOAT_NUMBER, f_val );
1294                    }
1295                    else
1296                    {
1297                        // See if hexadecimal value
1298

1299                        if( next_char == 'x' || next_char == 'X' )
1300                        {
1301                            advance();
1302                            radix = 16;
1303                        }
1304
1305                        StringBuffer JavaDoc val = new StringBuffer JavaDoc( "0" );
1306                        digit = Character.digit( (char)next_char, radix );
1307                        while( digit != -1 )
1308                        {
1309                            val.append( (char)next_char );
1310                            advance();
1311                            digit = Character.digit( (char)next_char, radix );
1312                        }
1313
1314                        String JavaDoc str = val.toString();
1315                        try
1316                        {
1317                            return new int_token( sym.NUMBER,
1318                                                  Integer.parseInt( str, radix ) );
1319                        }
1320                        catch( NumberFormatException JavaDoc ex )
1321                        {
1322                            try
1323                            {
1324                                return new long_token( sym.LONG_NUMBER,
1325                                                       Long.parseLong( str, radix ) );
1326                            }
1327                            catch( NumberFormatException JavaDoc ex2 )
1328                            {
1329                                emit_error( "Invalid octal/hex value: " + str );
1330                            }
1331                        }
1332                        return null;
1333                    }
1334                }
1335
1336                /* Try to scan integer, floating point or fixed point literals */
1337
1338                if (isDigit (((char)next_char)) ||
1339                    next_char == '.' ||
1340                    (next_char == '-' && isDigit (((char)next_char2))))
1341                {
1342                    StringBuffer JavaDoc value = new StringBuffer JavaDoc();
1343                    StringBuffer JavaDoc fraction = null;
1344                    int exp = 0;
1345
1346                    if ( next_char == '-' )
1347                    {
1348                        value.append( (char)next_char );
1349                        advance();
1350                    }
1351                    // Read integer part
1352
while( next_char >= '0' && next_char <= '9' )
1353                    {
1354                        value.append( (char)next_char );
1355                        advance();
1356                    }
1357
1358                    // Read fraction
1359
if( next_char == '.' )
1360                    {
1361                        fraction = new StringBuffer JavaDoc();
1362                        advance();
1363
1364                        while( next_char >= '0' && next_char <= '9' )
1365                        {
1366                            fraction.append( (char)next_char );
1367                            advance();
1368                        }
1369                    }
1370
1371                    // Read exponent
1372
if( next_char == 'e' || next_char == 'E' )
1373                    {
1374                        if( fraction == null )
1375                            fraction = new StringBuffer JavaDoc();
1376
1377                        fraction.append( 'e' );
1378                        advance();
1379                        if( next_char == '-' || next_char == '+' )
1380                        {
1381                            fraction.append( (char)next_char );
1382                            advance();
1383                        }
1384
1385                        while( next_char >= '0' && next_char <= '9' )
1386                        {
1387                            fraction.append( (char)next_char );
1388                            advance();
1389                        }
1390
1391                        if( fraction.length() == 1 )
1392                        {
1393                            emit_error( "Empty exponent in float/double." );
1394                            continue;
1395                        }
1396
1397                        return new float_token( sym.FLOAT_NUMBER,
1398                                Float.valueOf( value.toString() +
1399                                "." +
1400                                fraction.toString() ).floatValue() );
1401                    }
1402
1403                    if( next_char == 'd' || next_char == 'D' )
1404                    {
1405                        advance();
1406                        if( fraction == null )
1407                            fraction = new StringBuffer JavaDoc();
1408
1409                        java.math.BigDecimal JavaDoc bi =
1410                                new java.math.BigDecimal JavaDoc( value.toString() + "." +
1411                                fraction.toString() );
1412                        return new fixed_token( sym.FIXED_NUMBER, bi );
1413
1414                    }
1415
1416                    if( fraction == null )
1417                    {
1418                        /* integer or long */
1419
1420                        token tok = null;
1421                        String JavaDoc str = value.toString();
1422
1423                        try
1424                        {
1425                            tok = new int_token( sym.NUMBER, Integer.parseInt( str ) );
1426                        }
1427                        catch( NumberFormatException JavaDoc ex )
1428                        {
1429                            try
1430                            {
1431                                tok = new long_token
1432                                    ( sym.LONG_NUMBER, Long.parseLong( str ) );
1433                            }
1434                            catch( NumberFormatException JavaDoc ex2 )
1435                            {
1436                                try
1437                                {
1438                                    // Not quite critical yet - lets try stuffing it into
1439
// a bigdecimal for later checking.
1440
tok = new fixed_token
1441                                        (sym.FIXED_NUMBER, new java.math.BigDecimal JavaDoc (str));
1442                                }
1443                                catch (NumberFormatException JavaDoc ex3)
1444                                {
1445                                    emit_error( "Invalid long value: " + str );
1446                                }
1447                            }
1448                        }
1449
1450                        return tok;
1451                    }
1452                    else
1453                    {
1454                        try
1455                        {
1456                            float f =
1457                                    Float.valueOf( value.toString() + "." +
1458                                    fraction.toString() ).floatValue();
1459                            return new float_token( sym.FLOAT_NUMBER, f );
1460                        }
1461                        catch( NumberFormatException JavaDoc nf )
1462                        {
1463                            emit_error( "Unexpected symbol: " +
1464                                    value.toString() + "." +
1465                                    fraction.toString() );
1466                        }
1467                    }
1468                }
1469
1470                /* look for a single character symbol */
1471                sym_num = find_single_char( next_char );
1472
1473                /* upon an opening double quote, return the
1474                   sym.DBLQUOTE token and continue scanning in the
1475                   in_string branch */

1476
1477                if( (char)next_char == '\"' )
1478                {
1479                    in_string = true;
1480                    advance();
1481                    return new token( sym.DBLQUOTE );
1482                }
1483
1484                if( (char)next_char == '\'' )
1485                {
1486                    advance();
1487
1488                    token t = null;
1489
1490                    if( next_char == '\\' )
1491                    {
1492                        // Now need to process escaped character.
1493

1494                        advance();
1495
1496                        if( isDigit( (char)next_char ) )
1497                        {
1498                            // Octal character
1499
char octal1 = '0';
1500                            char octal2 = '0';
1501                            char octal3 = (char)next_char;
1502
1503                            if( isDigit( (char)next_char2 ) )
1504                            {
1505                                advance();
1506                                octal2 = octal3;
1507                                octal3 = (char)next_char;
1508
1509                                if( isDigit( (char)next_char2 ) )
1510                                {
1511                                    advance();
1512                                    octal1 = octal2;
1513                                    octal2 = octal3;
1514                                    octal3 = (char)next_char;
1515                                }
1516                            }
1517
1518                            t = new char_token
1519                                    (
1520                                            sym.CH,
1521                                            (char)Integer.parseInt
1522                                    ( new String JavaDoc
1523                                            ( new char[]{octal1, octal2, octal3} ),
1524                                            8
1525                                    )
1526                                    );
1527                        }
1528                        else if( (char)next_char == 'x' )
1529                        {
1530                            // Hexadecimal character
1531
advance();
1532
1533                            char hex1 = '0';
1534                            char hex2 = (char)next_char;
1535
1536                            if( isHexLetterOrDigit( (char)next_char2 ) )
1537                            {
1538                                advance();
1539                                hex1 = hex2;
1540                                hex2 = (char)next_char;
1541                            }
1542                            else if( (char)next_char2 != '\'' )
1543                            {
1544                                emit_error( "Illegal hex character" );
1545                                return null;
1546                            }
1547
1548                            t = new char_token
1549                                    (
1550                                            sym.CH,
1551                                            (char)Integer.parseInt
1552                                    ( new String JavaDoc
1553                                            ( new char[]{hex1, hex2} ),
1554                                            16
1555                                    )
1556                                    );
1557
1558                        }
1559                        else if( (char)next_char == 'u' )
1560                        {
1561                            if( wide == false )
1562                            {
1563                                emit_error( "Unicode characters are only legal with wide character" );
1564                                return null;
1565                            }
1566                            else
1567                            {
1568                                // Hexadecimal character
1569
advance();
1570
1571                                char uni1 = '0';
1572                                char uni2 = '0';
1573                                char uni3 = '0';
1574                                char uni4 = (char)next_char;
1575
1576                                if( isHexLetterOrDigit( (char)next_char2 ) )
1577                                {
1578                                    advance();
1579                                    uni3 = uni4;
1580                                    uni4 = (char)next_char;
1581
1582                                    if( isHexLetterOrDigit( (char)next_char2 ) )
1583                                    {
1584                                        advance();
1585                                        uni2 = uni3;
1586                                        uni3 = uni4;
1587                                        uni4 = (char)next_char;
1588
1589                                        if( isHexLetterOrDigit( (char)next_char2 ) )
1590                                        {
1591                                            advance();
1592                                            uni1 = uni2;
1593                                            uni2 = uni3;
1594                                            uni3 = uni4;
1595                                            uni4 = (char)next_char;
1596                                        }
1597                                        else if( (char)next_char2 != '\'' )
1598                                        {
1599                                            emit_error( "Illegal unicode character" );
1600                                            return null;
1601                                        }
1602                                    }
1603                                    else if( (char)next_char2 != '\'' )
1604                                    {
1605                                        emit_error( "Illegal unicode character" );
1606                                        return null;
1607                                    }
1608                                }
1609                                else if( (char)next_char2 != '\'' )
1610                                {
1611                                    emit_error( "Illegal unicode character" );
1612                                    return null;
1613                                }
1614
1615                                t = new char_token
1616                                        (
1617                                                sym.CH,
1618                                                (char)Integer.parseInt
1619                                        ( new String JavaDoc
1620                                                ( new char[]{uni1, uni2, uni3, uni4} ),
1621                                                16
1622                                        )
1623                                        );
1624                            }
1625                        }
1626                        else
1627                        {
1628                            switch( next_char )
1629                            {
1630                                case 'n':
1631                                    {
1632                                        t = new char_token( sym.CH, '\n' );
1633                                        break;
1634                                    }
1635                                case 't':
1636                                    {
1637                                        t = new char_token( sym.CH, '\t' );
1638                                        break;
1639                                    }
1640                                case 'v':
1641                                    {
1642                                        t = new char_token( sym.CH, '\013' );
1643                                        break;
1644                                    }
1645                                case 'b':
1646                                    {
1647                                        t = new char_token( sym.CH, '\b' );
1648                                        break;
1649                                    }
1650                                case 'r':
1651                                    {
1652                                        t = new char_token( sym.CH, '\r' );
1653                                        break;
1654                                    }
1655                                case 'f':
1656                                    {
1657                                        t = new char_token( sym.CH, '\f' );
1658                                        break;
1659                                    }
1660                                case 'a':
1661                                    {
1662                                        t = new char_token( sym.CH, '\007' );
1663                                        break;
1664                                    }
1665                                case '\\':
1666                                    {
1667                                        t = new char_token( sym.CH, '\\' );
1668                                        break;
1669                                    }
1670                                case '?':
1671                                    {
1672                                        t = new char_token( sym.CH, '?' );
1673                                        break;
1674                                    }
1675                                case '0':
1676                                    {
1677                                        t = new char_token( sym.CH, '\0' );
1678                                        break;
1679                                    }
1680                                case '\'':
1681                                    {
1682                                        t = new char_token( sym.CH, '\'' );
1683                                        break;
1684                                    }
1685                                case '\"':
1686                                    {
1687                                        t = new char_token( sym.CH, '\"' );
1688                                        break;
1689                                    }
1690                                default:
1691                                    {
1692                                        emit_error( "Invalid escape symbol \'" );
1693                                        return null;
1694                                    }
1695                            }
1696                        }
1697                    }
1698                    else
1699                    {
1700                        t = new char_token( sym.CH, (char)next_char );
1701                    }
1702                    advance();
1703
1704                    if( (char)next_char == '\'' )
1705                    {
1706                        tokenStack.push( new token( sym.QUOTE ) );
1707                        tokenStack.push( t );
1708                        advance();
1709                    }
1710                    else
1711                    {
1712                        emit_error( "Expecting closing \'" );
1713                        return null;
1714                    }
1715                    wide = false;
1716
1717                    return new token( sym.QUOTE );
1718                }
1719
1720
1721                if( sym_num != -1 )
1722                {
1723                    /* found one -- advance past it and return a token for it */
1724                    advance();
1725
1726                    return new token( sym_num );
1727                }
1728
1729                /* look for an id or keyword */
1730                if( id_start_char( next_char ) )
1731                {
1732                    token t = do_symbol();
1733                    if( t != null )
1734                        return t;
1735                    else
1736                        continue;
1737                }
1738
1739                /* look for EOF */
1740                if( next_char == EOF_CHAR )
1741                {
1742                    return new token( sym.EOF );
1743                }
1744            }
1745            else // in_string
1746
{
1747
1748                /* empty string ? */
1749                if( (char)next_char == '\"' )
1750                {
1751                    in_string = false;
1752                    advance();
1753                    return new token( sym.DBLQUOTE );
1754                }
1755
1756                StringBuffer JavaDoc result = new StringBuffer JavaDoc();
1757                char previous = ' ';
1758
1759                /* collect up characters while they fit in id */
1760                while( true )
1761                {
1762                    if( next_char == '\\' )
1763                    {
1764                        // Remap those characters that have no equivilant in java
1765
switch( next_char2 )
1766                        {
1767                            case 'a':
1768                                {
1769                                    result.append( "\\007" );
1770                                    previous = 'a';
1771                                    advance();
1772                                    break;
1773                                }
1774                            case 'v':
1775                                {
1776                                    result.append( "\\013" );
1777                                    previous = 'v';
1778                                    advance();
1779                                    break;
1780                                }
1781                            case '?':
1782                                {
1783                                    result.append( "?" );
1784                                    previous = '?';
1785                                    advance();
1786                                    break;
1787                                }
1788                                // Replace \xA0 by octal equivilant
1789
case 'x':
1790                                {
1791                                    advance();
1792                                    advance();
1793
1794                                    // Now next_char will be A and next_char2 will be 0
1795
String JavaDoc octal = Integer.toOctalString
1796                                            (
1797                                                    Integer.parseInt
1798                                            (
1799                                                    new String JavaDoc
1800                                                            (
1801                                                                    new char[]{
1802                                                                        (char)next_char,
1803                                                                        (char)next_char2}
1804                                                            ),
1805                                                    16
1806                                            )
1807                                            );
1808                                    if( octal.length() != 3 )
1809                                    {
1810                                        if( octal.length() == 1 )
1811                                        {
1812                                            octal = "0" + octal;
1813                                        }
1814                                        octal = "0" + octal;
1815                                    }
1816                                    result.append( "\\" + octal );
1817                                    previous = (char)next_char2;
1818
1819                                    advance();
1820                                    break;
1821                                }
1822                            case 'u':
1823                                {
1824                                    if( wide == false )
1825                                    {
1826                                        emit_error( "Unicode characters are only legal with wide strings" );
1827                                        return null;
1828                                    }
1829                                    else
1830                                    {
1831                                        result.append( (char)next_char );
1832                                        result.append( (char)next_char2 );
1833                                        advance();
1834                                        advance();
1835
1836                                        char uni1 = (char)next_char;
1837                                        char uni2 = '0';
1838                                        char uni3 = '0';
1839                                        char uni4 = '0';
1840
1841                                        if( isHexLetterOrDigit( (char)next_char2 ) )
1842                                        {
1843                                            advance();
1844                                            uni2 = (char)next_char;
1845
1846                                            if( isHexLetterOrDigit( (char)next_char2 ) )
1847                                            {
1848                                                advance();
1849                                                uni3 = (char)next_char;
1850
1851                                                if( isHexLetterOrDigit( (char)next_char2 ) )
1852                                                {
1853                                                    advance();
1854                                                    uni4 = (char)next_char;
1855                                                }
1856                                                else
1857                                                {
1858                                                    emit_error( "Illegal unicode character" );
1859                                                    return null;
1860                                                }
1861                                            }
1862                                            else
1863                                            {
1864                                                emit_error( "Illegal unicode character" );
1865                                                return null;
1866                                            }
1867                                        }
1868                                        else
1869                                        {
1870                                            emit_error( "Illegal unicode character" );
1871                                            return null;
1872                                        }
1873
1874                                        previous = uni4;
1875                                        result.append( uni1 );
1876                                        result.append( uni2 );
1877                                        result.append( uni3 );
1878                                        result.append( uni4 );
1879                                    }
1880                                    break;
1881                                }
1882                            default:
1883                                {
1884                                    previous = (char)next_char;
1885                                    result.append( (char)next_char );
1886                                }
1887                        }
1888                    }
1889                    else
1890                    {
1891                        previous = (char)next_char;
1892                        result.append( (char)next_char );
1893                    }
1894                    advance();
1895
1896                    // Handle backslash quote but exit if just quote
1897
if( ( (char)next_char ) == '\"' && previous != '\\' )
1898                    {
1899                        break;
1900                    }
1901                }
1902                wide = false;
1903
1904                String JavaDoc s = result.toString();
1905
1906                /* build and return an id token with an attached string */
1907                return new org.jacorb.idl.str_token( sym.ID, s,
1908                        getPosition(),
1909                        GlobalInputStream.currentFile().getName() );
1910            }
1911
1912            /* if we get here, we have an unrecognized character */
1913            emit_warn( "Unrecognized character '" +
1914                    new Character JavaDoc( (char)next_char ) + "'(" + next_char + ") -- ignored" );
1915
1916            /* advance past it */
1917            advance();
1918        }
1919    }
1920
1921    /**
1922     * Returns true if character is US ASCII 0-9
1923     *
1924     * @param c a value of type 'char'
1925     * @return a value of type 'boolean'
1926     */

1927    static boolean isDigit( char c )
1928    {
1929        boolean result = false;
1930
1931        if( c >= '\u0030' )
1932        {
1933            if( c <= '\u0039' )
1934            {
1935                // Range 0030 [0] -> 0039 [9]
1936
result = true;
1937            }
1938        }
1939        return result;
1940    }
1941
1942
1943    /**
1944     * Returns true if character is US ASCII 0-9, a-f, A-F
1945     *
1946     * @param c a value of type 'char'
1947     * @return a value of type 'boolean'
1948     */

1949    private static boolean isHexLetterOrDigit( char c )
1950    {
1951        boolean result = false;
1952
1953        if( c >= '\u0030' )
1954        {
1955            if( c <= '\u0039' )
1956            {
1957                // Range 0030 [0] -> 0039 [9]
1958
result = true;
1959            }
1960            else
1961            {
1962                if( c >= '\u0041' )
1963                {
1964                    if( c <= '\u0046' )
1965                    {
1966                        // Range 0041 [A] -> 0046 [F]
1967
result = true;
1968                    }
1969                    if( c >= '\u0061' )
1970                    {
1971                        if( c <= '\u0066' )
1972                        {
1973                            // Range 0061 [a] -> 0066 [f]
1974
result = true;
1975                        }
1976                    }
1977                }
1978            }
1979        }
1980        return result;
1981    }
1982}
1983
Popular Tags