package org.rubypeople.rdt.internal.core.util; import java.io.CharArrayReader; import java.io.IOException; import org.jruby.CompatVersion; import org.jruby.common.NullWarnings; import org.jruby.lexer.yacc.LexerSource; import org.jruby.lexer.yacc.RubyYaccLexer; import org.jruby.lexer.yacc.SyntaxException; import org.jruby.lexer.yacc.RubyYaccLexer.LexState; import org.jruby.parser.ParserConfiguration; import org.jruby.parser.ParserSupport; import org.jruby.parser.RubyParserResult; import org.jruby.util.KCode; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.compiler.IScanner; import org.rubypeople.rdt.core.compiler.InvalidInputException; public class PublicScanner implements IScanner { private char[] source; private RubyYaccLexer lexer; private ParserSupport parserSupport; private RubyParserResult result; private LexerSource lexerSource; private int fOffset; private int fTokenLength; public PublicScanner() { // FIXME This probably doesn't handle unicode at all! lexer = new RubyYaccLexer(); parserSupport = new ParserSupport(); ParserConfiguration config = new ParserConfiguration(KCode.NIL, 0, true, false, CompatVersion.RUBY1_8); parserSupport.setConfiguration(config); result = new RubyParserResult(); parserSupport.setResult(result); lexer.setParserSupport(parserSupport); lexer.setWarnings(new NullWarnings()); lexer.setEncoding(config.getKCode().getEncoding()); } public int getCurrentTokenEndPosition() { return fOffset + fTokenLength; } public int getCurrentTokenStartPosition() { return fTokenLength; } public int getNextToken() throws InvalidInputException { fOffset = lexerSource.getOffset(); fTokenLength = 0; int returnValue = 0; boolean isEOF = false; try { isEOF = !lexer.advance(); if (isEOF) { returnValue = TokenNameEOF; } else { fTokenLength = lexerSource.getOffset() - fOffset; returnValue = lexer.token(); } } catch (SyntaxException se) { if (lexerSource.getOffset() == 0 || fOffset >= source.length) return TokenNameEOF; // return eof if we hit a problem found at // end of parsing fTokenLength = lexerSource.getOffset() - fOffset; return 0; } catch (NumberFormatException nfe) { fTokenLength = lexerSource.getOffset() - fOffset; return returnValue; } catch (IOException e) { RubyCore.log(e); } return returnValue; } public void setSource(char[] source) { this.source = source; lexer.reset(); lexer.setState(LexState.EXPR_BEG); parserSupport.initTopLocalVariables(); ParserConfiguration config = new ParserConfiguration(KCode.NIL, 0, true, false, CompatVersion.RUBY1_8); lexerSource = LexerSource.getSource("filename", new CharArrayReader(source), null, config); lexer.setSource(lexerSource); } }