2
/******************************************************************************
3
* MODULE : mathemagix_language.cpp
4
* DESCRIPTION: the "mathemagix" language
5
* COPYRIGHT : (C) 2008 Francis Jamet
6
*******************************************************************************
7
* This software falls under the GNU general public license version 3 or later.
8
* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9
* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10
******************************************************************************/
12
#include "analyze.hpp"
13
#include "impl_language.hpp"
14
#include "Scheme/object.hpp"
16
static void parse_number (string s, int& pos);
17
static void parse_string (string s, int& pos);
18
static void parse_alpha (string s, int& pos);
20
mathemagix_language_rep::mathemagix_language_rep (string name):
21
language_rep (name), colored ("")
23
eval ("(use-modules (utils misc tm-keywords))");
24
list<string> l= as_list_string (eval ("(map symbol->string highlight-any)"));
26
colored (l->item)= "blue";
32
mathemagix_language_rep::advance (string s, int& pos) {
33
if (pos==N(s)) return &tp_normal_rep;
36
pos++; return &tp_space_rep; }
37
if (c >= '0' && c <= '9') {
38
parse_number (s, pos); return &tp_normal_rep; }
39
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
40
(c == '_') || (c == '$')) {
41
parse_alpha (s, pos); return &tp_normal_rep; }
42
tm_char_forwards (s, pos);
43
return &tp_normal_rep;
47
mathemagix_language_rep::get_hyphens (string s) {
49
array<int> penalty (N(s)+1);
50
penalty[0]= HYPH_INVALID;
51
for (i=1; i<N(s); i++)
52
if (s[i-1] == '-' && is_alpha (s[i]))
54
else penalty[i]= HYPH_INVALID;
55
penalty[i]= HYPH_INVALID;
60
mathemagix_language_rep::hyphenate (
61
string s, int after, string& left, string& right)
64
right= s(after, N(s));
68
mathemagix_color_setup_constants (hashmap<string, string> & t) {
72
t ("cpp_preamble")= c;
82
mathemagix_color_setup_keywords (hashmap<string, string> & t) {
83
string c= "#8020c0"; string d= "modifier"; string e= "class";
131
t ("interactive")= c;
137
t ("literal_integer")= c;
138
t ("literal_floating")= c;
139
t ("literal_string")= c;
152
t ("postfix")= "postfix";
181
mathemagix_color_setup_otherlexeme (hashmap<string, string>& t) {
200
t ("<less><less>")= c;
201
t ("<less><less>*")= c;
202
t ("<less><less>%")= c;
207
belongs_to_identifier (char c) {
208
return ((c<='9' && c>='0') ||
209
(c<='Z' && c>='A') ||
210
(c<='z' && c>='a') ||
211
c=='_' || c=='$' || c=='?');
216
return (c>='0' && c<='9');
220
parse_identifier (hashmap<string, string>& t,
221
string s, int& pos, bool postfix) {
223
if (pos>=N(s)) return;
224
if (is_number (s[i])) return;
225
if (postfix && s[i]=='.') i++;
226
while (i<N(s) && belongs_to_identifier (s[i])) i++;
227
if (!(t->contains (s (pos, i)))) pos= i;
231
parse_alpha (string s, int& pos) {
232
static hashmap<string,string> empty;
233
parse_identifier (empty, s, pos, false);
237
parse_blanks (string s, int& pos) {
238
while (pos<N(s) && (s[pos]==' ' || s[pos]=='\t')) pos++;
242
parse_string (string s, int& pos) {
243
if (pos>=N(s)) return;
248
((s[pos-1]=='\\' && s[pos]=='\042') || s[pos]!='\042'));
249
if (s[pos]=='\042') pos++;
252
if (pos+1<N(s) && s[pos+1]=='\042') {
255
if (pos+1<N(s) && s[pos]=='\042' && s[pos+1]=='/') {
264
parse_keyword (hashmap<string,string>& t, string s, int& pos) {
266
if (pos>=N(s)) return;
267
if (is_number (s[i])) return;
268
while ((i<N(s)) && belongs_to_identifier (s[i])) i++;
269
string r= s (pos, i);
270
if (t->contains (r) && t(r)=="#8020c0") { pos=i; return; }
274
parse_modifier (hashmap<string,string>& t, string s, int& pos) {
276
if (pos>=N(s)) return;
277
if (is_number (s[i])) return;
278
while ((i<N(s)) && belongs_to_identifier (s[i])) i++;
279
string r= s (pos, i);
280
if (t->contains (r) && t(r)=="modifier") { pos=i; return; }
284
parse_class (hashmap<string,string>& t, string s, int& pos) {
286
if (pos>=N(s)) return;
287
if (is_number (s[i])) return;
288
while ((i<N(s)) && belongs_to_identifier (s[i])) i++;
289
string r= s (pos, i);
290
if (t->contains (r) && t(r)=="class") { pos=i; return; }
295
parse_postfix (hashmap<string,string>& t, string s, int& pos) {
297
if (pos>=N(s)) return;
298
if (is_number (s[i])) return;
299
while ((i<N(s)) && belongs_to_identifier (s[i])) i++;
300
string r= s (pos, i);
301
if (t->contains (r) && t(r)=="postfix") { pos=i; return; }
305
parse_constant (hashmap<string,string>& t, string s, int& pos) {
307
if (pos>=N(s)) return;
308
if (is_number (s[i])) return;
309
while ((i<N(s)) && belongs_to_identifier (s[i])) i++;
310
string r= s (pos, i);
311
if (t->contains (r) && t(r)=="#2060c0") { pos=i; return; }
315
parse_other_lexeme (hashmap<string,string>& t, string s, int& pos) {
317
for (i=12; i>=1; i--) {
318
string r=s(pos,pos+i);
319
if (t->contains(r) && t(r)=="black") {
325
parse_number (string s, int& pos) {
327
if (pos>=N(s)) return;
328
if (s[i] == '.') return;
331
(s[i] == '.' && (i+1<N(s)) &&
332
(is_number (s[i+1]) ||
333
s[i+1] == 'e' || s[i+1] == 'E')))) i++;
334
if (i == pos) return;
335
if (i<N(s) && (s[i] == 'e' || s[i] == 'E')) {
337
if (i<N(s) && s[i] == '-') i++;
338
while (i<N(s) && (is_number (s[i]))) i++;
344
parse_no_declare_type (string s, int& pos) {
345
if (pos+1<N(s) && s[pos]==':' && s[pos+1]==':') pos=pos+2;
349
parse_declare_type (string s, int& pos) {
350
if (pos>=N(s)) return;
351
if (s[pos]!=':') return;
352
if (pos+1<N(s) && s[pos+1]=='=') return;
354
if (!test (s, pos, "<gtr>")) return;
359
parse_comment (string s, int& pos) {
360
if (pos>=N(s)) return;
361
if (s[pos]!='/') return;
362
if (pos+1<N(s) && s[pos+1]=='/') {pos=N(s);return;}
363
if (pos+1<N(s) && s[pos+1]=='{') {
365
while ((pos<N(s) && s[pos]!='}') || (pos+1<N(s) && s[pos+1]!='/')) pos++;
366
pos= min(pos+2,N(s));
371
parse_end_comment (string s, int& pos) {
372
if (pos+1<N(s) && s[pos]=='}' && s[pos+1]=='/') pos=pos+2;
377
parse_parenthesized (string s, int& pos) {
379
if (pos>=N(s)) return;
380
if (s[i]!='(') return;
386
case ')':if (nbpar>0) nbpar--;
387
if (nbpar==0) {i++;pos=i;return;}
391
(s[i+1]=='\042' || s[i+1]=='{' || s[i+1]=='/')) {
404
parse_backquote (string s, int & pos) {
405
if (pos>=N(s)) return;
406
if (s[pos]=='\047') pos++;
410
parse_declare_function (string s, int& pos) {
411
if (pos+1>=N(s)) return;
412
if (s[pos]==':' && s[pos+1]=='=') { pos=pos+2; return; }
413
if (s[pos]=='=' && s[pos+1]=='=') { pos=pos+2; return; }
417
parse_declare_macro (string s, int& pos) {
418
if (test(s,pos,"==<gtr>")) { pos=pos+7; return; }
419
if (test(s,pos,":=<gtr>")) { pos=pos+7; return; }
423
mathemagix_language_rep::get_color (tree t, int start, int end) {
424
static bool setup_done= false;
426
mathemagix_color_setup_constants (colored);
427
mathemagix_color_setup_keywords (colored);
428
mathemagix_color_setup_otherlexeme (colored);
432
static string none= "";
433
if (start >= end) return none;
436
bool backquote= false;
437
bool after_backquote;
439
bool possible_function= true;
440
bool possible_type= false;
441
bool possible_class= false;
442
bool possible_future_type= false;
443
bool possible_future_function= true;
444
bool possible_future_class= false;
449
parse_string (s, pos);
451
parse_comment (s, pos);
453
parse_end_comment (s, pos);
455
if (pos>start) {return "brown";}
467
after_backquote= backquote;
468
possible_function= possible_future_function;
469
possible_type= possible_future_type;
470
possible_class= possible_future_class;
472
parse_blanks (s, pos);
474
parse_string (s, pos);
479
possible_future_function= false;
480
possible_future_type= false;
481
possible_future_class= false;
482
possible_type= false;
485
parse_comment (s, pos);
490
possible_future_type= false;
491
possible_type= false;
494
parse_modifier (colored, s, pos);
499
possible_future_type= false;
500
possible_type= false;
501
possible_function= false;
504
parse_postfix (colored, s, pos);
509
possible_future_type= false;
510
possible_future_class= false;
511
possible_type= false;
512
possible_function= false;
513
possible_future_class= false;
516
parse_class (colored, s, pos);
521
possible_future_type= false;
522
possible_type= false;
523
possible_future_class=true;
524
possible_future_function= false;
527
parse_keyword (colored, s, pos);
532
possible_future_type= false;
533
possible_type= false;
534
possible_function= false;
535
possible_future_function= false;
536
possible_future_class= false;
539
parse_other_lexeme (colored, s, pos); //not left parenthesis
541
type= "other_lexeme";
544
possible_function= false;
545
possible_future_function= true;
546
possible_future_type= false;
547
possible_future_class= false;
548
possible_type= false;
551
parse_constant (colored, s, pos);
556
possible_future_function= false;
557
possible_future_class= false;
560
parse_number (s, pos);
565
possible_future_function= false;
566
possible_future_class= false;
569
parse_no_declare_type (s, pos); // ::
571
type= "no_declare_type";
572
possible_type= false;
573
possible_future_type= false;
574
possible_function= false;
575
possible_future_function= false;
576
possible_future_class= false;
579
parse_backquote (s, pos);
583
possible_future_function= false;
584
possible_future_class= false;
587
parse_declare_type (s, pos); // : and :>
589
type= "declare_type";
592
if (!after_backquote) possible_future_type=true;
593
possible_function= false;
594
possible_future_function= false;
595
possible_future_class= false;
598
parse_identifier (colored, s, pos, postfix);
603
possible_future_function=false;
604
possible_future_class= false;
607
parse_parenthesized (s, pos);
608
// stops after well parenthesized ) or before // or /{ or " or /"
609
if (opos<pos && pos<=start) {
610
type="left_parenthesis";
613
possible_function= false;
614
possible_future_function= true;
615
possible_future_class= false;
618
if (opos<pos && possible_type==true)
620
if (opos<pos && after_backquote)
630
if (possible_type) return "dark green";
631
if (type=="string") return "#a06040";
632
if (type=="comment") return "brown";
633
if (type=="keyword" && !after_backquote) return "#8020c0";
634
if (type=="other_lexeme") return none;
635
if (type=="constant") return "#2060c0";
636
if (type=="number") return "#2060c0";
637
if (type=="no_declare_type") return none;
638
if (type=="declare_type") return none;
639
if (type=="left_parenthesis") return none;
640
if (type=="identifier" && possible_function==false && possible_class==false)
642
if (type=="identifier" && possible_function) {
643
possible_function= false;
647
parse_blanks (s, pos);
649
parse_identifier (colored, s, pos,false);
650
if (opos<pos) { possible_function= true; break; }
651
parse_number (s, pos);
652
if (opos<pos) { possible_function= true; break; }
653
parse_constant (colored, s, pos);
654
if (opos<pos) { possible_function= true; break; }
655
parse_comment (s, pos);
657
parse_parenthesized (s, pos);
658
if (opos<pos) { possible_function= true; break; }
663
if (!possible_function) return none;
667
parse_blanks (s, pos);
669
parse_identifier (colored, s, pos,false);
673
parse_constant (colored, s, pos);
675
parse_comment(s,pos);
677
parse_parenthesized (s, pos);
679
parse_no_declare_type (s, pos);
681
parse_declare_type (s, pos);
683
parse_declare_macro(s,pos);
684
if (opos<pos) return "#00d000";
685
parse_declare_function (s, pos);
686
if (opos<pos) return "#0000e0";
693
if (type=="identifier" && possible_class) {
697
parse_blanks (s, pos);
699
parse_identifier (colored, s, pos,false);
703
parse_constant (colored, s, pos);
705
parse_comment(s,pos);
707
parse_parenthesized (s, pos);
709
parse_no_declare_type (s, pos);
711
parse_declare_type (s, pos);
713
parse_declare_function (s, pos);
714
if (opos<pos) return "#0000e0";