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