-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLexicalAnalyzer.java
More file actions
113 lines (101 loc) · 3.52 KB
/
LexicalAnalyzer.java
File metadata and controls
113 lines (101 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import java.util.Arrays;
/**
* A LexicalAnalyzer breaks a String into Tokens.
*
* <pre>
* lexer.fetchNextToken();
* Token t1 = lexer.getCurrentToken();
* </pre>
*/
public final class LexicalAnalyzer {
private Token token;
private String text;
private int position;
private TokenFactory[] tokenFactories;
/**
* Create an analyzer for the given text,
* using the given factories to recognize and create tokens.
* @param expression The text to analyze
* @param factories The token factories to use
*/
public LexicalAnalyzer(final String expression, final TokenFactory[] factories) {
tokenFactories = Arrays.copyOf(factories, factories.length);
setText(expression);
}
/**
* Create an analyzer for the given text.
* @param expression The text to analyze
*/
public LexicalAnalyzer(final String expression) {
this(expression, new TokenFactory[] {
new IdentifierTokenFactory(),
new LiteralTokenFactory(),
new OperatorTokenFactory("+", TokenType.PLUS),
new OperatorTokenFactory("-", TokenType.MINUS),
new OperatorTokenFactory("*", TokenType.STAR),
new OperatorTokenFactory("/", TokenType.SLASH),
new OperatorTokenFactory("=", TokenType.EQUAL),
new OperatorTokenFactory(" ", TokenType.SPACE),
new OperatorTokenFactory("%", TokenType.PERCENT),
new OperatorTokenFactory("(", TokenType.OPEN_PAREN),
new OperatorTokenFactory(")", TokenType.CLOSED_PAREN),
new OperatorTokenFactory("^", TokenType.HAT),
new OperatorTokenFactory(":", TokenType.COLON),
new OperatorTokenFactory(">", TokenType.GR_THAN),
new OperatorTokenFactory(",", TokenType.COMMA),
});
}
/**
* Provide a new text to analyze.
* @param expression The text to analyze
*/
public void setText(final String expression) {
token = null;
text = expression;
position = 0;
for (final TokenFactory factory : tokenFactories) {
factory.setText(expression);
}
}
/**
* Ask the analyzer to move to the next token in the text.
*/
public void fetchNextToken() {
token = scanToken();
}
/**
* Scan the text and extract the next token.
* @return the next token
*/
private Token scanToken() {
if (position == text.length()) {
return new Token(TokenType.END_OF_FILE, "", position);
} else {
int maxLength = 0;
TokenFactory factoryWithLongestMatch = null;
// Utilize the tokenFactories to find a factory has the longest match
for (final TokenFactory factory : tokenFactories) {
if (factory.find(position)) {
if (factory.getTokenLength() > maxLength) {
factoryWithLongestMatch = factory;
maxLength = factory.getTokenLength();
}
}
}
// if no match is found then return null, otherwise produce a token
if (factoryWithLongestMatch == null) {
return null;
} else {
position += factoryWithLongestMatch.getTokenLength();
return factoryWithLongestMatch.getToken();
}
}
}
/**
* Get the current token.
* @return the current token
*/
public Token getCurrentToken() {
return token;
}
}