Initial commit of newLISP.
[newlisp.git] / guiserver / java / SyntaxHighlighter.java
blob3219f57d1e59c605a8c927c65020fd3b05083a58
1 //
2 // SyntaxHighlighter.java
3 // guiserver
4 //
5 // Created by Lutz Mueller on 7/19/07.
6 //
7 // Copyright (C) 2007 Lutz Mueller
8 //
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 import java.awt.*;
24 import java.util.*;
25 import java.util.regex.Pattern;
26 import javax.swing.*;
27 import javax.swing.text.*;
29 @SuppressWarnings("unchecked")
30 public class SyntaxHighlighter {
32 static String reserved[] = {
33 "!","!=","$","$0","$1","$10","$11","$12","$13","$14","$15","$2","$3","$4","$5","$6","$7","$8","$9",
34 "$args","$idx","$main-args","%","&","*","+","-","/","<","<<","<=","=",">",">=",">>","?","@","MAIN",
35 "NaN?","^","abs","acos","acosh","add","address","amb","and","append","append-file","apply","args",
36 "array","array-list","array?","asin","asinh","assoc","assoc-set","atan","atan2","atanh","atom?","base64-dec",
37 "base64-enc","bayes-query","bayes-train","begin","beta","betai","bind","binomial","callback","case",
38 "catch","ceil","change-dir","char","chop","clean","close","command-line","cond","cons","constant",
39 "context","context?","copy-file","cos","cosh","count","cpymem","crc32","crit-chi2","crit-z","current-line",
40 "curry","date","date-value","debug","dec","def-new","default","define","define-macro","delete","delete-file",
41 "delete-url","destroy","det","device","difference","directory","directory?","div","do-until","do-while","doargs",
42 "dolist","dostring","dotimes","dotree","dump","dup","empty?","encrypt","ends-with","env","erf","error-event",
43 "error-number","error-text","eval","eval-string","exec","exists","exit","exp","expand","explode","factor",
44 "fft","file-info","file?","filter","find","find-all","first","flat","float","float?","floor","flt","for",
45 "for-all","fork","format","fv","gammai","gammaln","gcd","get-char","get-float","get-int","get-long",
46 "get-string","get-url","global","global?","if","ifft","import","inc","index","int","integer","integer?",
47 "intersect","invert","irr","join","lambda?","last","legal?","length","let","letex","letn","list","list?",
48 "load","local","log","lookup","lower-case","macro?","main-args","make-dir","map","mat","match","max",
49 "member","min","mod","mul","multiply","name","net-accept","net-close","net-connect","net-error","net-eval",
50 "net-listen","net-local","net-lookup","net-peek","net-peer","net-ping","net-receive","net-receive-from",
51 "net-receive-udp","net-select","net-send","net-send-to","net-send-udp","net-service","net-sessions","new",
52 "nil","nil?","normal","not","now","nper","npv","nth","nth-set","null?","number?","open","or","ostype",
53 "pack","parse","parse-date","peek","pipe","pmt","pop","pop-assoc", "post-url","pow","pretty-print","primitive?","print",
54 "println","prob-chi2","prob-z","process","protected?","push","put-url","pv","quote","quote?","rand",
55 "random","randomize","read-buffer","read-char","read-file","read-key","read-line","real-path","ref","ref-set",
56 "ref-all","regex","remove-dir","rename-file","replace","replace-assoc","reset","rest","reverse","rotate",
57 "round","save","search","seed","seek","select","semaphore","sequence","series","set","set-assoc","set-locale","set-nth",
58 "set-ref","set-ref-all","setq","sgn","share","signal","silent","sin","sinh","sleep","slice","sort","source","sqrt","starts-with",
59 "string","string?","sub","swap","sym","symbol?","symbols","sys-error","sys-info","tan","tanh","throw",
60 "throw-error","time","time-of-day","timer","title-case","trace","trace-highlight","transpose","trim",
61 "true","true?","unicode","unify","unique","unless","unpack","until","upper-case","utf8","utf8len","uuid",
62 "wait-pid","when","while","write-buffer","write-char","write-file","write-line","xml-error","xml-parse",
63 "xml-type-tags","zero?","|","~" };
65 static SimpleAttributeSet comment;
66 static SimpleAttributeSet keyword;
67 static SimpleAttributeSet string;
68 static SimpleAttributeSet number;
69 static SimpleAttributeSet paren;
70 static SimpleAttributeSet quoted;
71 static SimpleAttributeSet normal;
73 static Color normalColor = Color.black;
74 static Color commentColor = Color.gray;
75 static Color keywordColor = new Color(0, 0, 192);
76 static Color stringColor = new Color(0, 128, 0);
77 static Color numberColor = new Color(192,128, 0);
78 static Color parenColor = new Color(192, 0, 0);
79 static Color quotedColor = new Color(96, 96, 192);
81 static String numberPattern = "^-?\\d+$|^-?\\d+\\.\\d+$|^0x[0-9a-fA-F]+$";
82 static Pattern compiledPattern;
84 static StyledDocument doc;
85 static String text;
86 static String token;
87 static Vector topLevels;
89 static HashSet keys = null;
90 static boolean active = false;
92 @SuppressWarnings("unchecked")
93 static public void color(TextPaneWidget widget, int offset, int length)
95 int parenCount = 0;
96 int curlCount = 0;
97 int startToken;
98 int idx = offset;
99 char chr;
101 active = true;
104 doc = widget.styledDoc;
105 topLevels = widget.shTopLevels;
107 normal = new SimpleAttributeSet();
108 StyleConstants.setForeground(normal, widget.foreground);
110 try { text = doc.getText(0, widget.documentLength); }
111 catch (Exception e) {text = null;}
113 if(keys == null) init();
115 while(idx < length)
117 chr = text.charAt(idx++);
118 while(chr <= ' ' && idx < length) chr = text.charAt(idx++);
119 switch(chr)
121 case ';':
122 case '#':
123 startToken = idx - 1;
124 while(chr != '\n' && idx < length) chr = text.charAt(idx++);
125 doc.setCharacterAttributes(startToken, idx - startToken, comment, false);
126 continue;
127 case '(':
128 ++parenCount;
129 doc.setCharacterAttributes(idx - 1, 1, paren, false);
130 continue;
131 case ')':
132 --parenCount;
133 doc.setCharacterAttributes(idx - 1, 1, paren, false);
134 if(parenCount == 0) // top level
136 topLevels.addElement(offset);
137 offset = idx;
139 continue;
140 case '\'':
141 startToken = idx - 1;
142 while(chr > ' ' && chr != '(' && chr != ')' && idx < length) chr = text.charAt(idx++);
143 if(chr == ' ' || chr == '(' || chr == ')')
145 doc.setCharacterAttributes(startToken, idx - startToken - 1, quoted, false);
146 idx--;
147 continue;
149 else
150 doc.setCharacterAttributes(startToken, idx - startToken, quoted, false);
152 continue;
153 case '"':
154 startToken = idx - 1;
155 //while(idx < length && text.charAt(idx++) != '"' );
156 //doc.setCharacterAttributes(startToken, idx - startToken, string, false);
157 //continue;
158 while(idx < length)
160 chr = text.charAt(idx++);
161 if(chr == '"')
163 doc.setCharacterAttributes(startToken, idx - startToken, string, false);
164 break;
166 if(chr == '\\')
168 idx++;
169 continue;
172 continue;
173 case '{':
174 startToken = idx - 1;
175 curlCount = 1;
176 while(curlCount != 0 && idx < length)
178 chr = text.charAt(idx++);
179 if(chr == '}') curlCount--;
180 else if(chr == '{') curlCount++;
182 doc.setCharacterAttributes(startToken, idx - startToken, string, false);
183 continue;
184 case '[':
185 startToken = idx - 1;
186 if(text.startsWith("[text]", startToken))
188 idx = text.indexOf("[/text]", startToken + 6);
189 if(idx < 0) idx = length;
190 else idx = idx + 7;
191 doc.setCharacterAttributes(startToken, idx - startToken, string, false);
192 continue;
194 continue;
195 default:
196 startToken = idx - 1;
197 while(chr > ' ' && chr != '(' && chr != ')' && chr != '\'' && idx < length) chr = text.charAt(idx++);
198 token = text.substring(startToken, idx - 1);
200 if(keys.contains(token))
201 doc.setCharacterAttributes(startToken, idx - startToken, keyword, false);
202 else
204 //if(token.matches(numberPattern))
205 if(compiledPattern.matcher(token).matches())
206 doc.setCharacterAttributes(startToken, idx - startToken, number, false);
207 else
208 doc.setCharacterAttributes(startToken, idx - startToken, normal, false);
211 if(chr == '(')
213 ++parenCount;
214 doc.setCharacterAttributes(idx - 1, 1, paren, false);
215 continue;
217 else if(chr == ')')
219 --parenCount;
220 doc.setCharacterAttributes(idx - 1, 1, paren, false);
221 if(parenCount == 0) // top level
223 topLevels.addElement(offset);
224 offset = idx;
226 continue;
228 else if(chr == '\'')
230 doc.setCharacterAttributes(idx - 1, 1, paren, false);
231 continue;
236 active = false;
239 static void init()
241 if(keys == null)
243 keys = new HashSet();
244 for(int idx = 0; idx < reserved.length; idx++)
245 keys.add(reserved[idx]);
248 compiledPattern = Pattern.compile(numberPattern);
250 comment = new SimpleAttributeSet();
251 StyleConstants.setForeground(comment, commentColor);
253 keyword = new SimpleAttributeSet();
254 StyleConstants.setForeground(keyword, keywordColor);
256 string = new SimpleAttributeSet();
257 StyleConstants.setForeground(string, stringColor);
259 number = new SimpleAttributeSet();
260 StyleConstants.setForeground(number, numberColor);
262 quoted = new SimpleAttributeSet();
263 StyleConstants.setForeground(quoted, quotedColor);
265 paren = new SimpleAttributeSet();
266 StyleConstants.setForeground(paren, parenColor);
269 public static void setSyntaxColors(StringTokenizer tokens)
271 commentColor = new Color(Float.parseFloat(tokens.nextToken()),
272 Float.parseFloat(tokens.nextToken()), Float.parseFloat(tokens.nextToken()));
274 keywordColor = new Color(Float.parseFloat(tokens.nextToken()),
275 Float.parseFloat(tokens.nextToken()), Float.parseFloat(tokens.nextToken()));
277 stringColor = new Color(Float.parseFloat(tokens.nextToken()),
278 Float.parseFloat(tokens.nextToken()), Float.parseFloat(tokens.nextToken()));
280 numberColor = new Color(Float.parseFloat(tokens.nextToken()),
281 Float.parseFloat(tokens.nextToken()), Float.parseFloat(tokens.nextToken()));
283 quotedColor = new Color(Float.parseFloat(tokens.nextToken()),
284 Float.parseFloat(tokens.nextToken()), Float.parseFloat(tokens.nextToken()));
286 parenColor = new Color(Float.parseFloat(tokens.nextToken()),
287 Float.parseFloat(tokens.nextToken()), Float.parseFloat(tokens.nextToken()));
289 init();
290 SyntaxHighlighterC.init();
294 // eof