/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.lang; import com.intellij.lexer.LexerBase; import com.intellij.psi.tree.IElementType; import gw.lang.GosuShop; import gw.lang.parser.ISourceCodeTokenizer; import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class GosuLexer extends LexerBase { private ISourceCodeTokenizer _tokenizer; private CharSequence _buffer; private int _iBufferIndex; private int _iBufferEndOffset; @Nullable private IElementType _tokenType; private int _iTokenEndOffset; // Positioned after the last symbol of the current token private Method _goToPosition; public final void start(CharSequence buffer, int startOffset, int endOffset, int initialState) { _buffer = buffer; _iBufferIndex = startOffset; _iBufferEndOffset = endOffset; _tokenType = null; _iTokenEndOffset = startOffset; _tokenizer = GosuShop.createSourceCodeTokenizer(buffer); _tokenizer.setWhitespaceSignificant(true); _tokenizer.setCommentsSignificant(true); _tokenizer.setParseDotsAsOperators(true); _tokenizer.wordChars('_', '_'); if (isForTemplate()) { _tokenizer.setInstructor(GosuShop.createTemplateTokenizerInstructor(_tokenizer)); } _tokenizer.nextToken(); } protected boolean isForTemplate() { return false; } public int getState() { return 0; } public final IElementType getTokenType() { locateToken(); return _tokenType; } public final int getTokenStart() { return _iBufferIndex; } public final int getTokenEnd() { locateToken(); return _iTokenEndOffset; } public final void advance() { locateToken(); _tokenType = null; } private void locateToken() { if (_tokenType != null) { return; } if (_iTokenEndOffset == _iBufferEndOffset) { _tokenType = null; _iBufferIndex = _iBufferEndOffset; return; } // System.out.println( "INDEX: " + _iBufferIndex + " END: " + _iBufferEndOffset ); _iBufferIndex = _iTokenEndOffset; nextTokenFromTokenizer(); if (_iTokenEndOffset > _iBufferEndOffset) { _iTokenEndOffset = _iBufferEndOffset; } } private void nextTokenFromTokenizer() { goToHack(); // hack: until we expose the goToPosition() method in the api _tokenType = GosuIjTokenMap.instance().getTokenType(_tokenizer.getType()); if (_iTokenEndOffset == _tokenizer.getTokenEnd()) { _tokenizer.nextToken(); } _iTokenEndOffset = _tokenizer.getTokenEnd(); } private void goToHack() { if (_tokenizer.isEOF()) { return; } try { if (_goToPosition == null) { Class tok = Class.forName("gw.internal.gosu.parser.SourceCodeTokenizer"); _goToPosition = tok.getDeclaredMethod("goToPosition", int.class); _goToPosition.setAccessible(true); } try { _goToPosition.invoke(_tokenizer, _iBufferIndex); } catch (InvocationTargetException e) { if (e.getCause() instanceof IOException) { // Handle read past EOF e.g., unterminated comment return; } throw new RuntimeException(e); } } catch (Exception e) { throw new RuntimeException(e); } } public CharSequence getBufferSequence() { return _buffer; } public final int getBufferEnd() { return _iBufferEndOffset; } }