1 package fri.patterns.interpreter.parsergenerator.lexer; 2 3 import java.util.*; 4 import java.io.*; 5 import fri.patterns.interpreter.parsergenerator.Lexer; 6 import fri.patterns.interpreter.parsergenerator.Token; 7 8 19 20 public class LexerImpl implements 21 Lexer, 22 StrategyFactoryMethod, 23 Serializable 24 { 25 protected Strategy strategy; 26 private List ignoredSymbols; 27 private Map charConsumers; 28 private transient InputText input; 29 private List listeners; 30 private transient boolean debug; 31 32 37 public LexerImpl(List ignoredSymbols, Map charConsumers) { 38 setConsumers(ignoredSymbols, charConsumers); 39 } 40 41 42 protected LexerImpl() { 43 } 44 45 46 public void addTokenListener(Lexer.TokenListener tokenListener) { 47 if (listeners == null) 48 listeners = new ArrayList(1); 49 listeners.add(tokenListener); 50 } 51 52 public void removeTokenListener(Lexer.TokenListener tokenListener) { 53 if (listeners != null) 54 listeners.remove(tokenListener); 55 } 56 57 58 private void setConsumers(List ignoredSymbols, Map charConsumers) { 59 this.charConsumers = charConsumers; this.ignoredSymbols = ignoredSymbols; 62 for (int i = 0; ignoredSymbols != null && i < ignoredSymbols.size(); i++) { String sym = (String ) ignoredSymbols.get(i); 64 Consumer cc = (Consumer) charConsumers.get(sym); 65 ensureStrategy().addIgnoringConsumer(sym, cc); 66 } 67 68 for (Iterator it = charConsumers.entrySet().iterator(); it.hasNext(); ) { 70 Consumer c = (Consumer) ((Map.Entry) it.next()).getValue(); 71 if (c instanceof ConsumerAlternatives) { 72 ((ConsumerAlternatives) c).setStrategyFactoryMethod(this); 73 } 74 } 75 } 76 77 private Strategy ensureStrategy() { 78 if (strategy == null) 79 strategy = newStrategy(); 80 return strategy; 81 } 82 83 84 public Strategy newStrategy() { 85 return new Strategy(); 86 } 87 88 92 public void setCompeteForLongestInput(boolean competeForLongestInput) { 93 ensureStrategy().setCompeteForLongestInput(competeForLongestInput); 94 } 95 96 97 99 104 public void setInput(Object text) 105 throws IOException 106 { 107 input = new InputText(text); 108 } 109 110 114 public void setTerminals(List terminals) { 115 for (int i = 0; i < terminals.size(); i++) { 116 String symbol = (String ) terminals.get(i); 117 118 if (symbol.length() <= 2 || Token.isTerminal(symbol) == false) 120 throw new IllegalArgumentException ("Terminals must be enclosed within quotes: "+symbol); 121 122 String text = symbol.substring(1, symbol.length() - 1); 124 if (ensureStrategy().hasTerminal(symbol) == false) { if (symbol.charAt(0) == Token.COMMAND_QUOTE) { Consumer cc = (Consumer) charConsumers.get(text); 127 if (cc == null) 128 throw new IllegalArgumentException ("Lexer token is not among character consumers: "+text); 129 else 130 ensureStrategy().addTokenConsumer(symbol, cc); 131 } 132 else { 133 ensureStrategy().addTokenConsumer(symbol, new Consumer(text)); 134 } 135 } 136 } 138 if (debug) 139 System.err.println("StrategyList is:\n"+strategy); 140 } 141 142 143 144 public void clear() { 145 } 146 147 148 149 160 public Token getNextToken(LexerSemantic lexerSemantic) 161 throws IOException 162 { 163 return getNextToken(lexerSemantic, null); 164 } 165 166 174 public Token getNextToken(Map expectedTokenSymbols) 175 throws IOException 176 { 177 return getNextToken(null, expectedTokenSymbols); 178 } 179 180 private Token getNextToken(LexerSemantic lexerSemantic, Map expectedTokenSymbols) 181 throws IOException 182 { 183 if (input == null) 184 throw new IllegalStateException ("Lexer has no input, call setInput(...)."); 185 186 Token.Address start = new Token.Address(input.getScanLine(), input.getScanColumn(), input.getScanOffset()); 187 int c = input.peek(); if (c == Input.EOF) 189 return createToken(Token.EPSILON, null, new Token.Range(start, start)); 190 191 Strategy.Item item = getNextLexerItem(expectedTokenSymbols, c); 193 194 if (item != null) { if (ignoredSymbols != null && ignoredSymbols.indexOf(item.getSymbol()) >= 0) { 196 if (listeners != null && listeners.size() > 0) fireTokenReceived(createToken(item.getTokenIdentifier(), item.getResultTree(), lexerSemantic), true); 198 return getNextToken(expectedTokenSymbols); 199 } 200 else { 201 Token token = createToken(item.getTokenIdentifier(), item.getResultTree(), lexerSemantic); 202 fireTokenReceived(token, false); 203 return token; 204 } 205 } 206 207 Token.Address end = new Token.Address(input.getReadLine(), input.getReadColumn(), input.getScanOffset()); 209 return createToken(null, input.getUnreadText(), new Token.Range(start, end)); 210 } 211 212 private Strategy.Item getNextLexerItem(Map expectedTokenSymbols, int lookahead) 214 throws IOException 215 { 216 if (strategy == null) 217 throw new IllegalStateException ("Lexer has no terminals, call setTerminals(syntaxSeparation.getTokenSymbols())."); 218 219 Strategy.Item item = strategy.consume(input, lookahead, expectedTokenSymbols); 220 221 if (item != null) 222 input.resolveBuffer(); 224 return item; 225 } 226 227 private void fireTokenReceived(Token token, boolean ignored) { 229 for (int i = 0; listeners != null && i < listeners.size(); i++) 230 ((Lexer.TokenListener) listeners.get(i)).tokenReceived(token, ignored); 231 } 232 233 234 protected Token createToken(String tokenIdentifier, ResultTree result, LexerSemantic lexerSemantic) { 235 if (lexerSemantic != null) 236 loopResultTree(result, lexerSemantic); 237 return createToken(tokenIdentifier, result.toString(), result.getRange()); } 239 240 241 protected Token createToken(String tokenIdentifier, String text, Token.Range range) { 242 return new Token(tokenIdentifier, text, range); 243 } 244 245 246 266 public boolean lex(LexerSemantic lexerSemantic) 267 throws IOException 268 { 269 int c = input.peek(); 270 boolean eof = (c == Input.EOF); 271 boolean error = eof; 272 273 if (error == false) { 274 Strategy.Item item = getNextLexerItem(null, c); 275 error = (item == null || item.getTokenIdentifier() == null); 276 277 if (error == false && lexerSemantic != null) 278 loopResultTree(item.getResultTree(), lexerSemantic); 279 280 c = input.peek(); 281 eof = (c == Input.EOF); 282 error = (eof == false); 283 } 284 285 if (error) { 286 dump(System.err); 287 System.err.println("Could not process character '"+(char)c+"' (int "+c+"), at line/column "+input.getScanLine()+"/"+input.getScanColumn()+", at offset "+input.getScanOffset()); 288 } 289 290 return error == false; 291 } 292 293 301 protected void loopResultTree(ResultTree result, LexerSemantic lexerSemantic) { 302 Set wantedNonterminals = lexerSemantic.getWantedNonterminals(); 303 Set ignoredNonterminals = lexerSemantic.getIgnoredNonterminals(); 304 String nonterminal = result.getRule().getNonterminal(); 305 306 if (nonterminal.startsWith(Token.ARTIFICIAL_NONTERMINAL_START_CHARACTER) == false && 307 (wantedNonterminals == null || wantedNonterminals.contains(nonterminal)) && 308 (ignoredNonterminals == null || ignoredNonterminals.contains(nonterminal) == false)) 309 { 310 lexerSemantic.ruleEvaluated(result.getRule(), result); 311 } 312 313 for (int i = 0; i < result.getChildCount(); i++) { 314 Object child = result.getChild(i); 315 if (child instanceof ResultTree) 316 loopResultTree((ResultTree) child, lexerSemantic); 317 } 318 } 319 320 321 322 324 325 public void setDebug(boolean debug) { 326 this.debug = debug; 327 } 328 329 330 public String getLineText() { 331 return input.getLine(); 332 } 333 334 335 public int getLine() { 336 return input.getReadLine(); 337 } 338 339 340 public int getColumn() { 341 return input.getReadColumn(); 342 } 343 344 345 public int getOffset() { 346 return input.getScanOffset(); 347 } 348 349 350 351 public void dump(PrintStream out) { 352 int lineNr = input.getReadLine(); 353 String line = getLineText(); 354 355 if (lineNr > 1) { 356 String prevLine = input.getPreviousLine(); 357 out.print((lineNr - 1)+":\t"); 358 out.println(prevLine); 359 } 360 361 out.print(lineNr+":\t"); 362 out.println(line); 363 364 int nrLen = Integer.toString(lineNr).length(); 365 for (int i = 0; i < nrLen; i++) 366 out.print(" "); 367 368 out.print("\t"); 369 370 int errPos = input.getReadColumn(); 371 372 for (int i = 0; i < errPos && i < line.length(); i++) 373 if (line.charAt(i) == '\t') 374 out.print("\t"); 375 else 376 out.print(" "); 377 378 out.println("^"); 379 } 380 381 } 382 | Popular Tags |