2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <Cocoa/Cocoa.h>
26 static int linepos
, lineno
, charno
, yylen
;
27 static int textpos
, textlen
, totallen
;
29 static unichar yytext
[256];
31 //initializing to default SC colors, these will get overriden
32 //by CocoaDocument.sc upon lang compilation, defaults are given
33 //here so when lang compilation fails, we still have some colors
34 //over the text to debug.
35 SCColor synColText
= SCMakeColor(0, 0, 0, 1),
36 synColClass
= SCMakeColor(0, 0, 0.75, 1),
37 synColString
= SCMakeColor(0.375, 0.375, 0.375, 1),
38 synColSymbol
= SCMakeColor(0, 0.45, 0, 1),
39 synColComment
= SCMakeColor(0.75, 0, 0, 1),
40 synColNumber
= SCMakeColor(0.0, 0.0, 0.0, 1),
41 synColSpecialVals
= SCMakeColor(0.2, 0.2, 0.75, 1), // true false nil inf
42 synColSpecialVars
= SCMakeColor(0.4, 0.4, 0.75, 1), // super, thisProcess
43 synColDecl
= SCMakeColor(0, 0, 1, 1), // var, const, args
44 synColPunc
= SCMakeColor(0.0, 0.0, 0.0, 1), // : ; ' [ ] { } ( )
45 synColEnv
= SCMakeColor(1.0, 0.4, 0, 1);
47 static bool streq(const char *cstr
, unichar
*ustr
)
52 if (u
!= c
) return false;
53 else if (u
== 0) return true;
58 static unichar
input()
61 if (textpos
> textlen
) {
67 if (c
== '\n' || c
== '\r') {
72 if (c
!= 0) yytext
[yylen
++] = c
;
73 //if (gDebugLexer) post("input '%c' %d\n",c,c);
77 static unichar
input0()
80 if (textpos
> textlen
) {
82 textpos
++; // so unput will work properly
87 if (c
== '\n' || c
== '\r') {
92 //if (gDebugLexer) post("input0 '%c' %d\n",c,c);
96 static void unput(unichar c
)
98 if (textpos
>0) textpos
--;
101 if (charno
) --charno
;
102 if (c
== '\n' || c
== '\r') {
108 unichar
* startColorizer(NSTextView
* textView
);
109 unichar
* startColorizer(NSTextView
* textView
)
111 totallen
= [[textView textStorage
] length
];
113 NSRange range
= [textView selectedRange
];
114 if (range.length
== 0) range
= NSMakeRange(0, totallen
);
116 if (![textView shouldChangeTextInRange
: range replacementString
: nil]) return 0;
118 textpos
= range.location
;
119 textlen
= textpos
+ range.length
;
121 text
= (unichar
*)malloc((totallen
+1) * sizeof(unichar
));
122 [[[textView textStorage
] string
] getCharacters
: text
];
134 void SyntaxColorize(NSTextView
* textView
)
137 long startrun
= 0, endrun
;
139 int startline
, clevel
, prevc
;
140 NSColor
* textColor
= [NSColor colorWithCalibratedRed
: synColText.red green
: synColText.green blue
: synColText.blue alpha
: synColText.alpha
];
141 NSColor
* commentColor
= [NSColor colorWithCalibratedRed
: synColComment.red green
: synColComment.green blue
: synColComment.blue alpha
: synColComment.alpha
];
142 NSColor
* classColor
= [NSColor colorWithCalibratedRed
: synColClass.red green
: synColClass.green blue
: synColClass.blue alpha
: synColClass.alpha
];
143 NSColor
* symbolColor
= [NSColor colorWithCalibratedRed
: synColSymbol.red green
: synColSymbol.green blue
: synColSymbol.blue alpha
: synColSymbol.alpha
];
144 NSColor
* stringColor
= [NSColor colorWithCalibratedRed
: synColString.red green
: synColString.green blue
: synColString.blue alpha
: synColString.alpha
];
145 NSColor
* numberColor
= [NSColor colorWithCalibratedRed
: synColNumber.red green
: synColNumber.green blue
: synColNumber.blue alpha
: synColNumber.alpha
];
146 NSColor
* specialValsColor
= [NSColor colorWithCalibratedRed
: synColSpecialVals.red green
: synColSpecialVals.green blue
: synColSpecialVals.blue alpha
: synColSpecialVals.alpha
];
147 NSColor
* specialVarsColor
= [NSColor colorWithCalibratedRed
: synColSpecialVars.red green
: synColSpecialVars.green blue
: synColSpecialVars.blue alpha
: synColSpecialVars.alpha
];
148 NSColor
* declColor
= [NSColor colorWithCalibratedRed
: synColDecl.red green
: synColDecl.green blue
: synColDecl.blue alpha
: synColDecl.alpha
];
149 NSColor
* puncColor
= [NSColor colorWithCalibratedRed
: synColPunc.red green
: synColPunc.green blue
: synColPunc.blue alpha
: synColPunc.alpha
];
150 NSColor
* environColor
= [NSColor colorWithCalibratedRed
: synColEnv.red green
: synColEnv.green blue
: synColEnv.blue alpha
: synColEnv.alpha
];
151 NSTextStorage
*textStorage
= [textView textStorage
];
153 if (!startColorizer(textView
)) return;
155 [textStorage beginEditing
];
157 // reset to textColor
158 range
= NSMakeRange(textpos
, textlen
- textpos
);
159 [textStorage addAttribute
:NSForegroundColorAttributeName value
: textColor range
: range
];
161 bool bracket
= false;
166 if (c
== 0 || textpos
> textlen
) goto leave
;
167 else if (c
==' ' || c
=='\t' || c
=='\v' || c
=='\f' || c
=='\n' || c
=='\r') {
171 if (c
== '|' && bracket
) goto arglist
;
172 if (c
== '{') { bracket
= true; }
173 else bracket
= false;
175 if ((c
>= 'A' && c
<= 'Z') ||
(c
>= 'a' && c
<= 'z') || c
== '_') goto ident
;
176 else if (c
== '\\') goto symbol1
;
177 else if (c
== '\'') goto symbol3
;
178 else if (c
== '"') goto string1
;
181 if (c
== '/') goto comment1
;
182 else if (c
== '*') goto comment2
;
193 goto characterLiteral
;
195 else if(c
== '-') goto negnumber
; //might be a negative number
196 else if(c
>= '0' && c
<= '9') goto number
;
197 else if(c
==':' || c
==';' || c
=='.' || c
== ',' || c
=='(' || c
==')' || c
=='[' || c
==']' || c
=='{' || c
=='}') goto punct
;
198 else if(c
=='~') goto environment
;
205 if ((c
>= 'A' && c
<= 'Z') ||
(c
>= 'a' && c
<= 'z')
206 || c
== '_' ||
(c
>= '0' && c
<= '9')) goto ident
;
209 //r = processkeywordbinop(yytext) ;
215 startrun
= textpos
- yylen
;
216 range
= NSMakeRange(startrun
, endrun
- startrun
);
217 if (yytext
[0] == '_') {
218 [textStorage addAttribute
:NSForegroundColorAttributeName value
: classColor range
: range
];
220 else if (yytext
[0] >= 'A' && yytext
[0] <= 'Z') {
221 [textStorage addAttribute
:NSForegroundColorAttributeName value
: classColor range
: range
];
223 else if ( streq("var",yytext
)
224 ||
streq("arg",yytext
)
225 ||
streq("classvar",yytext
)
226 ||
streq("const",yytext
)
228 range
= NSMakeRange(startrun
, endrun
- startrun
);
229 [textStorage addAttribute
:NSForegroundColorAttributeName value
: declColor range
: range
];
231 else if ( streq("this",yytext
)
232 ||
streq("super",yytext
)
233 ||
streq("thisProcess",yytext
)
234 ||
streq("thisThread",yytext
)
235 ||
streq("thisMethod",yytext
)
236 ||
streq("thisFunctionDef",yytext
)
237 ||
streq("thisFunction",yytext
)
239 [textStorage addAttribute
:NSForegroundColorAttributeName value
: specialVarsColor range
: range
];
241 else if ( streq("nil",yytext
)
242 ||
streq("false",yytext
)
243 ||
streq("true",yytext
)
244 ||
streq("inf",yytext
)
246 [textStorage addAttribute
:NSForegroundColorAttributeName value
: specialValsColor range
: range
];
253 if ((c
>= 'A' && c
<= 'Z') ||
(c
>= 'a' && c
<= 'z')
255 startrun
= textpos
- 2;
265 if ((c
>= 'A' && c
<= 'Z') ||
(c
>= 'a' && c
<= 'z')
266 || c
== '_' ||
(c
>= '0' && c
<= '9')) goto symbol2
;
270 range
= NSMakeRange(startrun
, endrun
- startrun
);
271 [textStorage addAttribute
:NSForegroundColorAttributeName value
: symbolColor range
: range
];
277 startrun
= textpos
- 1;
285 } while (!(c
== endchar
&& prevc
!= '\\') && c
!= 0);
286 if (c
== 0 || textpos
> textlen
) {
287 //postbuf("Open ended symbol ... started on line %d in file '%s'\n",
288 // startline, curfilename);
292 range
= NSMakeRange(startrun
, endrun
- startrun
);
293 [textStorage addAttribute
:NSForegroundColorAttributeName value
: symbolColor range
: range
];
302 startrun
= textpos
- 1;
310 if(prevc
== '\\' && c
== '\\') {
313 if(c
== endchar
) break;
315 } while (!(c
== endchar
&& prevc
!= '\\') && c
!= 0);
316 if (c
== 0 || textpos
> textlen
) {
317 //postbuf("Open ended string ... started on line %d in file '%s'\n",
318 // startline, curfilename);
322 range
= NSMakeRange(startrun
, endrun
- startrun
);
323 [textStorage addAttribute
:NSForegroundColorAttributeName value
: stringColor range
: range
];
328 startrun
= textpos
-1;
331 } while (c
!= '|' && c
!= 0);
334 range
= NSMakeRange(startrun
, endrun
- startrun
);
335 [textStorage addAttribute
:NSForegroundColorAttributeName value
: declColor range
: range
];
338 comment1
: /* comment -- to end of line */
339 startrun
= textpos
-2;
342 } while (c
!= '\n' && c
!= '\r' && c
!= 0);
344 range
= NSMakeRange(startrun
, endrun
- startrun
- 1);
345 [textStorage addAttribute
:NSForegroundColorAttributeName value
: commentColor range
: range
];
349 startrun
= textpos
-2;
355 if (c
== '/' && prevc
== '*') {
356 if (--clevel
<= 0) break;
357 } else if (c
== '*' && prevc
== '/') clevel
++;
360 if (textpos
> textlen
) {
364 range
= NSMakeRange(startrun
, endrun
- startrun
);
365 [textStorage addAttribute
:NSForegroundColorAttributeName value
: commentColor range
: range
];
369 startrun
= textpos
-1;
372 if(c
== '.') { c
= input0(); if(c
< '0' || c
> '9') { unput(c
); break; }; };
373 } while ((c
>= '0' && c
<= '9') || c
== '.' || c
== ' ');
374 endrun
= textpos
- 1;
375 range
= NSMakeRange(startrun
, endrun
- startrun
);
376 [textStorage addAttribute
:NSForegroundColorAttributeName value
: numberColor range
: range
];
380 startrun
= textpos
-1;
383 } while ((c
>= 'A' && c
<= 'Z') ||
(c
>= 'a' && c
<= 'z') || c
== '_' ||
(c
>= '0' && c
<= '9'));
384 endrun
= textpos
- 1;
385 range
= NSMakeRange(startrun
, endrun
- startrun
);
386 [textStorage addAttribute
:NSForegroundColorAttributeName value
: environColor range
: range
];
391 startrun
= textpos
-3;
393 startrun
= textpos
-2;
396 range
= NSMakeRange(startrun
, endrun
- startrun
);
397 [textStorage addAttribute
:NSForegroundColorAttributeName value
: numberColor range
: range
];
400 startrun
= textpos
-1;
402 range
= NSMakeRange(startrun
, endrun
- startrun
);
403 [textStorage addAttribute
:NSForegroundColorAttributeName value
: puncColor range
: range
];
406 bool numFound
= false; //no digit found yet, after minus sign
407 bool reachedStart
= false;
408 int tempTextpos
= textpos
, tempCharno
= charno
, tempYylen
= yylen
, tempLineno
= lineno
;
409 do { //go backwards until you find stg. other than whitespace and numbers
412 if(textpos
<= 1) { //beginning of doc. escape!
416 } while (c
== ' ' || c
== '\n' || c
== '\t' || c
== '\v' || c
== '\f' || c
== '\r' || c
== 0 ||
(c
>= '0' && c
<= '9'));
417 textpos
= tempTextpos
; charno
= tempCharno
; yylen
= tempYylen
; lineno
= tempLineno
; //restore original position
418 if(reachedStart
) continue;
419 if((c
>= 'A' && c
<= 'Z') ||
(c
>= 'a' && c
<= 'z') || c
== '_' || c
== ')' || c
== ']') continue; //it must be a subtraction operator, skip.
420 startrun
= textpos
- 1;
423 } while(c
== ' ' || c
== '\n' || c
== '\t' || c
== '\v' || c
== '\f' || c
== '\r');
424 if(c
>= '0' && c
<= '9') {
431 range
= NSMakeRange(startrun
, endrun
- startrun
);
432 [textStorage addAttribute
:NSForegroundColorAttributeName value
: numberColor range
: range
];
441 [textStorage endEditing
];