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