KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jmock > examples > calculator > Lexer


1 /* Copyright (c) 2000-2004 jMock.org
2  */

3 package org.jmock.examples.calculator;
4
5 import java.io.IOException JavaDoc;
6 import java.io.PushbackReader JavaDoc;
7 import java.io.Reader JavaDoc;
8 import java.io.StringReader JavaDoc;
9 import java.util.Stack JavaDoc;
10
11
12 public class Lexer
13 {
14     private static final int END_OF_STREAM = -1;
15     private static final char DECIMAL_PLACE = '.';
16
17     private PushbackReader JavaDoc input;
18     private StringBuffer JavaDoc tokenValue = new StringBuffer JavaDoc();
19     private Stack JavaDoc pushBack = new Stack JavaDoc();
20
21     public Lexer( Reader JavaDoc input ) {
22         this.input = new PushbackReader JavaDoc(input);
23     }
24
25     public Lexer( String JavaDoc inputString ) {
26         this(new StringReader JavaDoc(inputString));
27     }
28
29     public void pushBack( Token token ) {
30         pushBack.push(token);
31     }
32
33     public Token nextToken() throws IOException JavaDoc, ParseException {
34         if (pushBack.isEmpty()) {
35             return readToken();
36         }
37         return (Token)pushBack.pop();
38     }
39
40     private Token readToken() throws IOException JavaDoc, ParseException {
41         tokenValue.setLength(0);
42
43         skipWhitespace();
44
45         int ch = peekChar();
46
47         if (ch == END_OF_STREAM) {
48             return new Token(Token.END, null);
49         } else if (isDigit(ch)) {
50             return readNumber();
51         } else if (isIdentifierStart(ch)) {
52             return readIdentifier();
53         } else {
54             return readOperator();
55         }
56     }
57
58     public void skipWhitespace() throws IOException JavaDoc {
59         int ch;
60
61         do {
62             ch = readChar();
63         }
64         while (ch != END_OF_STREAM && Character.isWhitespace((char)ch));
65
66         unreadChar(ch);
67     }
68
69     private boolean isDigit( int ch ) {
70         return ch != END_OF_STREAM && Character.isDigit((char)ch);
71     }
72
73     private Token readNumber() throws IOException JavaDoc {
74         collectDigits();
75         if (peekChar() == DECIMAL_PLACE) {
76             tokenValue.append((char)readChar());
77             collectDigits();
78         }
79
80         return createToken(Token.NUMBER);
81     }
82
83     private void collectDigits() throws IOException JavaDoc {
84         int ch;
85
86         while (isDigit(ch = readChar())) {
87             tokenValue.append((char)ch);
88         }
89
90         unreadChar(ch);
91     }
92
93     private boolean isIdentifierStart( int ch ) {
94         return Character.isUnicodeIdentifierStart((char)ch);
95     }
96
97     private boolean isIdentifierPart( int ch ) {
98         return ch != -1 && Character.isUnicodeIdentifierPart((char)ch);
99     }
100
101     private Token readIdentifier() throws IOException JavaDoc {
102         tokenValue.append((char)readChar());
103
104         int ch;
105         while (isIdentifierPart((ch = readChar()))) {
106             tokenValue.append((char)ch);
107         }
108         unreadChar(ch);
109
110         return createToken(Token.IDENTIFIER);
111     }
112
113     private Token readOperator() throws IOException JavaDoc, ParseException {
114         int ch = readChar();
115         tokenValue.append((char)ch);
116
117         switch (ch) {
118         case '+':
119             return createToken(Token.ADD);
120         case '-':
121             return createToken(Token.SUBTRACT);
122         case '*':
123             return createToken(Token.MULTIPLY);
124         case '/':
125             return createToken(Token.DIVIDE);
126         case '^':
127             return createToken(Token.POWER);
128         case '(':
129             return createToken(Token.PAREN_OPEN);
130         case ')':
131             return createToken(Token.PAREN_CLOSE);
132
133         default:
134             throw new ParseException("unrecognised character '" + (char)ch + "'");
135         }
136     }
137
138
139     private Token createToken( int tokenType ) {
140         return new Token(tokenType, tokenValue.toString());
141     }
142
143     private int peekChar() throws IOException JavaDoc {
144         int ch = readChar();
145         unreadChar(ch);
146         return ch;
147     }
148
149     private int readChar() throws IOException JavaDoc {
150         return input.read();
151     }
152
153     private void unreadChar( int ch ) throws IOException JavaDoc {
154         if (ch != END_OF_STREAM) input.unread(ch);
155     }
156 }
157
Popular Tags