* Bug #14374 fixed - Parser did not manage comments properly in shellmode
[scilab.git] / scilab / modules / ast / src / cpp / parse / flex / scanscilab.ll
1 %{                                                            /* -*- C++ -*- */
2 /*
3  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
4  *  Copyright (C) 2008-2012 - Scilab Enterprises - Bruno JOFRET
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #include <stack>
18
19 #include "isatty.hxx"
20 #include "parse.hxx"
21 #include "parser_private.hxx"
22
23 #include "context.hxx"
24
25 extern "C"
26 {
27 #include "charEncoding.h"
28 #include "sci_malloc.h"
29 }
30
31 static std::stack<int> paren_levels;
32
33 static int comment_level = 0;
34 static int last_token = 0;
35 static int linebreak_stored_token = 0;
36 static bool linebreak_stored_space = FALSE;
37 static int exit_status = PARSE_ERROR;
38 static int str_opener_column = 0;
39 static std::string current_file;
40 static std::string program_name;
41
42 static std::string pstBuffer;
43
44 extern void yyerror(std::string);
45
46 #define YY_USER_ACTION                          \
47     yylloc.first_column = yylloc.last_column; yylloc.last_column += yyleng;
48 //yylloc.last_column += yyleng;
49
50 /* -*- Verbose Special Debug -*- */
51 //#define DEV
52 //#define TOKENDEV
53
54 #ifdef DEV
55 #define DEBUG(x) std::cout << "[DEBUG] " << x << std::endl;
56 #else
57 #define DEBUG(x) /* Nothing */
58 #endif
59
60 #ifdef DEV
61 std::string token_to_string(int);
62 #endif
63
64 %}
65
66 %option stack
67 %option noyywrap
68
69 %x SIMPLESTRING
70 %x DOUBLESTRING
71 %x REGIONCOMMENT
72 %x LINECOMMENT
73 %x LINEBREAK
74
75 %x MATRIX
76
77 %x SHELLMODE
78 %x BEGINID
79
80 spaces                  [ \t\v\f]+
81 integer                 [0-9]+
82 number                  [0-9]+[\.][0-9]*
83 little                  \.[0-9]+
84 bom             \xEF\xBB\xBF
85
86 floating_D              ({little}|{number}|{integer})[dD][+-]?{integer}
87 floating_E              ({little}|{number}|{integer})[eE][+-]?{integer}
88
89 hex             [0]x[0-9a-fA-F]+
90 oct             [0]o[0-7]+
91
92
93 utf2            ([\xC2-\xDF][\x80-\xBF])
94 utf31           ([\xE0][\xA0-\xBF][\x80-\xBF])
95 utf32           ([\xE1-\xEC][\x80-\xBF][\x80-\xBF])
96 utf33           ([\xED][\x80-\x9F][\x80-\xBF])
97 utf34           ([\xEE-\xEF][\x80-\xBF][\x80-\xBF])
98 utf41           ([\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF])
99 utf42           ([\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF])
100 utf43           ([\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF])
101
102 utf3            ({utf31}|{utf32}|{utf33}|{utf34})
103 utf4            ({utf41}|{utf42}|{utf43})
104
105 utf             ({utf2}|{utf3}|{utf4})
106 id              ((([a-zA-Z_%#?]|{utf})([a-zA-Z_0-9#?$]|{utf})*)|([$]([a-zA-Z_0-9#?$]|{utf})+))
107
108
109 newline                 ("\r"|"\n"|"\r\n")
110 blankline               {spaces}+{newline}
111 emptyline       {newline}({spaces}|[,;])+{newline}
112 next                    \.\.+
113 char_in_line_comment    [^\r\n]*
114 char_in_comment         [^\r\n\/*]*
115
116 boolnot                 ("@"|"~")
117 booltrue                ("%t"|"%T")
118 boolfalse               ("%f"|"%F")
119 booland                 ("&")
120 boolandand              ("&&")
121 boolor                  ("|")
122 booloror                ("||")
123
124 lbrack                  "["
125 rbrack                  "]"
126
127 lparen                  "("
128 rparen                  ")"
129
130 lbrace                  "{"
131 rbrace                  "}"
132
133 dollar                  "$"
134
135 semicolon               ";"
136 comma                   ","
137 colon                   ":"
138
139 startcomment            "//"
140 startblockcomment       "/*"
141 endblockcomment         "*/"
142
143 dquote                  "\""
144 quote                   "'"
145 in_string               [^\"\'\r\n\.]*
146
147 dot             "."
148 dotquote                ".'"
149 dottimes                ".*"
150 dotrdivide              "./"
151 dotldivide              ".\\"
152 dotpower                (".^"|".**")
153
154 plus                    "+"
155 minus                   "-"
156 rdivide                 "/"
157 ldivide                 "\\"
158 times                   "*"
159 power                   ("^"|"**")
160
161 equal                   "="{spaces}*"="
162 notequal                ("~"{spaces}*"="|"@"{spaces}*"="|"<"{spaces}*">")
163 lowerthan               "<"
164 greaterthan             ">"
165 lowerequal              "<"{spaces}*"="
166 greaterequal            ">"{spaces}*"="
167
168 krontimes               ".*."
169 kronrdivide             "./."
170 kronldivide             ".\\."
171
172 controltimes    ("*."[^0-9])
173 controlrdivide  ("/."[^0-9])
174 controlldivide  ("\\."[^0-9])
175
176 assign                  "="
177
178 %%
179 <INITIAL>{bom}/.* {
180 // BOM found ==> ignored
181 }
182
183 <INITIAL,BEGINID>{booltrue}     {
184     BEGIN(INITIAL);
185     return scan_throw(BOOLTRUE);
186 }
187 <INITIAL,BEGINID>{boolfalse}    {
188     BEGIN(INITIAL);
189     return scan_throw(BOOLFALSE);
190 }
191
192 <INITIAL,BEGINID>"if"            {
193         if (last_token != DOT)
194     {
195         ParserSingleInstance::pushControlStatus(Parser::WithinIf);
196     }
197     DEBUG("BEGIN(INITIAL)");
198     BEGIN(INITIAL);
199     return scan_throw(IF);
200 }
201
202 <INITIAL,BEGINID>"then"          {
203     DEBUG("BEGIN(INITIAL)");
204     BEGIN(INITIAL);
205     return scan_throw(THEN);
206 }
207
208 <INITIAL,BEGINID>"else"          {
209         if (last_token != DOT)
210     {
211         // Pop to step out IF
212         ParserSingleInstance::popControlStatus();
213         ParserSingleInstance::pushControlStatus(Parser::WithinElse);
214     }
215     DEBUG("BEGIN(INITIAL)");
216     BEGIN(INITIAL);
217         return scan_throw(ELSE);
218 }
219
220 <INITIAL,BEGINID>"elseif" {
221         if (last_token != DOT)
222     {
223         ParserSingleInstance::popControlStatus();
224         ParserSingleInstance::pushControlStatus(Parser::WithinElseIf);
225     }
226     DEBUG("BEGIN(INITIAL)");
227     BEGIN(INITIAL);
228         return scan_throw(ELSEIF);
229 }
230
231 <INITIAL,BEGINID>"end"          {
232         if (last_token != DOT)
233     {
234         ParserSingleInstance::popControlStatus();
235     }
236     DEBUG("BEGIN(INITIAL)");
237     BEGIN(INITIAL);
238     return scan_throw(END);
239 }
240
241 <INITIAL,BEGINID>"select"       {
242         if (last_token != DOT)
243     {
244         ParserSingleInstance::pushControlStatus(Parser::WithinSelect);
245     }
246     DEBUG("BEGIN(INITIAL)");
247     BEGIN(INITIAL);
248     return scan_throw(SELECT);
249 }
250
251 <INITIAL,BEGINID>"switch"       {
252         if (last_token != DOT)
253     {
254         ParserSingleInstance::pushControlStatus(Parser::WithinSwitch);
255     }
256     DEBUG("BEGIN(INITIAL)");
257     BEGIN(INITIAL);
258     return scan_throw(SWITCH);
259 }
260
261 <INITIAL,BEGINID>"otherwise" {
262         if (last_token != DOT)
263     {
264         ParserSingleInstance::popControlStatus();
265         ParserSingleInstance::pushControlStatus(Parser::WithinOtherwise);
266     }
267     DEBUG("BEGIN(INITIAL)");
268     BEGIN(INITIAL);
269         return scan_throw(OTHERWISE);
270 }
271
272 <INITIAL,BEGINID>"case"         {
273         if (last_token != DOT)
274     {
275         ParserSingleInstance::popControlStatus();
276         ParserSingleInstance::pushControlStatus(Parser::WithinCase);
277     }
278     DEBUG("BEGIN(INITIAL)");
279     BEGIN(INITIAL);
280     return scan_throw(CASE);
281 }
282
283 <INITIAL,BEGINID>"function" {
284         if (last_token != DOT)
285     {
286         ParserSingleInstance::pushControlStatus(Parser::WithinFunction);
287     }
288     DEBUG("BEGIN(INITIAL)");
289     BEGIN(INITIAL);
290     return scan_throw(FUNCTION);
291 }
292
293 <INITIAL,BEGINID>"endfunction" {
294         if (last_token != DOT)
295     {
296         ParserSingleInstance::popControlStatus();
297     }
298     DEBUG("BEGIN(INITIAL)");
299     BEGIN(INITIAL);
300         return scan_throw(ENDFUNCTION);
301 }
302
303 <INITIAL,BEGINID>"for" {
304         if (last_token != DOT)
305     {
306         ParserSingleInstance::pushControlStatus(Parser::WithinFor);
307     }
308     BEGIN(INITIAL);
309     return scan_throw(FOR);
310 }
311
312 <INITIAL,BEGINID>"while"        {
313         if (last_token != DOT)
314     {
315         ParserSingleInstance::pushControlStatus(Parser::WithinWhile);
316     }
317         BEGIN(INITIAL);
318         return scan_throw(WHILE);
319 }
320
321 <INITIAL,BEGINID>"do"           {
322         BEGIN(INITIAL);
323     return scan_throw(DO);
324 }
325
326 <INITIAL,BEGINID>"break"                {
327         BEGIN(INITIAL);
328         return scan_throw(BREAK);
329 }
330
331 <INITIAL,BEGINID>"continue"             {
332         BEGIN(INITIAL);
333         return scan_throw(CONTINUE);
334 }
335
336 <INITIAL,BEGINID>"try" {
337         ParserSingleInstance::pushControlStatus(Parser::WithinTry);
338         BEGIN(INITIAL);
339         return scan_throw(TRY);
340 }
341
342 <INITIAL,BEGINID>"catch" {
343     // Pop to step out TRY
344         ParserSingleInstance::popControlStatus();
345         ParserSingleInstance::pushControlStatus(Parser::WithinCatch);
346         BEGIN(INITIAL);
347         return scan_throw(CATCH);
348 }
349
350 <INITIAL,BEGINID>"return"       {
351     BEGIN(INITIAL);
352     return scan_throw(RETURN);
353 }
354
355 <INITIAL,BEGINID>"resume"       {
356     BEGIN(INITIAL);
357     return scan_throw(RETURN);
358 }
359
360 ^{spaces}*/({id}){spaces}([^ \t\v\f(=<>~@]|([~@]{spaces}*[^=]?)) {
361         BEGIN(BEGINID);
362 }
363
364 <BEGINID>
365 {
366     {id}                        {
367         wchar_t *pwText = to_wide_string(yytext);
368         if (yytext != NULL && pwText == NULL)
369         {
370             std::string str = "Can\'t convert \'";
371             str += yytext;
372             str += "\' to UTF-8";
373             BEGIN(INITIAL);
374             yyerror(str);
375             return scan_throw(FLEX_ERROR);
376         }
377         yylval.str = new std::wstring(pwText);
378         FREE(pwText);
379         types::InternalType * pIT = symbol::Context::getInstance()->get(symbol::Symbol(*yylval.str));
380         if (pIT && pIT->isCallable())
381         {
382             scan_throw(ID);
383             BEGIN(SHELLMODE);
384         }
385         else
386         {
387             BEGIN(INITIAL);
388             return scan_throw(ID);
389         }
390     }
391
392 }
393
394 <INITIAL,MATRIX>{boolnot}               {
395   return scan_throw(NOT);
396 }
397 <INITIAL,MATRIX>{dollar}                {
398   return scan_throw(DOLLAR);
399 }
400 <INITIAL,MATRIX>{booltrue}              {
401   return scan_throw(BOOLTRUE);
402 }
403 <INITIAL,MATRIX>{boolfalse}             {
404   return scan_throw(BOOLFALSE);
405 }
406 <INITIAL,MATRIX>{booland}               {
407   return scan_throw(AND);
408 }
409 <INITIAL,MATRIX>{boolandand}    {
410   return scan_throw(ANDAND);
411 }
412 <INITIAL,MATRIX>{boolor}                {
413   return scan_throw(OR);
414 }
415 <INITIAL,MATRIX>{booloror}              {
416   return scan_throw(OROR);
417 }
418
419
420 <INITIAL>{lparen}                       {
421   return scan_throw(LPAREN);
422 }
423 <INITIAL>{rparen}                       {
424   return scan_throw(RPAREN);
425 }
426
427
428 <INITIAL,MATRIX>{semicolon}             {
429         scan_step();
430   return scan_throw(SEMI);
431 }
432
433 <INITIAL,MATRIX>{comma}                 {
434         scan_step();
435   return scan_throw(COMMA);
436 }
437
438 <INITIAL,MATRIX>{colon}                 {
439   return scan_throw(COLON);
440 }
441
442
443 <INITIAL,MATRIX>{lbrace}                {
444   yy_push_state(MATRIX);
445   paren_levels.push(0);
446   ParserSingleInstance::pushControlStatus(Parser::WithinCell);
447   return scan_throw(LBRACE);
448 }
449
450 {rbrace}                        {
451   return scan_throw(RBRACE);
452 }
453
454
455 <INITIAL,MATRIX>{dotquote}              {
456   return scan_throw(DOTQUOTE);
457 }
458 <INITIAL,MATRIX>{dottimes}              {
459   return scan_throw(DOTTIMES);
460 }
461 <INITIAL,MATRIX>{dotrdivide}            {
462   return scan_throw(DOTRDIVIDE);
463 }
464 <INITIAL,MATRIX>{dotldivide}            {
465   return scan_throw(DOTLDIVIDE);
466 }
467 <INITIAL,MATRIX>{dotpower}              {
468   return scan_throw(DOTPOWER);
469 }
470
471
472 {minus}                                 {
473   return scan_throw(MINUS);
474 }
475 {plus}                                  {
476   return scan_throw(PLUS);
477 }
478 <INITIAL,MATRIX>{times}                 {
479   return scan_throw(TIMES);
480 }
481 <INITIAL,MATRIX>{rdivide}               {
482   return scan_throw(RDIVIDE);
483 }
484 <INITIAL,MATRIX>{ldivide}               {
485   return scan_throw(LDIVIDE);
486 }
487 <INITIAL,MATRIX>{power}                 {
488   return scan_throw(POWER);
489 }
490
491 <INITIAL,MATRIX>{krontimes}             {
492   return scan_throw(KRONTIMES);
493 }
494 <INITIAL,MATRIX>{kronrdivide}           {
495   return scan_throw(KRONRDIVIDE);
496 }
497 <INITIAL,MATRIX>{kronldivide}           {
498   return scan_throw(KRONLDIVIDE);
499 }
500
501
502 <INITIAL,MATRIX>{controltimes}          {
503     unput(yytext[yyleng - 1]);
504     return scan_throw(CONTROLTIMES);
505 }
506 <INITIAL,MATRIX>{controlrdivide}                {
507     unput(yytext[yyleng - 1]);
508     return scan_throw(CONTROLRDIVIDE);
509 }
510 <INITIAL,MATRIX>{controlldivide}                {
511     unput(yytext[yyleng - 1]);
512     return scan_throw(CONTROLLDIVIDE);
513 }
514
515
516 <INITIAL,MATRIX>{equal}                 {
517   return scan_throw(EQ);
518 }
519 <INITIAL,MATRIX>{notequal}              {
520   return scan_throw(NE);
521 }
522 <INITIAL,MATRIX>{lowerthan}             {
523   return scan_throw(LT);
524 }
525 <INITIAL,MATRIX>{greaterthan}           {
526   return scan_throw(GT);
527 }
528 <INITIAL,MATRIX>{lowerequal}            {
529   return scan_throw(LE);
530 }
531 <INITIAL,MATRIX>{greaterequal}          {
532   return scan_throw(GE);
533 }
534
535
536 <INITIAL,MATRIX>{assign}                {
537   return scan_throw(ASSIGN);
538  }
539
540
541 <INITIAL,MATRIX>{lbrack}                {
542   DEBUG("yy_push_state(MATRIX)");
543   yy_push_state(MATRIX);
544   paren_levels.push(0);
545   ParserSingleInstance::pushControlStatus(Parser::WithinMatrix);
546   return scan_throw(LBRACK);
547 }
548
549 <INITIAL>{rbrack}                               {
550   return scan_throw(RBRACK);
551 }
552
553
554 <INITIAL,MATRIX>{dot}                   {
555   return scan_throw(DOT);
556 }
557
558 <INITIAL>{next}                 {
559     ParserSingleInstance::pushControlStatus(Parser::WithinDots);
560     yy_push_state(LINEBREAK);
561 }
562
563 <INITIAL,MATRIX>{integer}               {
564   yylval.number = atof(yytext);
565 #ifdef TOKENDEV
566   std::cout << "--> [DEBUG] INTEGER : " << yytext << std::endl;
567 #endif
568 //  scan_step();
569   return scan_throw(VARINT);
570 }
571
572
573 <INITIAL,MATRIX>{floating_D}            {
574   scan_exponent_convert(yytext);
575   yylval.number = atof(yytext);
576 #ifdef TOKENDEV
577   std::cout << "--> [DEBUG] FLOATING : " << yytext << std::endl;
578 #endif
579   //scan_step();
580   return scan_throw(VARFLOAT);
581 }
582
583 <INITIAL,MATRIX>{floating_E}            {
584   yylval.number = atof(yytext);
585 #ifdef TOKENDEV
586   std::cout << "--> [DEBUG] FLOATING : " << yytext << std::endl;
587 #endif
588   //scan_step();
589   return scan_throw(VARFLOAT);
590 }
591
592 <INITIAL,MATRIX>[0-9]+[\.]/[\*^\\\/]            {
593
594   yylval.number = atof(yytext);
595 #ifdef TOKENDEV
596   std::cout << "--> [DEBUG] NUMBER WITH DOT AS LAST CHARACTER : " << yytext << std::endl;
597 #endif
598 //  scan_step();
599   unput('.');
600   yylloc.last_column--;
601   return scan_throw(NUM);
602 }
603
604 <INITIAL,MATRIX>{number}                {
605   yylval.number = atof(yytext);
606 #ifdef TOKENDEV
607   std::cout << "--> [DEBUG] NUMBER : " << yytext << std::endl;
608 #endif
609 //  scan_step();
610   return scan_throw(NUM);
611 }
612
613
614 <INITIAL,MATRIX>{little}                {
615   yylval.number = atof(yytext);
616 #ifdef TOKENDEV
617   std::cout << "--> [DEBUG] LITTLE : " << yytext << std::endl;
618 #endif
619 //  scan_step();
620   return scan_throw(NUM);
621 }
622
623
624 <INITIAL,MATRIX>{id}                    {
625     wchar_t *pwText = to_wide_string(yytext);
626     if (yytext != NULL && pwText == NULL)
627     {
628         std::string str = "Can\'t convert \'";
629         str += yytext;
630         str += "\' to UTF-8";
631         BEGIN(INITIAL);
632         yyerror(str);
633         return scan_throw(FLEX_ERROR);
634     }
635     yylval.str = new std::wstring(pwText);
636     FREE(pwText);
637 #ifdef TOKENDEV
638   std::cout << "--> [DEBUG] ID : " << yytext << std::endl;
639 #endif
640 //  scan_step();
641   return scan_throw(ID);
642 }
643
644
645 <INITIAL,MATRIX,SHELLMODE,BEGINID>{startblockcomment}   {
646   yylval.comment = new std::wstring();
647   comment_level = 1;
648   ParserSingleInstance::pushControlStatus(Parser::WithinBlockComment);
649   yy_push_state(REGIONCOMMENT);
650 }
651
652
653 <INITIAL,MATRIX,SHELLMODE,BEGINID>{startcomment}                {
654   pstBuffer.clear();
655   yy_push_state(LINECOMMENT);
656 }
657
658
659 <INITIAL,MATRIX,SHELLMODE>{dquote}              {
660   pstBuffer.clear();
661   str_opener_column = yylloc.first_column;
662   yy_push_state(DOUBLESTRING);
663 }
664
665
666 <INITIAL,MATRIX,SHELLMODE>{quote}                       {
667   /*
668   ** Matrix Transposition special behaviour
669   ** ID' []' toto()' are transposition call
670   */
671   if (last_token == ID
672       || last_token == RBRACK
673       || last_token == RPAREN
674       || last_token == RBRACE
675       || last_token == VARINT
676       || last_token == VARFLOAT
677       || last_token == NUM
678       || last_token == BOOLTRUE
679       || last_token == BOOLFALSE)
680   {
681       return scan_throw(QUOTE);
682   }
683   else
684   {
685       pstBuffer.clear();
686       str_opener_column = yylloc.first_column;
687       yy_push_state(SIMPLESTRING);
688   }
689 }
690
691
692 <INITIAL,MATRIX>{spaces}                {
693         scan_step();
694 }
695
696
697 <INITIAL>{newline}              {
698   yylloc.last_line += 1;
699   yylloc.last_column = 1;
700   scan_step();
701   if (last_token != EOL) {
702       return scan_throw(EOL);
703   }
704
705 }
706
707
708 <INITIAL,MATRIX>{blankline}             {
709   yylloc.last_line += 1;
710   yylloc.last_column = 1;
711   scan_step();
712   if (last_token != EOL)
713   {
714       return scan_throw(EOL);
715   }
716   scan_throw(EOL);
717 }
718
719 <INITIAL,MATRIX>{emptyline}             {
720   yylloc.last_line += 2;
721   yylloc.last_column = 1;
722   scan_step();
723   if (last_token != EOL)
724   {
725       return scan_throw(EOL);
726   }
727   scan_throw(EOL);
728 }
729 .                                       {
730     std::string str = "Unexpected token \'";
731     str += yytext;
732     str += "\'";
733     BEGIN(INITIAL);
734     yyerror(str);
735     return scan_throw(FLEX_ERROR);
736 }
737
738
739 <MATRIX>
740 {
741   {lparen} {
742     ++paren_levels.top();
743     return scan_throw(LPAREN);
744   }
745
746   {rparen} {
747     --paren_levels.top();
748     return scan_throw(RPAREN);
749   }
750
751   {spaces}*{lparen} {
752       unput(yytext[yyleng -1]);
753       if (last_token == ID
754           || last_token == RPAREN
755           || last_token == QUOTE
756           || last_token == VARINT
757           || last_token == VARFLOAT
758           || last_token == NUM)
759       {
760           return scan_throw(COMMA);
761       }
762   }
763
764   {spaces}*{colon}{spaces}* {
765       return scan_throw(COLON);
766   }
767
768   {newline} {
769       yylloc.last_line += 1;
770       yylloc.last_column = 1;
771       if(last_token != DOTS && last_token != EOL)
772       {
773           return scan_throw(EOL);
774       }
775       scan_throw(EOL);
776   }
777
778   {rbrack}                              {
779     DEBUG("yy_pop_state()");
780     yy_pop_state();
781     paren_levels.pop();
782     ParserSingleInstance::popControlStatus();
783     return scan_throw(RBRACK);
784   }
785
786   {rbrace}                              {
787     yy_pop_state();
788     paren_levels.pop();
789     ParserSingleInstance::popControlStatus();
790     return scan_throw(RBRACE);
791   }
792
793   {plus}                                |
794   {spaces}{plus}{spaces}                {
795     // _+_ is always meaning a PLUS token
796     // + alone is a plus if and only if it does not
797     // fall into the {spaces}{plus} rule (in matrices space is coding)
798     // as Flex is greedy the {plus} rule is only applied
799     // if no {spaces}{plus} is found
800     // Examples:
801     // ========
802     // [1 + 2 3] must be understood as [(1+2), 3]
803     // [1 +2 3] must be understood as [1, 2, 3]
804     // [1 +...
805     // 2] must be understood as [(1+2)]
806     return scan_throw(PLUS);
807   }
808
809   {minus}                               |
810   {spaces}{minus}{spaces}               {
811     // _-_ is always meaning a MINUS token
812     // - alone is a MINUS only if and only if it does not
813     // fall into the {spaces}{minus} rule (in matrices space is coding)
814     // as Flex is greedy the {minus} rule is only applied
815     // if no {spaces}{minus} is found
816     // Examples:
817     // ========
818     // [1 - 2 3] must be understood as [(1-2), 3]
819     // [1 -2 3] must be understood as [1, -2, 3]
820     // [1 -...
821     // 2] must be understood as [(1-2)]
822     return scan_throw(MINUS);
823   }
824
825   {spaces}{plus}                        {
826     // This rule is made to take into account the coding spaces in matrices.
827     // It is important to distinguish between a space coding a matrix column separator
828     // and a simple non coding space around the PLUS operator
829     // Examples
830     // ========
831     // [a + b] == [(a + b)]
832     // but [a +b] == [a, b] and plus here is unary
833     // the space is non coding:
834     // * after any other binary operator __op__
835     //   Example : [a __op__ +b]
836     // * after brackets or parentheses delimiters
837     //   Example : [(1*2*a) +3]
838     // * at the beginning of a line
839     //   Example : [3 ...
840     //              _+2]
841
842     // no need to unput the '+'
843     if (last_token != LBRACK
844        && last_token != EOL
845        && last_token != SEMI
846        && last_token != COMMA
847        && last_token != DOTTIMES
848        && last_token != DOTRDIVIDE
849        && last_token != DOTLDIVIDE
850        && last_token != DOTPOWER
851        && last_token != MINUS
852        && last_token != PLUS
853        && last_token != TIMES
854        && last_token != RDIVIDE
855        && last_token != LDIVIDE
856        && last_token != POWER
857        && last_token != KRONTIMES
858        && last_token != KRONRDIVIDE
859        && last_token != KRONLDIVIDE
860        && last_token != EQ
861        && last_token != NE
862        && last_token != LT
863        && last_token != GT
864        && last_token != LE
865        && last_token != GE
866       && paren_levels.top() == 0)
867    {
868        return scan_throw(COMMA);
869    }
870    else
871    {
872        unput('+');
873        yylloc.last_column--;
874    }
875   }
876
877   {spaces}{minus}                       {
878     // See {spaces}{plus} rule for the rationale
879
880     unput('-');
881     yylloc.last_column--;
882     if (last_token != LBRACK
883        && last_token != EOL
884        && last_token != SEMI
885        && last_token != COMMA
886        && last_token != DOTTIMES
887        && last_token != DOTRDIVIDE
888        && last_token != DOTLDIVIDE
889        && last_token != DOTPOWER
890        && last_token != MINUS
891        && last_token != PLUS
892        && last_token != TIMES
893        && last_token != RDIVIDE
894        && last_token != LDIVIDE
895        && last_token != POWER
896        && last_token != KRONTIMES
897        && last_token != KRONRDIVIDE
898        && last_token != KRONLDIVIDE
899        && last_token != EQ
900        && last_token != NE
901        && last_token != LT
902        && last_token != GT
903        && last_token != LE
904        && last_token != GE
905        && paren_levels.top() == 0)
906    {
907        return scan_throw(COMMA);
908    }
909   }
910
911   .                                     {
912     std::string str = "Unexpected token \'";
913     str += yytext;
914     str += "\' within a matrix.";
915     BEGIN(INITIAL);
916     yyerror(str);
917     return scan_throw(FLEX_ERROR);
918   }
919
920   /* {next} rules
921    * ============
922    * Scilab can perform a line continuation with the ..
923    * In matrices as space may be coding extra care must be taken when parsing {next}
924    * Some states must be preserved to parse next line and to revert to a proper state
925    * after the ... // comments or ... \/* comments *\/
926    */
927
928   {spaces}*{plus}{next} {
929              // This rule is made to take into account a +... without spaces after plus
930              // if one simply ignores the next a situation like this could arise
931              // Example
932              // =======
933              // A = [1 +...
934              // 2] 
935              //
936              // what is meant by the user [1 +2] ? or [1 + 2]
937              // simply ignoring the ... would yield the 1st situation [1, 2]
938              // We consider this is NOT proper and instead that the user meant a binary plus
939              // split is two lines
940              // The same rationale applies to minus.
941
942              linebreak_stored_space = FALSE; // no spaces before ...
943              linebreak_stored_token = PLUS; // keep last token to restore
944              ParserSingleInstance::pushControlStatus(Parser::WithinDots);
945              yy_push_state(LINEBREAK);
946              return scan_throw(PLUS);
947          }
948
949   {spaces}*{minus}{next} {
950              // see {spaces}*{minus}{next} for the rationale
951
952              linebreak_stored_space = FALSE; // no spaces before ...
953              linebreak_stored_token = MINUS; // keep last token to restore
954              ParserSingleInstance::pushControlStatus(Parser::WithinDots);
955              yy_push_state(LINEBREAK);
956              return scan_throw(MINUS);
957          }
958
959   {next} {
960              // Store the state of the previously scanned token for next rule
961              // Only considerations of coding spaces is important for the parser
962
963              linebreak_stored_space = FALSE; // no spaces before ...
964              linebreak_stored_token = last_token; // keep last token to restore state
965              ParserSingleInstance::pushControlStatus(Parser::WithinDots);
966              yy_push_state(LINEBREAK);
967          }
968
969   {spaces}{next} {
970              // Store the state of the previously scanned token for next rule
971              // Only considerations of coding spaces is important for the parser
972
973              linebreak_stored_space = TRUE; // no spaces before ...
974              linebreak_stored_token = last_token; // keep last token to restore state
975              ParserSingleInstance::pushControlStatus(Parser::WithinDots);
976              yy_push_state(LINEBREAK);
977          }
978
979   <<EOF>>       {
980       yy_pop_state();
981       paren_levels.pop();
982   }
983 }
984
985 <LINEBREAK>
986 {
987   {newline}                             {
988     yylloc.last_line += 1;
989     yylloc.last_column = 1;
990     scan_step();
991     last_token = linebreak_stored_token;
992     if (linebreak_stored_space)
993     {
994         // This is important to restore coding spaces as if ... was not present
995         unput(' ');
996         linebreak_stored_space = FALSE;
997     }
998     yy_pop_state();
999     ParserSingleInstance::popControlStatus();
1000   }
1001
1002   {startblockcomment}                   {
1003     yylval.comment = new std::wstring();
1004     comment_level = 1;
1005     ParserSingleInstance::pushControlStatus(Parser::WithinBlockComment);
1006     yy_push_state(REGIONCOMMENT);
1007   }
1008
1009   {startcomment}                        {
1010     scan_throw(DOTS);
1011     pstBuffer.clear();
1012     yy_push_state(LINECOMMENT);
1013   }
1014
1015   {spaces}                              {
1016       /* Do nothing... */
1017   }
1018
1019   <<EOF>>       {
1020       yy_pop_state();
1021   }
1022   .                                     {
1023     // The following case is not handled by the parser
1024     // a line of code ... /* some multiline
1025     // comments */ continued here;
1026     // without the special case telling we are after comments
1027     // will generate the error as follows:
1028
1029     // Any characters after ... yields to an error
1030     std::string str = "Unexpected token \'";
1031     str += yytext;
1032     str += "\' after line break with .. or ...";
1033     yy_pop_state();
1034     ParserSingleInstance::popControlStatus();
1035     BEGIN(INITIAL);
1036     yyerror(str);
1037     return scan_throw(FLEX_ERROR);
1038   }
1039 }
1040
1041
1042 <LINECOMMENT>
1043 {
1044   {newline}     {
1045     //yylloc.last_line += 1;
1046     //yylloc.last_column = 1;
1047     //scan_step();
1048     yy_pop_state();
1049     for (int i = yyleng - 1 ; i >= 0 ; --i)
1050     {
1051         //std::cerr << "Unputting i = {" << i << "}" << std::endl;
1052         //std::cerr << "Unputting {" << yytext[i] << "}" << std::endl;
1053         unput(yytext[i]);
1054         yylloc.last_column--;
1055     }
1056     /*
1057     ** To forgot comments after lines break
1058     */
1059     if (last_token != DOTS)
1060     {
1061         //std::cerr << "pstBuffer = {" << *pstBuffer << "}" << std::endl;
1062         //std::cerr << "pstBuffer->c_str() = {" << pstBuffer->c_str() << "}" << std::endl;
1063         wchar_t *pwstBuffer = to_wide_string(pstBuffer.c_str());
1064         //std::wcerr << L"pwstBuffer = W{" << pwstBuffer << L"}" << std::endl;
1065         if (pstBuffer.c_str() != NULL && pwstBuffer == NULL)
1066         {
1067             pstBuffer.clear();
1068             std::string str = "Can\'t convert \'";
1069             str += pstBuffer.c_str();
1070             str += "\' to UTF-8";
1071             BEGIN(INITIAL);
1072             yyerror(str);
1073             return scan_throw(FLEX_ERROR);
1074         }
1075         yylval.comment = new std::wstring(pwstBuffer);
1076         pstBuffer.clear();
1077         FREE (pwstBuffer);
1078         return scan_throw(COMMENT);
1079     }
1080     else
1081     {
1082         pstBuffer.clear();
1083     }
1084   }
1085
1086   <<EOF>>       {
1087     yy_pop_state();
1088     wchar_t *pwstBuffer = to_wide_string(pstBuffer.c_str());
1089     if (pstBuffer.c_str() != NULL && pwstBuffer == NULL)
1090     {
1091         pstBuffer.clear();
1092         std::string str = "Can\'t convert \'";
1093         str += pstBuffer.c_str();
1094         str += "\' to UTF-8";
1095         BEGIN(INITIAL);
1096         yyerror(str);
1097         return scan_throw(FLEX_ERROR);
1098     }
1099     yylval.comment = new std::wstring(pwstBuffer);
1100     pstBuffer.clear();
1101     FREE (pwstBuffer);
1102     return scan_throw(COMMENT);
1103   }
1104
1105   {char_in_line_comment}         {
1106       // Put the char in a temporary CHAR buffer to go through UTF-8 trouble
1107       // only translate to WCHAR_T when popping state.
1108       pstBuffer += yytext;
1109   }
1110 }
1111
1112
1113 <REGIONCOMMENT>
1114 {
1115   {endblockcomment}                             {
1116     --comment_level;
1117     if (comment_level == 0) {
1118       ParserSingleInstance::popControlStatus();
1119       yy_pop_state();
1120       //return scan_throw(BLOCKCOMMENT);
1121     }
1122   }
1123
1124   {startblockcomment}                           {
1125     ++comment_level;
1126     yy_push_state(REGIONCOMMENT);
1127   }
1128
1129   {newline}                                     {
1130     yylloc.last_line += 1;
1131     yylloc.last_column = 1;
1132     scan_step();
1133     *yylval.comment += L"\n//";
1134   }
1135
1136   {char_in_comment}                             |
1137   .                                             {
1138       wchar_t *pwText = to_wide_string(yytext);
1139       *yylval.comment += std::wstring(pwText);
1140       FREE(pwText);
1141   }
1142
1143  <<EOF>>                                        {
1144       yy_pop_state();
1145 //    std::string str = "unexpected end of file in a comment";
1146 //    scan_error(str);
1147   }
1148 }
1149
1150
1151 <SIMPLESTRING>
1152 {
1153   {dquote}{dquote}                              {
1154     pstBuffer += "\"";
1155   }
1156
1157   {dquote}{quote}                               {
1158     pstBuffer += "'";
1159   }
1160
1161   {quote}{dquote}                               {
1162     pstBuffer += "\"";
1163   }
1164
1165   {quote}{quote}                                {
1166     pstBuffer += "'";
1167   }
1168
1169   {quote}                                       {
1170     yy_pop_state();
1171     //scan_step();
1172     wchar_t *pwstBuffer = to_wide_string(pstBuffer.c_str());
1173     if (pstBuffer.c_str() != NULL && pwstBuffer == NULL)
1174     {
1175         pstBuffer.clear();
1176         std::string str = "Can\'t convert \'";
1177         str += pstBuffer.c_str();
1178         str += "\' to UTF-8";
1179         BEGIN(INITIAL);
1180         yyerror(str);
1181         return scan_throw(FLEX_ERROR);
1182     }
1183     yylval.str = new std::wstring(pwstBuffer);
1184     pstBuffer.clear();
1185     FREE(pwstBuffer);
1186     yylloc.first_column = str_opener_column;
1187     return scan_throw(STR);
1188   }
1189
1190   {dquote}                  {
1191     pstBuffer.clear();
1192     BEGIN(INITIAL);
1193     yyerror("Heterogeneous string detected, starting with \' and ending with \".");
1194     return scan_throw(FLEX_ERROR);
1195   }
1196
1197   {next}{newline}           {
1198       yylloc.last_line += 1;
1199       yylloc.last_column = 1;
1200       /* Do nothing... Just skip */
1201   }
1202
1203   {newline}                                     {
1204     pstBuffer.clear();
1205     yylloc.last_line += 1;
1206     yylloc.last_column = 1;
1207     BEGIN(INITIAL);
1208     yyerror("Unexpected end of line in a string.");
1209     return scan_throw(FLEX_ERROR);
1210   }
1211
1212   <<EOF>>                                       {
1213     pstBuffer.clear();
1214     BEGIN(INITIAL);
1215     yyerror("Unexpected end of file in a string.");
1216     return scan_throw(FLEX_ERROR);
1217   }
1218
1219   {in_string}                                           |
1220   .                                                     {
1221     //scan_step();
1222     pstBuffer += yytext;
1223   }
1224 }
1225
1226
1227 <DOUBLESTRING>
1228 {
1229   {dquote}{dquote}                              {
1230     pstBuffer += "\"";
1231   }
1232
1233   {dquote}{quote}                               {
1234     pstBuffer += "'";
1235   }
1236
1237   {quote}{dquote}               {
1238     pstBuffer += "\"";
1239   }
1240
1241   {quote}{quote}                                {
1242     pstBuffer += "'";
1243   }
1244
1245   {dquote}                      {
1246     yy_pop_state();
1247     //scan_step();
1248     wchar_t *pwstBuffer = to_wide_string(pstBuffer.c_str());
1249     if (pstBuffer.c_str() != NULL && pwstBuffer == NULL)
1250     {
1251         pstBuffer.clear();
1252         std::string str = "Can\'t convert \'";
1253         str += pstBuffer.c_str();
1254         str += "\' to UTF-8";
1255         BEGIN(INITIAL);
1256         yyerror(str);
1257         return scan_throw(FLEX_ERROR);
1258     }
1259     yylval.str = new std::wstring(pwstBuffer);
1260     pstBuffer.clear();
1261     FREE(pwstBuffer);
1262     yylloc.first_column = str_opener_column;
1263     return scan_throw(STR);
1264   }
1265
1266   {quote}                  {
1267     pstBuffer.clear();
1268     BEGIN(INITIAL);
1269     yyerror("Heterogeneous string detected, starting with \" and ending with \'.");
1270     return scan_throw(FLEX_ERROR);
1271   }
1272
1273   {next}{newline}           {
1274       yylloc.last_line += 1;
1275       yylloc.last_column = 1;
1276       /* Do nothing... Just skip */
1277   }
1278
1279   {newline} {
1280     pstBuffer.clear();
1281     yylloc.last_line += 1;
1282     yylloc.last_column = 1;
1283     BEGIN(INITIAL);
1284     yyerror("Unexpected end of line in a string.");
1285     return scan_throw(FLEX_ERROR);
1286   }
1287
1288   <<EOF>>   {
1289     pstBuffer.clear();
1290     BEGIN(INITIAL);
1291     yyerror("Unexpected end of file in a string.");
1292     return scan_throw(FLEX_ERROR);
1293   }
1294
1295   {in_string}         |
1296   .                   {
1297    //scan_step();
1298    pstBuffer += yytext;
1299   }
1300 }
1301
1302
1303 <SHELLMODE>
1304 {
1305     {spaces}                    {
1306         if (last_token == ID)
1307         {
1308             scan_throw(SPACES);
1309             return ID;
1310         }
1311     }
1312
1313     {semicolon}                 {
1314         BEGIN(INITIAL);
1315         scan_step();
1316         return scan_throw(SEMI);
1317     }
1318
1319     {comma}                     {
1320         BEGIN(INITIAL);
1321         scan_step();
1322         return scan_throw(COMMA);
1323     }
1324
1325     {newline}                   {
1326         BEGIN(INITIAL);
1327         yylloc.last_line += 1;
1328         yylloc.last_column = 1;
1329         scan_step();
1330         return scan_throw(EOL);
1331     }
1332
1333     {assign} {
1334         if (last_token == STR || last_token == SPACES)
1335         {
1336             wchar_t *pwText = to_wide_string(yytext);
1337             yylval.str = new std::wstring(pwText);
1338             FREE(pwText);
1339             return scan_throw(STR);
1340         }
1341         else
1342         {
1343             BEGIN(INITIAL);
1344             return scan_throw(ASSIGN);
1345         }
1346     }
1347
1348     {lparen} {
1349         if (last_token == STR || last_token == SPACES)
1350         {
1351             wchar_t *pwText = to_wide_string(yytext);
1352             yylval.str = new std::wstring(pwText);
1353             FREE(pwText);
1354             return scan_throw(STR);
1355         }
1356         else
1357         {
1358             BEGIN(INITIAL);
1359             return scan_throw(LPAREN);
1360         }
1361     }
1362
1363     {lowerthan} {
1364         if (last_token == STR || last_token == SPACES)
1365         {
1366             wchar_t *pwText = to_wide_string(yytext);
1367             yylval.str = new std::wstring(pwText);
1368             FREE(pwText);
1369             return scan_throw(STR);
1370         }
1371         else
1372         {
1373             BEGIN(INITIAL);
1374             return scan_throw(LT);
1375         }
1376     }
1377
1378     {greaterthan} {
1379         if (last_token == STR || last_token == SPACES)
1380         {
1381             wchar_t *pwText = to_wide_string(yytext);
1382             yylval.str = new std::wstring(pwText);
1383             FREE(pwText);
1384             return scan_throw(STR);
1385         }
1386         else
1387         {
1388             BEGIN(INITIAL);
1389             return scan_throw(GT);
1390         }
1391     }
1392
1393     {boolnot} {
1394         if (last_token == STR || last_token == SPACES)
1395         {
1396             wchar_t *pwText = to_wide_string(yytext);
1397             yylval.str = new std::wstring(pwText);
1398             FREE(pwText);
1399             return scan_throw(STR);
1400         }
1401         else
1402         {
1403             BEGIN(INITIAL);
1404             return scan_throw(NOT);
1405         }
1406     }
1407
1408
1409     [^ \t\v\f\r\n,;'"]+               {
1410         wchar_t *pwText = to_wide_string(yytext);
1411         yylval.str = new std::wstring(pwText);
1412         FREE(pwText);
1413         return scan_throw(STR);
1414     }
1415
1416     <<EOF>>                     {
1417         BEGIN(INITIAL);
1418     }
1419
1420 }
1421
1422 %%
1423
1424 int scan_throw(int token) {
1425   last_token = token;
1426 #ifdef DEV
1427   std::cout << "--> [DEBUG] TOKEN : " << token << " - " << token_to_string(token) << std::endl;
1428 #endif
1429   return token;
1430 }
1431
1432 int get_last_token() {
1433     return last_token;
1434 }
1435
1436 void scan_step() {
1437   yylloc.first_line = yylloc.last_line;
1438   yylloc.first_column = yylloc.last_column;
1439 }
1440
1441 /*
1442 ** convert floating numbers to C standard
1443 ** 1.2d-3 -> 1.2e-3
1444 ** 1.2D-3 -> 1.2e-3
1445 */
1446 void scan_exponent_convert(char *in)
1447 {
1448   for (; *in != 'd' && *in != 'D'; ++in);
1449   *in = 'e';
1450 }
1451
1452 #ifdef _MSC_VER
1453 int isatty (int desc)
1454 {
1455   return 0;
1456 }
1457 #endif
1458
1459 #ifdef DEV
1460 std::string token_to_string(int token)
1461 {
1462     std::string str;
1463     switch(token)
1464     {
1465         case AND :                   str = "AND";
1466                                      break;
1467         case ASSIGN :                str = "ASSIGN";
1468                                      break;
1469         case BOOLFALSE :             str = "BOOLFALSE";
1470                                      break;
1471         case BOOLTRUE :              str = "BOOLTRUE";
1472                                      break;
1473         case BREAK :                 str = "BREAK";
1474                                      break;
1475         case CASE :                  str = "CASE";
1476                                      break;
1477         case CATCH :                 str = "CATCH";
1478                                      break;
1479         case COLON :                 str = "COLON";
1480                                      break;
1481         case COMMA :                 str = "COMMA";
1482                                      break;
1483         case COMMENT :               str = "COMMENT";
1484                                      break;
1485         case CONTINUE :              str = "CONTINUE";
1486                                      break;
1487         case CONTROLLDIVIDE :        str = "CONTROLLDIVIDE";
1488                                      break;
1489         case CONTROLRDIVIDE :        str = "CONTROLRDIVIDE";
1490                                      break;
1491         case CONTROLTIMES :          str = "CONTROLTIMES";
1492                                      break;
1493         case DO :                    str = "DO";
1494                                      break;
1495         case DOLLAR :                str = "DOLLAR";
1496                                      break;
1497         case DOT :                   str = "DOT";
1498                                      break;
1499         case DOTLDIVIDE :            str = "DOTLDIVIDE";
1500                                      break;
1501         case DOTPOWER :              str = "DOTPOWER";
1502                                      break;
1503         case DOTQUOTE :              str = "DOTQUOTE";
1504                                      break;
1505         case DOTRDIVIDE :            str = "DOTRDIVIDE";
1506                                      break;
1507         case DOTS :                  str = "DOTS";
1508                                      break;
1509         case DOTTIMES :              str = "DOTTIMES";
1510                                      break;
1511         case ELSE :                  str = "ELSE";
1512                                      break;
1513         case ELSEIF :                str = "ELSEIF";
1514                                      break;
1515         case END :                   str = "END";
1516                                      break;
1517         case ENDFUNCTION :           str = "ENDFUNCTION";
1518                                      break;
1519         case EOL :                   str = "EOL";
1520                                      break;
1521         case EQ :                    str = "EQ";
1522                                      break;
1523         case FLEX_ERROR :            str = "FLEX_ERROR";
1524                                      break;
1525         case FOR :                   str = "FOR";
1526                                      break;
1527         case FUNCTION :              str = "FUNCTION";
1528                                      break;
1529         case GE :                    str = "GE";
1530                                      break;
1531         case GT :                    str = "GT";
1532                                      break;
1533         case ID :                    str = "ID";
1534                                      break;
1535         case IF :                    str = "IF";
1536                                      break;
1537         case KRONLDIVIDE :           str = "KRONLDIVIDE";
1538                                      break;
1539         case KRONRDIVIDE :           str = "KRONRDIVIDE";
1540                                      break;
1541         case KRONTIMES :             str = "KRONTIMES";
1542                                      break;
1543         case LBRACE :                str = "LBRACE";
1544                                      break;
1545         case LBRACK :                str = "LBRACK";
1546                                      break;
1547         case LDIVIDE :               str = "LDIVIDE";
1548                                      break;
1549         case LE :                    str = "LE";
1550                                      break;
1551         case LPAREN :                str = "LPAREN";
1552                                      break;
1553         case LT :                    str = "LT";
1554                                      break;
1555         case MINUS :                 str = "MINUS";
1556                                      break;
1557         case NE :                    str = "NE";
1558                                      break;
1559         case NOT :                   str = "NOT";
1560                                      break;
1561         case NUM :                   str = "NUM";
1562                                      break;
1563         case OR :                    str = "OR";
1564                                      break;
1565         case OROR :                  str = "OROR";
1566                                      break;
1567         case OTHERWISE :             str = "OTHERWISE";
1568                                      break;
1569         case PLUS :                  str = "PLUS";
1570                                      break;
1571         case POWER :                 str = "POWER";
1572                                      break;
1573         case QUOTE :                 str = "QUOTE";
1574                                      break;
1575         case RBRACE :                str = "RBRACE";
1576                                      break;
1577         case RBRACK :                str = "RBRACK";
1578                                      break;
1579         case RDIVIDE :               str = "RDIVIDE";
1580                                      break;
1581         case RETURN :                str = "RETURN";
1582                                      break;
1583         case RPAREN :                str = "RPAREN";
1584                                      break;
1585         case SELECT :                str = "SELECT";
1586                                      break;
1587         case SEMI :                  str = "SEMI";
1588                                      break;
1589         case SPACES :                str = "SPACES";
1590                                      break;
1591         case STR :                   str = "STR";
1592                                      break;
1593         case SWITCH :                str = "SWITCH";
1594                                      break;
1595         case THEN :                  str = "THEN";
1596                                      break;
1597         case TIMES :                 str = "TIMES";
1598                                      break;
1599         case TRY :                   str = "TRY";
1600                                      break;
1601         case VARFLOAT :              str = "VARFLOAT";
1602                                      break;
1603         case VARINT :                str = "VARINT";
1604                                      break;
1605         case WHILE :                 str = "WHILE";
1606                                      break;
1607         default :                    str = "UNKNOWN";
1608                                      break;
1609     }
1610     return str;
1611
1612 }
1613 #endif