processing.app.syntax.PdeTokenMarker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pde Show documentation
Show all versions of pde Show documentation
Processing is a programming language, development environment, and online community.
This PDE package contains the Processing IDE.
The newest version!
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
PdeKeywords - handles text coloring and links to html reference
Part of the Processing project - http://processing.org
Copyright (c) 2004-12 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package processing.app.syntax;
import javax.swing.text.Segment;
import processing.app.ui.Editor;
public class PdeTokenMarker extends TokenMarker {
protected KeywordMap keywordColoring;
// protected int lastOffset;
// protected int lastKeyword;
/**
* Add a keyword, and the associated coloring. KEYWORD2 and KEYWORD3
* should only be used with functions (where parens are present).
* This is done for the extra paren handling.
* @param coloring one of KEYWORD1, KEYWORD2, LITERAL1, etc.
*/
public void addColoring(String keyword, String coloring) {
if (keywordColoring == null) {
keywordColoring = new KeywordMap(false);
}
// KEYWORD1 -> 0, KEYWORD2 -> 1, etc
int num = coloring.charAt(coloring.length() - 1) - '1';
// byte id = (byte) ((isKey ? Token.KEYWORD1 : Token.LITERAL1) + num);
int id = 0;
switch (coloring.charAt(0)) {
case 'K':
id = Token.KEYWORD1 + num;
keywordColoring.add(keyword, (byte) id, false);
if (id == Token.KEYWORD6) {
// these can be followed by parens
keywordColoring.add(keyword, (byte) id, true);
}
break;
case 'L':
id = Token.LITERAL1 + num;
keywordColoring.add(keyword, (byte) id, false);
break;
case 'F':
id = Token.FUNCTION1 + num;
keywordColoring.add(keyword, (byte) id, true);
break;
}
}
class MarkerState {
int lastOffset;
int lastKeyword;
MarkerState(int offset) {
lastOffset = offset;
lastKeyword = offset;
}
}
public byte markTokensImpl(byte token, Segment line, int lineIndex) {
char[] array = line.array;
int offset = line.offset;
// lastOffset = offset;
// lastKeyword = offset;
MarkerState ms = new MarkerState(offset);
int mlength = offset + line.count;
boolean backslash = false;
loop: for (int i = offset; i < mlength; i++) {
int i1 = (i + 1);
char c = array[i];
if (c == '\\') {
backslash = !backslash;
continue;
}
switch (token) {
case Token.NULL:
switch (c) {
case '#':
if (backslash)
backslash = false;
break;
case '"':
doKeyword(ms, line, i, c);
if (backslash)
backslash = false;
else {
addToken(i - ms.lastOffset, token);
token = Token.LITERAL1;
ms.lastOffset = ms.lastKeyword = i;
}
break;
case '\'':
doKeyword(ms, line, i, c);
if (backslash)
backslash = false;
else {
addToken(i - ms.lastOffset, token);
token = Token.LITERAL2;
ms.lastOffset = ms.lastKeyword = i;
}
break;
case ':':
if (ms.lastKeyword == offset) {
if (doKeyword(ms, line, i, c))
break;
backslash = false;
addToken(i1 - ms.lastOffset, Token.LABEL);
ms.lastOffset = ms.lastKeyword = i1;
} else if (doKeyword(ms, line, i, c))
break;
break;
case '/':
backslash = false;
doKeyword(ms, line, i, c);
if (mlength - i > 1) {
switch (array[i1]) {
case '*':
addToken(i - ms.lastOffset, token);
ms.lastOffset = ms.lastKeyword = i;
if (mlength - i > 2 && array[i + 2] == '*')
token = Token.COMMENT2;
else
token = Token.COMMENT1;
break;
case '/':
addToken(i - ms.lastOffset, token);
addToken(mlength - i, Token.COMMENT1);
ms.lastOffset = ms.lastKeyword = mlength;
break loop;
}
// https://github.com/processing/processing/issues/1681
if (array[i1] != ' ') {
i++; // http://processing.org/bugs/bugzilla/609.html [jdf]
}
}
break;
default:
backslash = false;
if (!Character.isLetterOrDigit(c) && c != '_') {
doKeyword(ms, line, i, c);
}
break;
}
break;
case Token.COMMENT1:
case Token.COMMENT2:
backslash = false;
if (c == '*' && mlength - i > 1) {
if (array[i1] == '/') {
i++;
addToken((i + 1) - ms.lastOffset, token);
token = Token.NULL;
ms.lastOffset = ms.lastKeyword = i + 1;
}
}
break;
case Token.LITERAL1:
if (backslash)
backslash = false;
else if (c == '"') {
addToken(i1 - ms.lastOffset, token);
token = Token.NULL;
ms.lastOffset = ms.lastKeyword = i1;
}
break;
case Token.LITERAL2:
if (backslash)
backslash = false;
else if (c == '\'') {
addToken(i1 - ms.lastOffset, Token.LITERAL1);
token = Token.NULL;
ms.lastOffset = ms.lastKeyword = i1;
}
break;
default:
throw new InternalError("Invalid state: " + token);
}
}
if (token == Token.NULL) {
doKeyword(ms, line, mlength, '\0');
}
switch (token) {
case Token.LITERAL1:
case Token.LITERAL2:
addToken(mlength - ms.lastOffset, Token.INVALID);
token = Token.NULL;
break;
case Token.KEYWORD2:
addToken(mlength - ms.lastOffset, token);
if (!backslash)
token = Token.NULL;
addToken(mlength - ms.lastOffset, token);
break;
default:
addToken(mlength - ms.lastOffset, token);
break;
}
return token;
}
protected boolean doKeyword(MarkerState ms, Segment line, int i, char c) {
int i1 = i + 1;
int len = i - ms.lastKeyword;
boolean paren = Editor.checkParen(line.array, i, line.array.length);
byte id = keywordColoring.lookup(line, ms.lastKeyword, len, paren);
if (id != Token.NULL) {
if (ms.lastKeyword != ms.lastOffset) {
addToken(ms.lastKeyword - ms.lastOffset, Token.NULL);
}
addToken(len, id);
ms.lastOffset = i;
}
ms.lastKeyword = i1;
return false;
}
}