update dev300-m58
[ooovba.git] / idlc / source / scanner.ll
blob74f5c82fded166baed6a403571d2d3989f51fb4d
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  * 
5  * Copyright 2008 by Sun Microsystems, Inc.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * $RCSfile: scanner.ll,v $
10  * $Revision: 1.16.16.1 $
11  *
12  * This file is part of OpenOffice.org.
13  *
14  * OpenOffice.org is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU Lesser General Public License version 3
16  * only, as published by the Free Software Foundation.
17  *
18  * OpenOffice.org is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU Lesser General Public License version 3 for more details
22  * (a copy is included in the LICENSE file that accompanied this code).
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * version 3 along with OpenOffice.org.  If not, see
26  * <http://www.openoffice.org/license.html>
27  * for a copy of the LGPLv3 License.
28  *
29  ************************************************************************/
33  * scanner.ll - Lexical scanner for IDLC 1.0
34  */
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <string.h>
40 #ifndef _IDLC_IDLC_HXX_
41 #include <idlc/idlc.hxx>
42 #endif
43 #ifndef _IDLC_ERRORHANDLER_HXX_
44 #include <idlc/errorhandler.hxx>
45 #endif
46 #ifndef _IDLC_FEHELPER_HXX_
47 #include <idlc/fehelper.hxx>
48 #endif
50 #include "attributeexceptions.hxx"
52 class AstExpression;
53 class AstArray;
54 class AstMember;
56 #include <parser.hxx>
58 sal_Int32               beginLine = 0;
59 ::rtl::OString  docu;
61 static int asciiToInteger(char const * s, sal_Int64  * sval, sal_uInt64 * uval) {
62     bool neg = false;
63     if (*s == '-') {
64         neg = true;
65         ++s;
66     }
67     unsigned int base = 10;
68     if (*s == '0') {
69         base = 8;
70         ++s;
71         if (*s == 'X' || *s == 'x') {
72             base = 16;
73             ++s;
74         }
75     }
76     sal_uInt64 val = 0;
77     for (; *s != 0; ++s) {
78         unsigned int n;
79         if (*s >= '0' && *s <= '9') {
80             n = *s - '0';
81         } else {
82             switch (*s) {
83             case 'A':
84             case 'a':
85                 n = 10;
86                 break;
87             case 'B':
88             case 'b':
89                 n = 11;
90                 break;
91             case 'C':
92             case 'c':
93                 n = 12;
94                 break;
95             case 'D':
96             case 'd':
97                 n = 13;
98                 break;
99             case 'E':
100             case 'e':
101                 n = 14;
102                 break;
103             case 'F':
104             case 'f':
105                 n = 15;
106                 break;
107             default:
108                 goto done;
109             }
110         }
111         // The following guarantees the invariant val <= SAL_MAX_UINT64 (because
112         // base and n are sufficiently small), *if*
113         // std::numeric_limits<sal_uInt64>::max() == SAL_MAX_UINT64:
114         sal_uInt64 nval = val * base + n;
115         if (nval < val) {
116             idlc()->error()->syntaxError(
117                 PS_NoState, idlc()->getLineNumber(),
118                 "integral constant too large");
119             val = 0;
120             break;
121         }
122         val = nval;
123     }
124  done:
125     if (neg) {
126         if (val < SAL_CONST_UINT64(0x8000000000000000)) {
127             *sval = -static_cast< sal_Int64 >(val);
128         } else if (val == SAL_CONST_UINT64(0x8000000000000000)) {
129             *sval = SAL_MIN_INT64;
130         } else {
131             idlc()->error()->syntaxError(
132                 PS_NoState, idlc()->getLineNumber(),
133                 "negative integral constant too large");
134             *sval = 0;
135         }
136         return IDL_INTEGER_LITERAL;
137     } else if (val <= static_cast< sal_uInt64 >(SAL_MAX_INT64)) {
138         *sval = static_cast< sal_Int64 >(val);
139         return IDL_INTEGER_LITERAL;
140     } else {
141         *uval = val;
142         return IDL_INTEGER_ULITERAL;
143     }
146 static double asciiToFloat(const sal_Char *s)
148         double          d = 0.0;
149         double          e, k;
150         sal_Int32       neg = 0, negexp = 0;
152         if (*s == '-')
153         {
154         neg = 1;
155         s++;
156         }
157         while (*s >= '0' && *s <= '9')
158         {
159         d = (d * 10) + *s - '0';
160         s++;
161         }
162         if (*s == '.')
163         {
164         s++;
165         e = 10;
166         while (*s >= '0' && *s <= '9')
167         {
168                 d += (*s - '0') / (e * 1.0);
169                 e *= 10;
170                 s++;
171         }
172         }
173         if (*s == 'e' || *s == 'E')
174         {
175         s++;
176         if (*s == '-')
177         {
178                 negexp = 1;
179                 s++;
180         } else
181         {
182                 if (*s == '+')
183                 s++;
184                 e = 0;
185                 while (*s >= '0' && *s <= '9')
186                 {
187                 e = (e * 10) + *s - '0';
188                 s++;
189                 }
190                 if (e > 0)
191                 {
192                 for (k = 1; e > 0; k *= 10, e--) ;
193                 if (negexp)
194                         d /= k;
195                 else
196                         d *= k;
197                 }
198                 }
199         }
200         if (neg) d *= -1.0;
201         return d;
204 static void     idlParsePragma(sal_Char* pPragma)
206         ::rtl::OString pragma(pPragma);
207         sal_Int32 index = pragma.indexOf("include");
208         sal_Char* begin = pPragma + index + 8;
209         sal_Char* offset = begin;
210         while (*offset != ',') offset++;
211         //::rtl::OString include = pragma.copy(index + 8, offset - begin);
212         idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin)));
213 }       
215 static void parseLineAndFile(sal_Char* pBuf)
217         sal_Char        *r = pBuf;
218         sal_Char    *h;
219         sal_Bool        bIsInMain = sal_False;
221         /* Skip initial '#' */
222         if (*r != '#')
223                 return;
225         /* Find line number */
226         for (r++; *r == ' ' || *r == '\t' || isalpha(*r); r++) ;
227         h = r;
228         for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ;
229         *r++ = 0;
230         idlc()->setLineNumber((sal_uInt32)atol(h));
232         /* Find file name, if present */
233         for (; *r != '"'; r++)
234         {
235                 if (*r == '\n' || *r == '\0')
236                         return;
237         }
238         h = ++r;
239         for (; *r != '"'; r++) ;
240         *r = 0;
241         if (*h == '\0')
242                 idlc()->setFileName(::rtl::OString("standard input"));
243         else
244                 idlc()->setFileName(::rtl::OString(h));
246         bIsInMain = (idlc()->getFileName() == idlc()->getRealFileName()) ? sal_True : sal_False;
247         idlc()->setInMainfile(bIsInMain);               
248 }       
250 // Suppress any warnings from generated code:
251 #if defined __GNUC__
252 #pragma GCC system_header
253 #elif defined __SUNPRO_CC
254 #pragma disable_warn
255 #elif defined _MSC_VER
256 #pragma warning(push, 1)
257 /**/
258 #ifdef yywrap
259 #undef  yywrap
260 #define yywrap() 1
261 #endif
262 /**/
263 #endif
266 %option noyywrap
267 %option never-interactive
269 %x DOCU
270 %x COMMENT
272 DIGIT           [0-9]
273 OCT_DIGIT       [0-7]
274 HEX_DIGIT       [a-fA-F0-9]
275 CAPITAL         [A-Z]
276 ALPHA           [a-zA-Z]
277 INT_LITERAL     [1-9][0-9]*
278 OCT_LITERAL     0{OCT_DIGIT}*
279 HEX_LITERAL     (0x|0X){HEX_DIGIT}*
281 IDENTIFIER_NEW  ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*)
282 IDENTIFIER      ("_"?({ALPHA}|{DIGIT})+)*
286 [ \t\r]+        ; /* eat up whitespace */
287 [\n]            {
288         idlc()->incLineNumber();
291 attribute       return IDL_ATTRIBUTE;
292 bound           return IDL_BOUND;
293 case            return IDL_CASE;
294 const           return IDL_CONST;
295 constants       return IDL_CONSTANTS;
296 constrained     return IDL_CONSTRAINED;
297 default         return IDL_DEFAULT;
298 enum            return IDL_ENUM;
299 exception       return IDL_EXCEPTION;
300 interface       return IDL_INTERFACE;
301 maybeambiguous  return IDL_MAYBEAMBIGUOUS;
302 maybedefault    return IDL_MAYBEDEFAULT;
303 maybevoid       return IDL_MAYBEVOID;
304 module          return IDL_MODULE;
305 needs           return IDL_NEEDS;
306 observes        return IDL_OBSERVES;
307 optional        return IDL_OPTIONAL;
308 property        return IDL_PROPERTY;
309 raises          return IDL_RAISES;
310 readonly        return IDL_READONLY;
311 removable       return IDL_REMOVEABLE;
312 service         return IDL_SERVICE;
313 sequence        return IDL_SEQUENCE;
314 singleton       return IDL_SINGLETON;
315 struct          return IDL_STRUCT;
316 switch          return IDL_SWITCH;
317 transient       return IDL_TRANSIENT;
318 typedef         return IDL_TYPEDEF;
319 union           return IDL_UNION;
321 any             return IDL_ANY;                         
322 boolean         return IDL_BOOLEAN;
323 byte            return IDL_BYTE;
324 char            return IDL_CHAR;
325 double          return IDL_DOUBLE;
326 float           return IDL_FLOAT;
327 hyper           return IDL_HYPER;
328 long            return IDL_LONG;
329 short           return IDL_SHORT;
330 string          return IDL_STRING;
331 type            return IDL_TYPE;
332 unsigned        return IDL_UNSIGNED;
333 void            return IDL_VOID;
335 TRUE            return IDL_TRUE;
336 True            return IDL_TRUE;
337 FALSE           return IDL_FALSE;
338 False           return IDL_FALSE;
340 in              return IDL_IN;
341 out             return IDL_OUT;
342 inout           return IDL_INOUT;
343 oneway          return IDL_ONEWAY;
345 get             return IDL_GET;
346 set             return IDL_SET;
348 published       return IDL_PUBLISHED;
350 "..."           return IDL_ELLIPSIS;
352 ("-")?{INT_LITERAL}+(l|L|u|U)?    {
353                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
354             }
356 ("-")?{OCT_LITERAL}+(l|L|u|U)?    {
357                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
358             }
360 ("-")?{HEX_LITERAL}+(l|L|u|U)?    {
361                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
362             }
364 ("-")?{DIGIT}+(e|E){1}(("+"|"-")?{DIGIT}+)+(f|F)?       |
365 ("-")?"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?       |
366 ("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?        {
367                 yylval.dval = asciiToFloat( yytext );
368                                 return IDL_FLOATING_PT_LITERAL;
369             }
371 {IDENTIFIER}    {
372                                 yylval.sval = new ::rtl::OString(yytext);
373                                 return IDL_IDENTIFIER;
374                         }
376 \<\<    {
377                 yylval.strval = yytext;
378                 return IDL_LEFTSHIFT;
379         }
380 \>\>    {
381                 yylval.strval = yytext;
382                 return IDL_RIGHTSHIFT;
383         }
384 \:\:    {
385                 yylval.strval = yytext;
386                 return IDL_SCOPESEPARATOR;
387         }
389 "/*"    { 
390                         BEGIN( COMMENT );
391                         docu = ::rtl::OString();
392                         beginLine = idlc()->getLineNumber();
393                 }
395 "/***"  { 
396                         BEGIN( COMMENT );
397                         docu = ::rtl::OString();
398                         beginLine = idlc()->getLineNumber();
399                 }
401 <COMMENT>[^*]+  {
402                                 docu += ::rtl::OString(yytext);
403                         } 
405 <COMMENT>"*"[^*/]+      {
406                                 docu += ::rtl::OString(yytext);
407                         }
409 <COMMENT>"**"   {
410                                 docu += ::rtl::OString(yytext);
411                         }
413 <COMMENT>[*]+"/"  {
414                                 docu = docu.trim();
415                 sal_Int32 nIndex = 0;
416                 int count = 0;
417                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
418                                 idlc()->setLineNumber( beginLine + count - 1);
419                                 BEGIN( INITIAL );
420                         }
422 "/**"   {
423                         BEGIN( DOCU );
424                         docu = ::rtl::OString();
425                         beginLine = idlc()->getLineNumber();
426                 }
428 <DOCU>[^*\n]+   {
429                                 docu += ::rtl::OString(yytext);
430                         }
432 <DOCU>"\n"[ \t]*"*"{1}  {
433                                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
434                                 docu += ::rtl::OString("\n");
435                         }
437 <DOCU>"\n"      {
438                                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
439                                 docu += ::rtl::OString(yytext);
440                         }
442 <DOCU>"*"[^*^/\n]*      {
443                                 docu += ::rtl::OString(yytext);
444                         }
446 <DOCU>"\n"[ \t]*"*/"    {
447                                 docu = docu.trim();
448                                 sal_Int32 nIndex = 0;
449                                 int count = 0;
450                                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
451                                 idlc()->setLineNumber( beginLine + count - 1);                
452                                 if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 )
453                                 {
454                     if ( 0 != nIndex &&
455                          (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
456                         idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
457                                                      "nested documentation strings are not allowed!");
458                                 }
459                                 idlc()->setDocumentation(docu);
460                                 BEGIN( INITIAL );
461                         }
463 <DOCU>"*/"      {
464                                 docu = docu.trim();
465                                 sal_Int32 nIndex = 0;
466                                 int count = 0;
467                                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
468                                 idlc()->setLineNumber( beginLine + count - 1);
469                                 if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 )
470                                 {
471                     if ( 0 != nIndex &&
472                          (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
473                         idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
474                                                      "nested documentation strings are not allowed!");
475                                 }
476                                 idlc()->setDocumentation(docu);
477                                 BEGIN( INITIAL );
478                         }
480 "//"[^/]{1}.*"\n" {
481                                 /* only a comment */
482                                 ::rtl::OString docStr(yytext);
483                                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
484                                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
485                                 docStr = docStr.trim();
486                                 idlc()->incLineNumber();
487                         }
489 "///".*"\n"  {
490                                 ::rtl::OString docStr(yytext);
491                                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
492                                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
493                                 docStr = docStr.trim();
494                                 idlc()->incLineNumber();
495                                 idlc()->setDocumentation(docStr);
496                         }
498 .       return yytext[0];
500 ^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n    {
501         parseLineAndFile(yytext);
504 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n {
505         parseLineAndFile(yytext);
508 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
509         parseLineAndFile(yytext);
512 ^#[ \t]*[0-9]*\n {
513         parseLineAndFile(yytext);
516 ^#[ \t]*ident.*\n {
517         /* ignore cpp ident */
518         idlc()->incLineNumber();
521 ^#[ \t]*pragma[ \t].*\n        {       /* remember pragma */
522         idlParsePragma(yytext);
523         idlc()->incLineNumber();