Gridarta Editor
PythonTokenMarker.java
Go to the documentation of this file.
1 /*
2  * PythonTokenMarker.java - Python token marker
3  * Copyright (C) 1999 Jonathan Revusky
4  * Copyright (C) 1998, 1999 Slava Pestov
5  * Copyright (C) 2000-2015 The Gridarta Developers.
6  *
7  * You may use and modify this package for any purpose. Redistribution is
8  * permitted, in both source and binary form, provided that this notice
9  * remains intact in all source distributions of this package.
10  */
11 
12 package net.sf.gridarta.textedit.textarea.tokenmarker;
13 
14 import javax.swing.text.Segment;
17 
22 public class PythonTokenMarker extends TokenMarker {
23 
24  private static final byte TRIPLE_QUOTE1 = Token.INTERNAL_FIRST;
25 
26  private static final byte TRIPLE_QUOTE2 = Token.INTERNAL_LAST;
27 
28  private static KeywordMap pythonKeywords;
29 
30  private final KeywordMap keywords;
31 
32  private int lastOffset;
33 
34  private int lastKeyword;
35 
36  public PythonTokenMarker() {
37  keywords = getPythonKeywords();
38  }
39 
40  @Override
41  public byte markTokensImpl(final byte token, final Segment line) {
42  final char[] array = line.array;
43  final int offset = line.offset;
44  lastOffset = offset;
45  lastKeyword = offset;
46  final int length = line.count + offset;
47  boolean backslash = false;
48 
49  byte currentToken = token;
50 loop:
51  for (int i = offset; i < length; i++) {
52  final int i1 = i + 1;
53 
54  final char c = array[i];
55  if (c == '\\') {
56  backslash = !backslash;
57  continue;
58  }
59 
60  switch (currentToken) {
61  case Token.NULL:
62  switch (c) {
63  case '#':
64  if (backslash) {
65  backslash = false;
66  } else {
67  doKeyword(line, i);
68  addToken(i - lastOffset, currentToken);
69  addToken(length - i, Token.COMMENT1);
70  lastOffset = length;
71  lastKeyword = length;
72  break loop;
73  }
74  break;
75 
76  case '"':
77  doKeyword(line, i);
78  if (backslash) {
79  backslash = false;
80  } else {
81  addToken(i - lastOffset, currentToken);
82  if (SyntaxUtilities.regionMatches(false, line, i1, "\"\"")) {
83  currentToken = TRIPLE_QUOTE1;
84  } else {
85  currentToken = Token.LITERAL1;
86  }
87  lastOffset = i;
88  lastKeyword = i;
89  }
90  break;
91 
92  case '\'':
93  doKeyword(line, i);
94  if (backslash) {
95  backslash = false;
96  } else {
97  addToken(i - lastOffset, currentToken);
98  if (SyntaxUtilities.regionMatches(false, line, i1, "''")) {
99  currentToken = TRIPLE_QUOTE2;
100  } else {
101  currentToken = Token.LITERAL2;
102  }
103  lastOffset = i;
104  lastKeyword = i;
105  }
106  break;
107 
108  default:
109  backslash = false;
110  if (!Character.isLetterOrDigit(c) && c != '_') {
111  doKeyword(line, i);
112  }
113  break;
114  }
115  break;
116 
117  case Token.LITERAL1:
118  if (backslash) {
119  backslash = false;
120  } else if (c == '"') {
121  addToken(i1 - lastOffset, currentToken);
122  currentToken = Token.NULL;
123  lastOffset = i1;
124  lastKeyword = i1;
125  }
126  break;
127 
128  case Token.LITERAL2:
129  if (backslash) {
130  backslash = false;
131  } else if (c == '\'') {
132  addToken(i1 - lastOffset, Token.LITERAL1);
133  currentToken = Token.NULL;
134  lastOffset = i1;
135  lastKeyword = i1;
136  }
137  break;
138 
139  case TRIPLE_QUOTE1:
140  if (backslash) {
141  backslash = false;
142  } else if (SyntaxUtilities.regionMatches(false, line, i, "\"\"\"")) {
143  i += 4;
144  addToken(i - lastOffset, Token.LITERAL1);
145  currentToken = Token.NULL;
146  lastOffset = i;
147  lastKeyword = i;
148  }
149  break;
150 
151  case TRIPLE_QUOTE2:
152  if (backslash) {
153  backslash = false;
154  } else if (SyntaxUtilities.regionMatches(false, line, i, "'''")) {
155  i += 4;
156  addToken(i - lastOffset, Token.LITERAL1);
157  currentToken = Token.NULL;
158  lastOffset = i;
159  lastKeyword = i;
160  }
161  break;
162 
163  default:
164  throw new InternalError("Invalid state: " + currentToken);
165  }
166  }
167 
168  switch (currentToken) {
169  case TRIPLE_QUOTE1:
170  case TRIPLE_QUOTE2:
171  addToken(length - lastOffset, Token.LITERAL1);
172  break;
173 
174  case Token.NULL:
175  doKeyword(line, length);
176 
177  default:
178  addToken(length - lastOffset, currentToken);
179  break;
180  }
181 
182  return currentToken;
183  }
184 
185  private static KeywordMap getPythonKeywords() {
186  if (pythonKeywords == null) {
187  pythonKeywords = new KeywordMap(false);
188  pythonKeywords.add("and", Token.KEYWORD3);
189  pythonKeywords.add("not", Token.KEYWORD3);
190  pythonKeywords.add("or", Token.KEYWORD3);
191  pythonKeywords.add("if", Token.KEYWORD1);
192  pythonKeywords.add("for", Token.KEYWORD1);
193  pythonKeywords.add("assert", Token.KEYWORD1);
194  pythonKeywords.add("break", Token.KEYWORD1);
195  pythonKeywords.add("continue", Token.KEYWORD1);
196  pythonKeywords.add("elif", Token.KEYWORD1);
197  pythonKeywords.add("else", Token.KEYWORD1);
198  pythonKeywords.add("except", Token.KEYWORD1);
199  pythonKeywords.add("exec", Token.KEYWORD1);
200  pythonKeywords.add("finally", Token.KEYWORD1);
201  pythonKeywords.add("raise", Token.KEYWORD1);
202  pythonKeywords.add("return", Token.KEYWORD1);
203  pythonKeywords.add("try", Token.KEYWORD1);
204  pythonKeywords.add("while", Token.KEYWORD1);
205  pythonKeywords.add("yield", Token.KEYWORD1);
206  pythonKeywords.add("as", Token.KEYWORD2);
207  pythonKeywords.add("def", Token.KEYWORD2);
208  pythonKeywords.add("class", Token.KEYWORD2);
209  pythonKeywords.add("del", Token.KEYWORD2);
210  pythonKeywords.add("from", Token.KEYWORD2);
211  pythonKeywords.add("global", Token.KEYWORD2);
212  pythonKeywords.add("import", Token.KEYWORD2);
213  pythonKeywords.add("in", Token.KEYWORD2);
214  pythonKeywords.add("is", Token.KEYWORD2);
215  pythonKeywords.add("lambda", Token.KEYWORD2);
216  pythonKeywords.add("pass", Token.KEYWORD2);
217  pythonKeywords.add("print", Token.KEYWORD2);
218  pythonKeywords.add("with", Token.KEYWORD2);
219  }
220  return pythonKeywords;
221  }
222 
223  private void doKeyword(final Segment line, final int i) {
224  final int i1 = i + 1;
225 
226  final int len = i - lastKeyword;
227  final byte id = keywords.lookup(line, lastKeyword, len);
228  if (id != Token.NULL) {
229  if (lastKeyword != lastOffset) {
230  addToken(lastKeyword - lastOffset, Token.NULL);
231  }
232  addToken(len, id);
233  lastOffset = i;
234  }
235  lastKeyword = i1;
236  }
237 
238 }
int length
The number of lines in the model being tokenized.
static final byte INTERNAL_FIRST
The first id that can be used for internal state in a token marker.
Definition: Token.java:94
byte lookup(final Segment text, final int offset, final int length)
Looks up a key.
Definition: KeywordMap.java:63
void add(final CharSequence keyword, final byte id)
Adds a key-value mapping.
Definition: KeywordMap.java:79
static final byte COMMENT1
Comment 1 token id.
Definition: Token.java:31
void addToken(final int length, final byte id)
Adds a token to the token list.
static final byte LITERAL1
Literal 1 token id.
Definition: Token.java:42
static final byte KEYWORD3
Keyword 3 token id.
Definition: Token.java:72
Base package of all Gridarta classes.
A linked list of tokens.
Definition: Token.java:21
Class with several utility functions used by jEdit&#39;s syntax colorizing subsystem. ...
This package contains the other part of the script editor.
byte markTokensImpl(final byte token, final Segment line)
static final byte LITERAL2
Literal 2 token id.
Definition: Token.java:48
static boolean regionMatches(final boolean ignoreCase, final Segment text, final int offset, final CharSequence match)
Checks if a sub-region of a.
static final byte NULL
Normal text token id.
Definition: Token.java:26
static final byte KEYWORD2
Keyword 2 token id.
Definition: Token.java:66
A token marker that splits lines of text into tokens.
static final byte INTERNAL_LAST
The last id that can be used for internal state in a token marker.
Definition: Token.java:99
static final byte KEYWORD1
Keyword 1 token id.
Definition: Token.java:60