source: other-projects/rsyntax-textarea/src/java/org/fife/ui/rsyntaxtextarea/modes/MakefileTokenMaker.flex@ 25584

Last change on this file since 25584 was 25584, checked in by davidb, 12 years ago

Initial cut an a text edit area for GLI that supports color syntax highlighting

File size: 10.1 KB
Line 
1/*
2 * 09/20/2008
3 *
4 * MakefileTokenMaker.java - Scanner for makefiles.
5 *
6 * This library is distributed under a modified BSD license. See the included
7 * RSyntaxTextArea.License.txt file for details.
8 */
9package org.fife.ui.rsyntaxtextarea.modes;
10
11import java.io.*;
12import java.util.Stack;
13import javax.swing.text.Segment;
14
15import org.fife.ui.rsyntaxtextarea.*;
16
17
18/**
19 * Scanner for makefiles.<p>
20 *
21 * This implementation was created using
22 * <a href="http://www.jflex.de/">JFlex</a> 1.4.1; however, the generated file
23 * was modified for performance. Memory allocation needs to be almost
24 * completely removed to be competitive with the handwritten lexers (subclasses
25 * of <code>AbstractTokenMaker</code>, so this class has been modified so that
26 * Strings are never allocated (via yytext()), and the scanner never has to
27 * worry about refilling its buffer (needlessly copying chars around).
28 * We can achieve this because RText always scans exactly 1 line of tokens at a
29 * time, and hands the scanner this line as an array of characters (a Segment
30 * really). Since tokens contain pointers to char arrays instead of Strings
31 * holding their contents, there is no need for allocating new memory for
32 * Strings.<p>
33 *
34 * The actual algorithm generated for scanning has, of course, not been
35 * modified.<p>
36 *
37 * If you wish to regenerate this file yourself, keep in mind the following:
38 * <ul>
39 * <li>The generated MakefileTokenMaker.java</code> file will contain two
40 * definitions of both <code>zzRefill</code> and <code>yyreset</code>.
41 * You should hand-delete the second of each definition (the ones
42 * generated by the lexer), as these generated methods modify the input
43 * buffer, which we'll never have to do.</li>
44 * <li>You should also change the declaration/definition of zzBuffer to NOT
45 * be initialized. This is a needless memory allocation for us since we
46 * will be pointing the array somewhere else anyway.</li>
47 * <li>You should NOT call <code>yylex()</code> on the generated scanner
48 * directly; rather, you should use <code>getTokenList</code> as you would
49 * with any other <code>TokenMaker</code> instance.</li>
50 * </ul>
51 *
52 * @author Robert Futrell
53 * @version 0.5
54 *
55 */
56%%
57
58%public
59%class MakefileTokenMaker
60%extends AbstractJFlexTokenMaker
61%unicode
62%type org.fife.ui.rsyntaxtextarea.Token
63
64
65%{
66
67 private Stack varDepths;
68
69
70 /**
71 * Constructor. This must be here because JFlex does not generate a
72 * no-parameter constructor.
73 */
74 public MakefileTokenMaker() {
75 }
76
77
78 /**
79 * Adds the token specified to the current linked list of tokens.
80 *
81 * @param tokenType The token's type.
82 */
83 private void addToken(int tokenType) {
84 addToken(zzStartRead, zzMarkedPos-1, tokenType);
85 }
86
87
88 /**
89 * Adds the token specified to the current linked list of tokens.
90 *
91 * @param tokenType The token's type.
92 */
93 private void addToken(int start, int end, int tokenType) {
94 int so = start + offsetShift;
95 addToken(zzBuffer, start,end, tokenType, so);
96 }
97
98
99 /**
100 * Adds the token specified to the current linked list of tokens.
101 *
102 * @param array The character array.
103 * @param start The starting offset in the array.
104 * @param end The ending offset in the array.
105 * @param tokenType The token's type.
106 * @param startOffset The offset in the document at which this token
107 * occurs.
108 */
109 public void addToken(char[] array, int start, int end, int tokenType, int startOffset) {
110 super.addToken(array, start,end, tokenType, startOffset);
111 zzStartRead = zzMarkedPos;
112 }
113
114
115 /**
116 * Returns the text to place at the beginning and end of a
117 * line to "comment" it in a this programming language.
118 *
119 * @return The start and end strings to add to a line to "comment"
120 * it out.
121 */
122 public String[] getLineCommentStartAndEnd() {
123 return new String[] { "#", null };
124 }
125
126
127 /**
128 * Returns whether tokens of the specified type should have "mark
129 * occurrences" enabled for the current programming language.
130 *
131 * @param type The token type.
132 * @return Whether tokens of this type should have "mark occurrences"
133 * enabled.
134 */
135 public boolean getMarkOccurrencesOfTokenType(int type) {
136 return type==Token.IDENTIFIER || type==Token.VARIABLE;
137 }
138
139
140 /**
141 * Returns the first token in the linked list of tokens generated
142 * from <code>text</code>. This method must be implemented by
143 * subclasses so they can correctly implement syntax highlighting.
144 *
145 * @param text The text from which to get tokens.
146 * @param initialTokenType The token type we should start with.
147 * @param startOffset The offset into the document at which
148 * <code>text</code> starts.
149 * @return The first <code>Token</code> in a linked list representing
150 * the syntax highlighted text.
151 */
152 public Token getTokenList(Segment text, int initialTokenType, int startOffset) {
153
154 resetTokenList();
155 this.offsetShift = -text.offset + startOffset;
156
157 s = text;
158 try {
159 yyreset(zzReader);
160 yybegin(Token.NULL);
161 return yylex();
162 } catch (IOException ioe) {
163 ioe.printStackTrace();
164 return new DefaultToken();
165 }
166
167 }
168
169
170 /**
171 * Refills the input buffer.
172 *
173 * @return <code>true</code> if EOF was reached, otherwise
174 * <code>false</code>.
175 * @exception IOException if any I/O-Error occurs.
176 */
177 private boolean zzRefill() throws java.io.IOException {
178 return zzCurrentPos>=s.offset+s.count;
179 }
180
181
182 /**
183 * Resets the scanner to read from a new input stream.
184 * Does not close the old reader.
185 *
186 * All internal variables are reset, the old input stream
187 * <b>cannot</b> be reused (internal buffer is discarded and lost).
188 * Lexical state is set to <tt>YY_INITIAL</tt>.
189 *
190 * @param reader the new input stream
191 */
192 public final void yyreset(java.io.Reader reader) throws java.io.IOException {
193 // 's' has been updated.
194 zzBuffer = s.array;
195 /*
196 * We replaced the line below with the two below it because zzRefill
197 * no longer "refills" the buffer (since the way we do it, it's always
198 * "full" the first time through, since it points to the segment's
199 * array). So, we assign zzEndRead here.
200 */
201 //zzStartRead = zzEndRead = s.offset;
202 zzStartRead = s.offset;
203 zzEndRead = zzStartRead + s.count - 1;
204 zzCurrentPos = zzMarkedPos = zzPushbackPos = s.offset;
205 zzLexicalState = YYINITIAL;
206 zzReader = reader;
207 zzAtBOL = true;
208 zzAtEOF = false;
209 }
210
211
212%}
213
214Letter = [A-Za-z]
215Digit = [0-9]
216IdentifierStart = ({Letter}|[_\.])
217IdentifierPart = ({IdentifierStart}|{Digit})
218Identifier = ({IdentifierStart}{IdentifierPart}*)
219Label = ({Identifier}":")
220
221CurlyVarStart = ("${")
222ParenVarStart = ("$(")
223
224LineTerminator = (\n)
225WhiteSpace = ([ \t\f])
226
227UnclosedCharLiteral = ([\']([^\'\n]|"\\'")*)
228CharLiteral = ({UnclosedCharLiteral}"'")
229UnclosedStringLiteral = ([\"]([^\"\n]|"\\\"")*)
230StringLiteral = ({UnclosedStringLiteral}[\"])
231UnclosedBacktickLiteral = ([\`]([^\`\n]|"\\`")*)
232BacktickLiteral = ({UnclosedBacktickLiteral}"`")
233
234LineCommentBegin = "#"
235
236IntegerLiteral = ({Digit}+)
237
238Operator = ([\:\+\?]?"=")
239
240
241%state VAR
242
243%%
244
245<YYINITIAL> {
246
247 /* Keywords */
248 "addprefix" |
249 "addsuffix" |
250 "basename" |
251 "dir" |
252 "filter" |
253 "filter-out" |
254 "findstring" |
255 "firstword" |
256 "foreach" |
257 "join" |
258 "notdir" |
259 "origin" |
260 "pathsubst" |
261 "shell" |
262 "sort" |
263 "strip" |
264 "suffix" |
265 "wildcard" |
266 "word" |
267 "words" |
268 "ifeq" |
269 "ifneq" |
270 "else" |
271 "endif" |
272 "define" |
273 "endef" |
274 "ifdef" |
275 "ifndef" { addToken(Token.RESERVED_WORD); }
276
277 {LineTerminator} { addNullToken(); return firstToken; }
278
279 {Label} { addToken(Token.PREPROCESSOR); }
280 {Identifier} { addToken(Token.IDENTIFIER); }
281
282 {WhiteSpace}+ { addToken(Token.WHITESPACE); }
283
284 /* String/Character literals. */
285 {CharLiteral} { addToken(Token.LITERAL_CHAR); }
286 {UnclosedCharLiteral} { addToken(Token.ERROR_CHAR); addNullToken(); return firstToken; }
287 {StringLiteral} { addToken(Token.LITERAL_STRING_DOUBLE_QUOTE); }
288 {UnclosedStringLiteral} { addToken(Token.ERROR_STRING_DOUBLE); addNullToken(); return firstToken; }
289 {BacktickLiteral} { addToken(Token.LITERAL_BACKQUOTE); }
290 {BacktickLiteral} { addToken(Token.ERROR_STRING_DOUBLE); addNullToken(); return firstToken; }
291
292 /* Variables. */
293 {CurlyVarStart} { if (varDepths==null) { varDepths = new Stack(); } else { varDepths.clear(); } varDepths.push(Boolean.TRUE); start = zzMarkedPos-2; yybegin(VAR); }
294 {ParenVarStart} { if (varDepths==null) { varDepths = new Stack(); } else { varDepths.clear(); } varDepths.push(Boolean.FALSE); start = zzMarkedPos-2; yybegin(VAR); }
295
296 /* Comment literals. */
297 {LineCommentBegin}.* { addToken(Token.COMMENT_EOL); addNullToken(); return firstToken; }
298
299 /* Operators. */
300 {Operator} { addToken(Token.OPERATOR); }
301
302 /* Numbers */
303 {IntegerLiteral} { addToken(Token.LITERAL_NUMBER_DECIMAL_INT); }
304
305 /* Ended with a line not in a string or comment. */
306 <<EOF>> { addNullToken(); return firstToken; }
307
308 /* Catch-all for anything else. */
309 . { addToken(Token.IDENTIFIER); }
310
311}
312
313<VAR> {
314 [^\}\)\$\#]+ {}
315 "}" {
316 if (!varDepths.empty() && varDepths.peek()==Boolean.TRUE) {
317 varDepths.pop();
318 if (varDepths.empty()) {
319 addToken(start,zzStartRead, Token.VARIABLE); yybegin(YYINITIAL);
320 }
321 }
322 }
323 ")" {
324 if (!varDepths.empty() && varDepths.peek()==Boolean.FALSE) {
325 varDepths.pop();
326 if (varDepths.empty()) {
327 addToken(start,zzStartRead, Token.VARIABLE); yybegin(YYINITIAL);
328 }
329 }
330 }
331 "${" { varDepths.push(Boolean.TRUE); }
332 "$(" { varDepths.push(Boolean.FALSE); }
333 "$" {}
334 "#".* { int temp1 = zzStartRead; int temp2 = zzMarkedPos; addToken(start,zzStartRead-1, Token.VARIABLE); addToken(temp1, temp2-1, Token.COMMENT_EOL); addNullToken(); return firstToken; }
335 <<EOF>> { addToken(start,zzStartRead-1, Token.VARIABLE); addNullToken(); return firstToken; }
336}
Note: See TracBrowser for help on using the repository browser.