fortrantokenmarker.java
来自「java写的多功能文件编辑器」· Java 代码 · 共 370 行
JAVA
370 行
/* * FortranTokenMarker.java - Fortran token marker * by Carl Smotricz * carl@smotricz.com * www.smotricz.com * * 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 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 org.gjt.sp.jedit.syntax;import javax.swing.text.Segment;/** * Custom TokenMarker for UNISYS's <cite>ASCII FORTRAN 77</cite>. * Characteristics of this dialect are:<ul> * <li>Fixed column format, with<ul> * <li>comment character ( 'C'|'c'|'*' ) in column 1,</li> * <li>labels (numeric) in column 1-5,</li> * <li>continuation character ( any nonblank ) in column 6,</li> * <li>logical end of line after column 72.</li> * </ul></li> * <li>Nonstandard block comment character ( '@' ) in any column,</li> * <li>Some nonstandard functions: <code>BITS</code>, <code>BOOL</code>, * <code>INDEX</code>, <code>TRMLEN</code></li> * </ul> * It should be easy enough to adapt this class for minor variations * in the dialect so long as the format is the classic fixed column format. * As this scanner is highly optimized for the fixed column format, it * is probably not readily adaptable for freeform FORTRAN code. */ public class FortranTokenMarker extends TokenMarker{ // private members private final static int MAYBE_KEYWORD_FIRST = Token.INTERNAL_FIRST; private final static int MAYBE_KEYWORD_MORE = 1 + MAYBE_KEYWORD_FIRST; private final static String S_E_P = "START EDIT PAGE"; private static KeywordMap fortranKeywords; private KeywordMap keywords; private int lastOffset; /** * Constructor, with a wee bit of initialization. */ public FortranTokenMarker() { this.keywords = getKeywords(); } /** * Implementation of code to mark tokens. */ public byte markTokensImpl(byte token, Segment line, int lineIndex) { byte lastLineToken = token; // --- Very quick check for empty line if (line.count < 1) return lastLineToken; // EXIT METHOD! char[] array = line.array; int offset = line.offset; char c = array[offset]; // --- Very quick check for 'C' comment line if (c == 'C' || c == 'c' || c == '*') { addToken(line.count, Token.COMMENT1); return lastLineToken; // EXIT METHOD! } token = Token.NULL; // context usually ends on line boundary int lineEnd = offset + line.count; // --- Check for a label int limit = Math.min(lineEnd, offset + 5); int i; for (i=offset; i<limit; i++) { c = array[i]; if (c == '@') { // comment to end of line guardedAddToken(i - offset, token); addToken(lineEnd - i, Token.COMMENT2); return lastLineToken; // EXIT METHOD! } else if (token == Token.NULL && '0' <= c && c <= '9') { // numerics: Label. token = Token.LABEL; } } addToken(limit - offset, token); // --- End of line? if (limit == lineEnd) return Token.NULL; // EXIT METHOD! // --- Check for line continuation c = array[i]; if (c == '@') { // comment to end of line addToken(lineEnd - i, Token.COMMENT2); return Token.NULL; // EXIT METHOD! } else if (c == ' ') { // just a plain old blank addToken(1, Token.NULL); token = Token.NULL; } else { // line continuation: mark it as a label to make it stand out addToken(1, Token.LABEL); token = lastLineToken; } // --- End of line? if (lineEnd == offset + 6) return Token.NULL; // EXIT METHOD! limit = Math.min(offset + 72, lineEnd); lastOffset = offset + 6; // --- Check for "START EDIT PAGE" if (checkStartEditPage(line)) { addToken(limit - lastOffset, Token.LABEL); return Token.NULL; // EXIT METHOD! } // --- 'normal' real, honest coding now int i1; for(i = lastOffset; i < limit; i++) { i1 = i + 1; c = array[i]; if (token == Token.LITERAL1) { // ignore anything but the end of literal if (c == '\'') { addToken(i1 - lastOffset, Token.LITERAL1); token = Token.NULL; lastOffset = i1; } } else if (c == '@') { // comment to end of line guardedAddToken(i - lastOffset, token); addToken(lineEnd - i, Token.COMMENT2); return token; // EXIT METHOD! } else if (token == Token.NULL) { switch (c) { case '\'': guardedAddToken(i - lastOffset, token); token = Token.LITERAL1; lastOffset = i; break; case '+': case '-': case '*': case '/': case '(': case ')': case ',': case ':': case '=': guardedAddToken(i - lastOffset, token); addToken(1, Token.OPERATOR); lastOffset = i1; break; default: if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) { guardedAddToken(i - lastOffset, token); token = MAYBE_KEYWORD_FIRST; lastOffset = i; break; } else { // unknown special char - maintain state } } } else if (token == MAYBE_KEYWORD_FIRST || token == MAYBE_KEYWORD_MORE) { if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '$')) { token = MAYBE_KEYWORD_MORE; } else { doKeyword(line, i); c = array[i]; switch (c) { case '+': case '-': case '*': case '/': case '(': case ')': case ',': case ':': case '=': guardedAddToken(i - lastOffset, token); addToken(1, Token.OPERATOR); lastOffset = i1; break; } token = Token.NULL; } } else { throw new InternalError("Invalid state: " + token); } } // end for // --- Finish up the coding part of the line if (token == MAYBE_KEYWORD_FIRST || token == MAYBE_KEYWORD_MORE) { doKeyword(line, i); token = Token.NULL; } else { guardedAddToken(i - lastOffset, token); } // --- End of line? if (limit == lineEnd) return token; // EXIT METHOD! // --- Anything beyond column 72 is comment guardedAddToken(lineEnd - i, Token.COMMENT2); // return token; } private boolean checkStartEditPage(Segment line) { if (line.count < 6+15) return false; int limit = line.offset + Math.min(line.count, 72); int i; for (i=line.offset+6; i<limit-15; i++) if (line.array[i] != ' ') break; if (!SyntaxUtilities.regionMatches(false, line, i, S_E_P)) return false; for (i+=15; i<limit; i++) if (line.array[i] != ' ') return false; return true; } /** * Add the latest token to the current list. * Process 'START' as a special case. */ private void doKeyword(Segment line, int keywordEnd) { int len = keywordEnd - lastOffset; if (len > 0) { byte id = keywords.lookup(line, lastOffset, len); addToken(len, id); lastOffset = keywordEnd; } } /** * Call addToken only if the length of the token is not 0. */ private void guardedAddToken(int len, byte token) { if (len > 0) addToken(len, token); } /** * Return the keyword map. * It's lazily initialized on the first call. */ public static KeywordMap getKeywords() { if (fortranKeywords == null) { fortranKeywords = new KeywordMap(false); // === Commands === fortranKeywords.add("CALL", Token.KEYWORD1); fortranKeywords.add("CLOSE", Token.KEYWORD1); fortranKeywords.add("CONTINUE", Token.KEYWORD1); fortranKeywords.add("DO", Token.KEYWORD1); fortranKeywords.add("ELSE", Token.KEYWORD1); fortranKeywords.add("ELSEIF", Token.KEYWORD1); fortranKeywords.add("ENDIF", Token.KEYWORD1); fortranKeywords.add("GOTO", Token.KEYWORD1); fortranKeywords.add("GO TO", Token.KEYWORD1); fortranKeywords.add("IF", Token.KEYWORD1); fortranKeywords.add("INDEX", Token.KEYWORD1); fortranKeywords.add("INQUIRE", Token.KEYWORD1); fortranKeywords.add("OPEN", Token.KEYWORD1); fortranKeywords.add("PRINT", Token.KEYWORD1); fortranKeywords.add("READ", Token.KEYWORD1); fortranKeywords.add("RETURN", Token.KEYWORD1); fortranKeywords.add("THEN", Token.KEYWORD1); fortranKeywords.add("WRITE", Token.KEYWORD1); // === Compiler directives === fortranKeywords.add("BLOCK DATA", Token.KEYWORD2); fortranKeywords.add("COMPILER", Token.KEYWORD2); fortranKeywords.add("END", Token.KEYWORD2); fortranKeywords.add("ENTRY", Token.KEYWORD2); fortranKeywords.add("FUNCTION", Token.KEYWORD2); fortranKeywords.add("INCLUDE", Token.KEYWORD2); fortranKeywords.add("SUBROUTINE", Token.KEYWORD2); // === Data types (etc.) === fortranKeywords.add("CHARACTER", Token.KEYWORD3); fortranKeywords.add("DATA", Token.KEYWORD3); fortranKeywords.add("DEFINE", Token.KEYWORD3); fortranKeywords.add("EQUIVALENCE", Token.KEYWORD3); fortranKeywords.add("IMPLICIT", Token.KEYWORD3); fortranKeywords.add("INTEGER", Token.KEYWORD3); fortranKeywords.add("LOGICAL", Token.KEYWORD3); fortranKeywords.add("PARAMETER", Token.KEYWORD3); fortranKeywords.add("REAL", Token.KEYWORD3); // === Operators === fortranKeywords.add(".AND.", Token.OPERATOR); fortranKeywords.add(".EQ.", Token.OPERATOR); fortranKeywords.add(".NE.", Token.OPERATOR); fortranKeywords.add(".NOT.", Token.OPERATOR); fortranKeywords.add(".OR.", Token.OPERATOR); fortranKeywords.add("+", Token.OPERATOR); fortranKeywords.add("-", Token.OPERATOR); fortranKeywords.add("*", Token.OPERATOR); fortranKeywords.add("**", Token.OPERATOR); fortranKeywords.add("/", Token.OPERATOR); // === Literals === fortranKeywords.add(".FALSE.", Token.LITERAL2); fortranKeywords.add(".TRUE.", Token.LITERAL2); } return fortranKeywords; }}// End of FortranTokenMarker.java
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?