package _VisualDVM.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) { // 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; // // 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; } // } } @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; } } }