1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/*
2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Conditions Of Use
3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* This software was developed by employees of the National Institute of
5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Standards and Technology (NIST), an agency of the Federal Government.
6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Pursuant to title 15 Untied States Code Section 105, works of NIST
7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* employees are not subject to copyright protection in the United States
8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* and are considered to be in the public domain.  As a result, a formal
9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* license is not needed to use the software.
10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* This software is provided by NIST as a service and is expressly
12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* AND DATA ACCURACY.  NIST does not warrant or make any representations
16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* regarding the use of the software or the results thereof, including but
17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* not limited to the correctness, accuracy, reliability or usefulness of
18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* the software.
19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Permission to use this software is contingent upon your acceptance
21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* of the terms of this agreement
22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* .
24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*
25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*/
26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.core;
27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException;
29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Hashtable;
30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** A lexical analyzer that is used by all parsers in our implementation.
32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *@version 1.2
34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *@since 1.1
35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *@author M. Ranganathan
37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class LexerCore extends StringTokenizer {
39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // IMPORTANT - All keyword matches should be between START and END
41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int START = 2048;
42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int END = START + 2048;
43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // IMPORTANT -- This should be < END
44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int ID = END - 1;
45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int SAFE = END - 2;
46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Individial token classes.
47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int WHITESPACE = END + 1;
48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int DIGIT = END + 2;
49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int ALPHA = END + 3;
50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int BACKSLASH = (int) '\\';
51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int QUOTE = (int) '\'';
52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int AT = (int) '@';
53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int SP = (int) ' ';
54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int HT = (int) '\t';
55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int COLON = (int) ':';
56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int STAR = (int) '*';
57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int DOLLAR = (int) '$';
58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int PLUS = (int) '+';
59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int POUND = (int) '#';
60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int MINUS = (int) '-';
61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int DOUBLEQUOTE = (int) '\"';
62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int TILDE = (int) '~';
63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int BACK_QUOTE = (int) '`';
64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int NULL = (int) '\0';
65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int EQUALS = (int) '=';
66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int SEMICOLON = (int) ';';
67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int SLASH = (int) '/';
68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int L_SQUARE_BRACKET = (int) '[';
69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int R_SQUARE_BRACKET = (int) ']';
70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int R_CURLY = (int) '}';
71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int L_CURLY = (int) '{';
72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int HAT = (int) '^';
73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int BAR = (int) '|';
74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int DOT = (int) '.';
75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int EXCLAMATION = (int) '!';
76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int LPAREN = (int) '(';
77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int RPAREN = (int) ')';
78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int GREATER_THAN = (int) '>';
79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int LESS_THAN = (int) '<';
80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int PERCENT = (int) '%';
81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int QUESTION = (int) '?';
82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int AND = (int) '&';
83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final int UNDERSCORE = (int) '_';
84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final Hashtable globalSymbolTable;
86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final Hashtable lexerTables;
87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected Hashtable currentLexer;
88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected String currentLexerName;
89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected Token currentMatch;
90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    static {
92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        globalSymbolTable = new Hashtable();
93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        lexerTables = new Hashtable();
94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void addKeyword(String name, int value) {
97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // System.out.println("addKeyword " + name + " value = " + value);
98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // new Exception().printStackTrace();
99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Integer val = Integer.valueOf(value);
100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        currentLexer.put(name, val);
101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!globalSymbolTable.containsKey(val))
102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            globalSymbolTable.put(val, name);
103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String lookupToken(int value) {
106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (value > START) {
107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return (String) globalSymbolTable.get(Integer.valueOf(value));
108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else {
109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Character ch = Character.valueOf((char) value);
110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return ch.toString();
111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected Hashtable addLexer(String lexerName) {
115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        currentLexer = (Hashtable) lexerTables.get(lexerName);
116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (currentLexer == null) {
117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            currentLexer = new Hashtable();
118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            lexerTables.put(lexerName, currentLexer);
119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return currentLexer;
121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    //public abstract void selectLexer(String lexerName);
124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void selectLexer(String lexerName) {
126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.currentLexerName = lexerName;
127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected LexerCore() {
130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.currentLexer = new Hashtable();
131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.currentLexerName = "charLexer";
132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Initialize the lexer with a buffer.
135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public LexerCore(String lexerName, String buffer) {
137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        super(buffer);
138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.currentLexerName = lexerName;
139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Peek the next id but dont move the buffer pointer forward.
142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String peekNextId() {
145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int oldPtr = ptr;
146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String retval = ttoken();
147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        savedPtr = ptr;
148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        ptr = oldPtr;
149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval;
150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Get the next id.
153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getNextId() {
155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return ttoken();
156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // call this after you call match
159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Token getNextToken() {
160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.currentMatch;
161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Look ahead for one token.
165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Token peekNextToken() throws ParseException {
167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return (Token) peekNextToken(1)[0];
168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Token[] peekNextToken(int ntokens) throws ParseException {
171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int old = ptr;
172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Token[] retval = new Token[ntokens];
173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        for (int i = 0; i < ntokens; i++) {
174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Token tok = new Token();
175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (startsId()) {
176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String id = ttoken();
177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                tok.tokenValue = id;
178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String idUppercase = id.toUpperCase();
179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (currentLexer.containsKey(idUppercase)) {
180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    Integer type = (Integer) currentLexer.get(idUppercase);
181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    tok.tokenType = type.intValue();
182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else
183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    tok.tokenType = ID;
184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char nextChar = getNextChar();
186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                tok.tokenValue = String.valueOf(nextChar);
187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (isAlpha(nextChar)) {
188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    tok.tokenType = ALPHA;
189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else if (isDigit(nextChar)) {
190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    tok.tokenType = DIGIT;
191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else
192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    tok.tokenType = (int) nextChar;
193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            retval[i] = tok;
195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        savedPtr = ptr;
197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        ptr = old;
198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval;
199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Match the given token or throw an exception if no such token
202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * can be matched.
203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Token match(int tok) throws ParseException {
205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (Debug.parserDebug) {
206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Debug.println("match " + tok);
207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (tok > START && tok < END) {
209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (tok == ID) {
210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Generic ID sought.
211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (!startsId())
212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new ParseException(buffer + "\nID expected", ptr);
213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String id = getNextId();
214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch = new Token();
215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenValue = id;
216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenType = ID;
217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (tok == SAFE) {
218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (!startsSafeToken())
219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new ParseException(buffer + "\nID expected", ptr);
220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String id = ttokenSafe();
221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch = new Token();
222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenValue = id;
223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenType = SAFE;
224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String nexttok = getNextId();
226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Integer cur = (Integer) currentLexer.get(nexttok.toUpperCase());
227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (cur == null || cur.intValue() != tok)
229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new ParseException(
230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        buffer + "\nUnexpected Token : " + nexttok,
231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        ptr);
232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch = new Token();
233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenValue = nexttok;
234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenType = tok;
235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else if (tok > END) {
237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Character classes.
238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            char next = lookAhead(0);
239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (tok == DIGIT) {
240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (!isDigit(next))
241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new ParseException(buffer + "\nExpecting DIGIT", ptr);
242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch = new Token();
243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenValue =
244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    String.valueOf(next);
245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenType = tok;
246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                consume(1);
247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (tok == ALPHA) {
249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (!isAlpha(next))
250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new ParseException(buffer + "\nExpecting ALPHA", ptr);
251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch = new Token();
252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenValue =
253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    String.valueOf(next);
254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenType = tok;
255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                consume(1);
256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else {
260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // This is a direct character spec.
261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            char ch = (char) tok;
262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            char next = lookAhead(0);
263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (next == ch) {
264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                /*this.currentMatch = new Token();
265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenValue =
266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    String.valueOf(ch);
267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                this.currentMatch.tokenType = tok;*/
268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                consume(1);
269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else
270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new ParseException(
271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    buffer + "\nExpecting  >>>" + ch + "<<< got >>>"
272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    + next + "<<<", ptr);
273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.currentMatch;
275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void SPorHT() {
278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            char c = lookAhead(0);
280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (c == ' ' || c == '\t') {
281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                consume(1);
282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                c = lookAhead(0);
283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Ignore
286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * JvB: utility function added to validate tokens
291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see RFC3261 section 25.1:
293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * token       =  1*(alphanum / "-" / "." / "!" / "%" / "*"
294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                     / "_" / "+" / "`" / "'" / "~" )
295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param c - character to check
297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return true iff character c is a valid token character as per RFC3261
298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final boolean isTokenChar( char c ) {
300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if ( isAlphaDigit(c) ) return true;
301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        else switch (c)
302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        {
303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '-':
304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '.':
305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '!':
306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '%':
307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '*':
308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '_':
309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '+':
310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '`':
311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '\'':
312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            case '~':
313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return true;
314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            default:
315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return false;
316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean startsId() {
321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            char nextChar = lookAhead(0);
323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return isTokenChar(nextChar);
324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return false;
326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean startsSafeToken() {
330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            char nextChar = lookAhead(0);
332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (isAlphaDigit(nextChar)) {
333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return true;
334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            else {
336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                switch (nextChar) {
337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '_':
338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '+':
339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '-':
340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '!':
341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '`':
342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '\'':
343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '.':
344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '/':
345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '}':
346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '{':
347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case ']':
348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '[':
349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '^':
350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '|':
351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '~':
352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '%': // bug fix by Bruno Konik, JvB copied here
353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '#':
354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '@':
355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '$':
356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case ':':
357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case ';':
358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '?':
359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '\"':
360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '*':
361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    case '=': // Issue 155 on java.net
362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return true;
363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    default:
364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return false;
365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return false;
369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String ttoken() {
373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int startIdx = ptr;
374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (hasMoreChars()) {
376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char nextChar = lookAhead(0);
377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if ( isTokenChar(nextChar) ) {
378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    consume(1);
379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    break;
381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return buffer.substring(startIdx, ptr);
384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return null;
386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /* JvB: unreferenced
390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String ttokenAllowSpace() {
391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int startIdx = ptr;
392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (hasMoreChars()) {
394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char nextChar = lookAhead(0);
395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (isAlphaDigit(nextChar)) {
396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    consume(1);
397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else {
399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    boolean isValidChar = false;
400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    switch (nextChar) {
401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '_':
402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '+':
403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '-':
404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '!':
405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '`':
406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '\'':
407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '~':
408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '%': // bug fix by Bruno Konik, JvB copied here
409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '.':
410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case ' ':
411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '\t':
412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '*':
413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            isValidChar = true;
414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (isValidChar) {
416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        consume(1);
417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else {
419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        break;
420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return buffer.substring(startIdx, ptr);
425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return null;
427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }*/
429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String ttokenSafe() {
431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int startIdx = ptr;
432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (hasMoreChars()) {
434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char nextChar = lookAhead(0);
435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (isAlphaDigit(nextChar)) {
436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    consume(1);
437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else {
439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    boolean isValidChar = false;
440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    switch (nextChar) {
441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '_':
442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '+':
443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '-':
444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '!':
445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '`':
446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '\'':
447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '.':
448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '/':
449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '}':
450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '{':
451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case ']':
452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '[':
453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '^':
454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '|':
455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '~':
456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '%': // bug fix by Bruno Konik, JvB copied here
457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '#':
458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '@':
459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '$':
460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case ':':
461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case ';':
462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '?':
463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '\"':
464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case '*':
465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            isValidChar = true;
466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (isValidChar) {
468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        consume(1);
469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    else {
471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        break;
472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return buffer.substring(startIdx, ptr);
476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return null;
478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    static final char ALPHA_VALID_CHARS = Character.MAX_VALUE;
482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    static final char DIGIT_VALID_CHARS = Character.MAX_VALUE - 1;
483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    static final char ALPHADIGIT_VALID_CHARS = Character.MAX_VALUE - 2;
484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void consumeValidChars(char[] validChars) {
485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int validCharsLength = validChars.length;
486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (hasMoreChars()) {
488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char nextChar = lookAhead(0);
489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                boolean isValid = false;
490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                for (int i = 0; i < validCharsLength; i++) {
491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    char validChar = validChars[i];
492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    switch(validChar) {
493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case ALPHA_VALID_CHARS:
494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            isValid = isAlpha(nextChar);
495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            break;
496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case DIGIT_VALID_CHARS:
497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            isValid = isDigit(nextChar);
498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            break;
499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        case ALPHADIGIT_VALID_CHARS:
500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            isValid = isAlphaDigit(nextChar);
501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            break;
502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        default:
503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            isValid = nextChar == validChar;
504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (isValid) {
506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        break;
507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (isValid) {
510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    consume(1);
511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else {
513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    break;
514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Parse a comment string cursor is at a ". Leave cursor at closing "
522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    *@return the substring containing the quoted string excluding the
523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    * closing quote.
524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    */
525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String quotedString() throws ParseException {
526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int startIdx = ptr + 1;
527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (lookAhead(0) != '\"')
528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return null;
529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        consume(1);
530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        while (true) {
531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            char next = getNextChar();
532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (next == '\"') {
533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Got to the terminating quote.
534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                break;
535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (next == '\0') {
536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new ParseException(
537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    this.buffer + " :unexpected EOL",
538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    this.ptr);
539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (next == '\\') {
540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                consume(1);
541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return buffer.substring(startIdx, ptr - 1);
544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Parse a comment string cursor is at a "(". Leave cursor at )
547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    *@return the substring containing the comment excluding the
548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    * closing brace.
549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    */
550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String comment() throws ParseException {
551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        StringBuffer retval = new StringBuffer();
552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (lookAhead(0) != '(')
553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return null;
554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        consume(1);
555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        while (true) {
556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            char next = getNextChar();
557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (next == ')') {
558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                break;
559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (next == '\0') {
560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new ParseException(
561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    this.buffer + " :unexpected EOL",
562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    this.ptr);
563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (next == '\\') {
564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                retval.append(next);
565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                next = getNextChar();
566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (next == '\0')
567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new ParseException(
568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        this.buffer + " : unexpected EOL",
569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        this.ptr);
570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                retval.append(next);
571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                retval.append(next);
573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval.toString();
576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Return a substring containing no semicolons.
579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    *@return a substring containing no semicolons.
580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    */
581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String byteStringNoSemicolon() {
582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        StringBuffer retval = new StringBuffer();
583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (true) {
585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char next = lookAhead(0);
586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // bug fix from Ben Evans.
587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (next == '\0' || next == '\n' || next == ';' || next == ',' ) {
588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    break;
589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    consume(1);
591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    retval.append(next);
592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return retval.toString();
596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval.toString();
598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Scan until you see a slash or an EOL.
602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return substring containing no slash.
604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String byteStringNoSlash() {
606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        StringBuffer retval = new StringBuffer();
607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (true) {
609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char next = lookAhead(0);
610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // bug fix from Ben Evans.
611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (next == '\0' || next == '\n' || next == '/'  ) {
612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    break;
613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    consume(1);
615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    retval.append(next);
616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return retval.toString();
620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval.toString();
622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Return a substring containing no commas
625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    *@return a substring containing no commas.
626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    */
627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String byteStringNoComma() {
629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        StringBuffer retval = new StringBuffer();
630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (true) {
632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char next = lookAhead(0);
633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (next == '\n' || next == ',') {
634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    break;
635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    consume(1);
637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    retval.append(next);
638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval.toString();
643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static String charAsString(char ch) {
646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return String.valueOf(ch);
647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Lookahead in the inputBuffer for n chars and return as a string.
650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Do not consume the input.
651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String charAsString(int nchars) {
653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return buffer.substring(ptr, ptr + nchars);
654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Get and consume the next number.
657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *@return a substring corresponding to a number
658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *(i.e. sequence of digits).
659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String number() throws ParseException {
661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int startIdx = ptr;
663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (!isDigit(lookAhead(0))) {
665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new ParseException(
666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    buffer + ": Unexpected token at " + lookAhead(0),
667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ptr);
668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            consume(1);
670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (true) {
671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char next = lookAhead(0);
672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (isDigit(next)) {
673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    consume(1);
674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else
675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    break;
676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return buffer.substring(startIdx, ptr);
678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return buffer.substring(startIdx, ptr);
680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Mark the position for backtracking.
684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *@return the current location of the pointer.
685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public int markInputPosition() {
687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return ptr;
688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Rewind the input ptr to the marked position.
691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *@param position - the position to rewind the parser to.
692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void rewindInputPosition(int position) {
694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.ptr = position;
695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Get the rest of the String
698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return rest of the buffer.
699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getRest() {
701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (ptr >= buffer.length())
702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return null;
703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        else
704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return buffer.substring(ptr);
705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Get the sub-String until the character is encountered
708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param c the character to match
709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return the substring that matches.
710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getString(char c) throws ParseException {
712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        StringBuffer retval = new StringBuffer();
713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        while (true) {
714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            char next = lookAhead(0);
715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            //System.out.println(" next = [" + next + ']' + "ptr = " + ptr);
716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            //System.out.println(next == '\0');
717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (next == '\0') {
719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new ParseException(
720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    this.buffer + "unexpected EOL",
721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    this.ptr);
722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (next == c) {
723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                consume(1);
724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                break;
725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (next == '\\') {
726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                consume(1);
727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                char nextchar = lookAhead(0);
728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (nextchar == '\0') {
729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new ParseException(
730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        this.buffer + "unexpected EOL",
731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        this.ptr);
732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    consume(1);
734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    retval.append(nextchar);
735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                consume(1);
738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                retval.append(next);
739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval.toString();
742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Get the read pointer.
745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public int getPtr() {
747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.ptr;
748600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
749600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
750600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Get the buffer.
751600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
752600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getBuffer() {
753600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.buffer;
754600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
755600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
756600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Create a parse exception.
757600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
758600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public ParseException createParseException() {
759600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return new ParseException(this.buffer, this.ptr);
760600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
761600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
762