/* * Copyright (C) 2007, 2008 Quadduc <quadduc@gmail.com> * * This file is part of LateralGM. * LateralGM is free software and comes with ABSOLUTELY NO WARRANTY. * See LICENSE for details. */ package org.lateralgm.jedit; import javax.swing.text.Segment; public class GMLTokenMarker extends TokenMarker { private static KeywordMap gmlKeywords; private KeywordMap stdKeywords, customKeywords; private int lastOffset; private int lastKeyword; private static final byte DQSTRING = Token.INTERNAL_FIRST; private static final byte SQSTRING = Token.INTERNAL_FIRST + 1; public GMLTokenMarker() { stdKeywords = getKeywords(); customKeywords = null; } @Override protected byte markTokensImpl(byte token, Segment line, int lineIndex) { char[] array = line.array; int offset = line.offset; lastOffset = offset; lastKeyword = offset; int length = line.count + offset; loop: for (int i = offset; i < length; i++) { int i1 = (i + 1); char c = array[i]; switch (token) { case Token.NULL: switch (c) { case '"': doKeyword(line,i); addToken(i - lastOffset,token); token = DQSTRING; lastOffset = i; lastKeyword = i; break; case '\'': doKeyword(line,i); addToken(i - lastOffset,token); token = SQSTRING; lastOffset = i; lastKeyword = i; break; case '/': doKeyword(line,i); if (length - i > 1) { switch (array[i1]) { case '*': addToken(i - lastOffset,token); lastOffset = i; lastKeyword = i; if (length - i > 2 && array[i + 2] == '*') token = Token.COMMENT2; else token = Token.COMMENT1; break; case '/': addToken(i - lastOffset,token); addToken(length - i,Token.COMMENT1); lastOffset = length; lastKeyword = length; break loop; } } break; case '{': case '}': addToken(i - lastOffset,token); addToken(1,Token.KEYWORD1); token = Token.NULL; lastOffset = i1; lastKeyword = i1; break; default: if (!Character.isLetterOrDigit(c) && c != '_') doKeyword(line,i); break; } case Token.COMMENT1: case Token.COMMENT2: if (c == '*' && length - i > 1) { if (array[i1] == '/') { i++; addToken((i + 1) - lastOffset,token); token = Token.NULL; lastOffset = i + 1; lastKeyword = i + 1; } } break; case DQSTRING: if (c == '"') { addToken(i1 - lastOffset,Token.LITERAL1); token = Token.NULL; lastOffset = i1; lastKeyword = i1; } break; case SQSTRING: if (c == '\'') { addToken(i1 - lastOffset,Token.LITERAL1); token = Token.NULL; lastOffset = i1; lastKeyword = i1; } break; default: throw new InternalError("Invalid state: " + token); } } if (token == Token.NULL) doKeyword(line,length); switch (token) { case DQSTRING: case SQSTRING: addToken(length - lastOffset,Token.LITERAL1); break; default: addToken(length - lastOffset,token); break; } return token; } public void setCustomKeywords(KeywordMap km) { customKeywords = km; } public static KeywordMap getKeywords() { if (gmlKeywords == null) { gmlKeywords = new KeywordMap(false); for (GMLKeywords.Construct keyword : GMLKeywords.CONSTRUCTS) gmlKeywords.add(keyword.getName(),Token.KEYWORD1); for (GMLKeywords.Operator keyword : GMLKeywords.OPERATORS) gmlKeywords.add(keyword.getName(),Token.OPERATOR); for (GMLKeywords.Constant keyword : GMLKeywords.CONSTANTS) gmlKeywords.add(keyword.getName(),Token.LITERAL2); for (GMLKeywords.Variable keyword : GMLKeywords.VARIABLES) gmlKeywords.add(keyword.getName(),Token.KEYWORD2); for (GMLKeywords.Function keyword : GMLKeywords.FUNCTIONS) gmlKeywords.add(keyword.getName(),Token.LABEL); } return gmlKeywords; } private boolean doKeyword(Segment line, int i) { int i1 = i + 1; int len = i - lastKeyword; byte id = stdKeywords.lookup(line,lastKeyword,len); if (id == Token.NULL && customKeywords != null) id = customKeywords.lookup(line,lastKeyword,len); if (id != Token.NULL) { if (lastKeyword != lastOffset) addToken(lastKeyword - lastOffset,Token.NULL); addToken(len,id); lastOffset = i; } lastKeyword = i1; return false; } }