410 lines
17 KiB
Java
410 lines
17 KiB
Java
package _VisualDVM.Visual.Syntax;
|
||
import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
|
||
import org.fife.ui.rsyntaxtextarea.Token;
|
||
import org.fife.ui.rsyntaxtextarea.TokenMap;
|
||
|
||
import javax.swing.text.Segment;
|
||
public class FortranSPFTokenMaker extends ProvidedTokenMaker {
|
||
@Override
|
||
public TokenMap getWordsToHighlight() {
|
||
TokenMap tokenMap = new TokenMap(true);
|
||
fillTokenMap(tokenMap, Token.RESERVED_WORD,
|
||
"FORALL", "ENDFORALL", "PUBLIC", "PRIVATE", "ADMIT", "ASSIGNMENT", "CALL", "COMMON",
|
||
"CYCLE", "DIMENSION", "END", "ENDDO", "ENTRY", "FORMAT", "IMPLICIT", "INTENT", "MAP",
|
||
"OPEN", "POINTER", "PROGRAM", "RECURSIVE", "STOP", "THEN", "WHILE", "ALLOCATABLE",
|
||
"ATEND", "CASE", "COMPLEX", "DATA", "DO", "ENDFILE", "EQUIVALENCE", "FUNCTION",
|
||
"INCLUDE", "INTERFACE", "MODULE", "OPTIONAL", "PRINT", "PURE", "READ", "RETURN",
|
||
"STRUCTURE", "TYPE", "WRITE", "ALLOCATE", "BACKSPACE", "CHARACTER", "CONTAINS",
|
||
"DEALLOCATE", "DOUBLE", "ENDIF", "EXIT", "GOTO", "INQUIRE", "INTRINSIC", "NAMELIST",
|
||
"PARAMETER", "PRECISION", "REAL", "REWIND", "SUBROUTINE", "UNION", "ASSIGN", "BLOCKDATA",
|
||
"CLOSE", "CONTINUE", "DEFAULT", "ELSE", "ELSEIF", "ENDSELECT", "EXTERNAL", "IF", "INTEGER",
|
||
"LOGICAL", "NONE", "PAUSE", "PROCEDURE", "RECORD", "SAVE", "TARGET", "USE", "SELECT", "BLOCK", "WHERE"
|
||
);
|
||
fillTokenMap(tokenMap, Token.OPERATOR,
|
||
".EQ.",
|
||
".NE.", ".LT.", ".LE.",
|
||
".GT.", ".GE.",
|
||
".NOT.", ".AND.", ".EQV.", ".NEQV.",
|
||
".OR.", ".TRUE.", ".FALSE."
|
||
);
|
||
return tokenMap;
|
||
}
|
||
@Override
|
||
public void addToken(Segment segment, int start, int end, int tokenType, int startOffset) {
|
||
int finalTokenType = tokenType;
|
||
switch (tokenType) {
|
||
case Token.COMMENT_EOL:
|
||
if (segment.count >= 5) {
|
||
switch (segment.subSequence(1, 5).toString().toUpperCase()) {
|
||
case "$SPF":
|
||
finalTokenType = Token.COMMENT_DOCUMENTATION;
|
||
break;
|
||
case "DVM$":
|
||
finalTokenType = Token.COMMENT_MARKUP;
|
||
break;
|
||
case "$OMP":
|
||
finalTokenType = Token.COMMENT_KEYWORD;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
case Token.IDENTIFIER:
|
||
int value = wordsToHighlight.get(segment, start, end);
|
||
//ключевое слово
|
||
if (value != -1) {
|
||
finalTokenType = value;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
super.addToken(segment, start, end, finalTokenType, startOffset);
|
||
}
|
||
@Override
|
||
public void Body(TokenProvider provider) {
|
||
switch (provider.position) {
|
||
//<editor-fold desc="Зона переноса">
|
||
case 0:
|
||
//тут всегда currentTokenType=NULL. переносимый известеи в startTokenType
|
||
provider.start();
|
||
switch (provider.c) {
|
||
case '!':
|
||
case '*':
|
||
case 'C':
|
||
case 'c':
|
||
case 'D':
|
||
case 'd':
|
||
//комментарий. анализ закончен
|
||
provider.setType(Token.COMMENT_EOL);
|
||
provider.stop();
|
||
break;
|
||
case '0':
|
||
case '1':
|
||
case '2':
|
||
case '3':
|
||
case '4':
|
||
case '5':
|
||
case '6':
|
||
case '7':
|
||
case '8':
|
||
case '9':
|
||
//метка.
|
||
provider.setType(Token.MARKUP_TAG_NAME);
|
||
provider.label_flag = true;
|
||
break;
|
||
case ' ':
|
||
case '\r':
|
||
//пробелы
|
||
provider.setType(Token.WHITESPACE);
|
||
break;
|
||
case '\t':
|
||
provider.SkipWrap();
|
||
break;
|
||
default:
|
||
//все остальное
|
||
provider.setType(Token.IDENTIFIER);
|
||
break;
|
||
}
|
||
break;
|
||
case 1:
|
||
case 2:
|
||
case 3:
|
||
case 4:
|
||
switch (provider.currentTokenType) {
|
||
case Token.MARKUP_TAG_NAME:
|
||
switch (provider.c) {
|
||
case '0':
|
||
case '1':
|
||
case '2':
|
||
case '3':
|
||
case '4':
|
||
case '5':
|
||
case '6':
|
||
case '7':
|
||
case '8':
|
||
case '9':
|
||
case '\r':
|
||
break;
|
||
case '!':
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
//комментарий. анализ закончен
|
||
provider.setType(Token.COMMENT_EOL);
|
||
provider.stop();
|
||
break;
|
||
case ' ':
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.setType(Token.WHITESPACE);
|
||
break;
|
||
case '\t':
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.SkipWrap();
|
||
break;
|
||
default:
|
||
//это не метка. меняем тип.
|
||
provider.setType(Token.IDENTIFIER);
|
||
break;
|
||
}
|
||
break;
|
||
case Token.WHITESPACE:
|
||
switch (provider.c) {
|
||
case ' ':
|
||
case '\r':
|
||
break;
|
||
case '\t':
|
||
provider.SkipWrap();
|
||
break;
|
||
case '0':
|
||
case '1':
|
||
case '2':
|
||
case '3':
|
||
case '4':
|
||
case '5':
|
||
case '6':
|
||
case '7':
|
||
case '8':
|
||
case '9':
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
//если метка уже бывала. значит больше меток нет
|
||
if (provider.label_flag) {
|
||
provider.setType(Token.IDENTIFIER);
|
||
} else {
|
||
provider.setType(Token.MARKUP_TAG_NAME);
|
||
provider.label_flag = true;
|
||
}
|
||
break;
|
||
case '!':
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
//комментарий. анализ закончен
|
||
provider.setType(Token.COMMENT_EOL);
|
||
provider.stop();
|
||
break;
|
||
default:
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.setType(Token.IDENTIFIER);
|
||
break;
|
||
}
|
||
break;
|
||
case Token.IDENTIFIER:
|
||
switch (provider.c) {
|
||
case '!':
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
//комментарий. анализ закончен
|
||
provider.setType(Token.COMMENT_EOL);
|
||
provider.stop();
|
||
break;
|
||
case '\t':
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.SkipWrap();
|
||
break;
|
||
default:
|
||
//уже неважно что это.
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
case 5:
|
||
switch (provider.c) {
|
||
case ' ':
|
||
case '\r':
|
||
case '\t':
|
||
switch (provider.currentTokenType) {
|
||
case Token.WHITESPACE:
|
||
//это пробел, и нам норм.
|
||
break;
|
||
default:
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.setType(Token.WHITESPACE);
|
||
break;
|
||
}
|
||
//это пробелы. переноса нет. убираем сохранение типа
|
||
provider.startTokenType = Token.NULL;
|
||
break;
|
||
default:
|
||
//это - позиция переноса. сохраняем все что было до нее.
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.setType(Token.OPERATOR);
|
||
SaveCurrent_(provider); //сохраняем его как одиночный оператор.
|
||
provider.setType(provider.startTokenType);
|
||
//берем унаследование от предыдущей строки
|
||
break;
|
||
}
|
||
break;
|
||
//</editor-fold>
|
||
//<editor-fold desc="Основной текст строки">
|
||
default:
|
||
switch (provider.currentTokenType) {
|
||
case Token.NULL:
|
||
provider.start();
|
||
provider.detectType();
|
||
break;
|
||
case Token.WHITESPACE:
|
||
switch (provider.c) {
|
||
case ' ':
|
||
case '\t':
|
||
case '\r':
|
||
break;
|
||
default:
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.detectType();
|
||
break;
|
||
}
|
||
break;
|
||
case Token.OPERATOR:
|
||
provider.checkWrap();
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.detectType();
|
||
break;
|
||
case Token.LITERAL_NUMBER_DECIMAL_INT:
|
||
provider.checkWrap();
|
||
switch (provider.c) {
|
||
case '0':
|
||
case '1':
|
||
case '2':
|
||
case '3':
|
||
case '4':
|
||
case '5':
|
||
case '6':
|
||
case '7':
|
||
case '8':
|
||
case '9':
|
||
case '\r':
|
||
break;
|
||
case '.':
|
||
case 'e':
|
||
case 'E':
|
||
case 'd':
|
||
case 'D':
|
||
provider.setType(Token.LITERAL_NUMBER_FLOAT);
|
||
break;
|
||
default:
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.detectType();
|
||
break;
|
||
}
|
||
break;
|
||
case Token.LITERAL_NUMBER_FLOAT:
|
||
provider.checkWrap();
|
||
switch (provider.c) {
|
||
case '0':
|
||
case '1':
|
||
case '2':
|
||
case '3':
|
||
case '4':
|
||
case '5':
|
||
case '6':
|
||
case '7':
|
||
case '8':
|
||
case '9':
|
||
case '\r':
|
||
break;
|
||
case 'e':
|
||
case 'E':
|
||
case 'd':
|
||
case 'D':
|
||
SaveCurrent_(provider);
|
||
provider.setType(Token.NULL);
|
||
break;
|
||
default:
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.detectType();
|
||
break;
|
||
}
|
||
break;
|
||
case Token.RESERVED_WORD_2:
|
||
provider.checkWrap();
|
||
switch (provider.c) {
|
||
case '0':
|
||
case '1':
|
||
case '2':
|
||
case '3':
|
||
case '4':
|
||
case '5':
|
||
case '6':
|
||
case '7':
|
||
case '8':
|
||
case '9':
|
||
//подозрения подтвердились. это дробь.
|
||
provider.setType(Token.LITERAL_NUMBER_FLOAT);
|
||
break;
|
||
case '\r':
|
||
break;
|
||
default:
|
||
provider.setType(Token.IDENTIFIER);
|
||
break;
|
||
}
|
||
break;
|
||
case Token.LITERAL_CHAR:
|
||
switch (provider.c) {
|
||
case '\'':
|
||
SaveCurrent_(provider);
|
||
provider.setType(Token.NULL);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case Token.LITERAL_STRING_DOUBLE_QUOTE:
|
||
switch (provider.c) {
|
||
case '"':
|
||
SaveCurrent_(provider);
|
||
provider.setType(Token.NULL);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case Token.IDENTIFIER:
|
||
provider.checkWrap();
|
||
if (!
|
||
(RSyntaxUtilities.isLetter(provider.c) ||
|
||
RSyntaxUtilities.isDigit(provider.c) ||
|
||
(provider.c == '_') ||
|
||
(provider.c == '.')
|
||
)) {
|
||
SaveCurrent(provider);
|
||
provider.start();
|
||
provider.detectType();
|
||
}
|
||
break;
|
||
}
|
||
//</editor-fold>
|
||
}
|
||
}
|
||
@Override
|
||
public void performFinish(TokenProvider provider) {
|
||
switch (provider.currentTokenType) {
|
||
case Token.NULL:
|
||
addNullToken();
|
||
break;
|
||
// case Token.IDENTIFIER:
|
||
case Token.LITERAL_NUMBER_DECIMAL_INT:
|
||
case Token.LITERAL_NUMBER_FLOAT:
|
||
case Token.RESERVED_WORD_2:
|
||
SaveCurrent(provider);
|
||
break;
|
||
default:
|
||
SaveCurrent(provider);
|
||
addNullToken();
|
||
break;
|
||
}
|
||
}
|
||
//_VisualDVM.
|
||
}
|