Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / idlc / source / scanner.l
blob4c123ea8f0c331382ffa3c2c1d94095e3805478b
1 /*
2  * This file is part of the LibreOffice project.
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * This file incorporates work covered by the following license notice:
9  *
10  *   Licensed to the Apache Software Foundation (ASF) under one or more
11  *   contributor license agreements. See the NOTICE file distributed
12  *   with this work for additional information regarding copyright
13  *   ownership. The ASF licenses this file to you under the Apache
14  *   License, Version 2.0 (the "License"); you may not use this file
15  *   except in compliance with the License. You may obtain a copy of
16  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
17  */
19 %option yylineno
23  * scanner.ll - Lexical scanner for IDLC 1.0
24  */
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #ifndef _IDLC_IDLC_HXX_
31 #include <idlc/idlc.hxx>
32 #endif
33 #ifndef _IDLC_ERRORHANDLER_HXX_
34 #include <idlc/errorhandler.hxx>
35 #endif
36 #ifndef _IDLC_FEHELPER_HXX_
37 #include <idlc/fehelper.hxx>
38 #endif
40 #include "attributeexceptions.hxx"
43 class AstExpression;
44 class AstArray;
45 class AstMember;
47 #include <parser.hxx>
49 /* handle locations */
50 int yycolumn = 1;
52 #define YY_USER_ACTION idlc()->setOffset(yycolumn, yycolumn+yyleng-1); \
53     yycolumn += yyleng;
55 sal_Int32               beginLine = 0;
56 ::rtl::OString  docu;
58 static int asciiToInteger(char const * s, sal_Int64  * sval, sal_uInt64 * uval) {
59     bool neg = false;
60     if (*s == '-') {
61         neg = true;
62         ++s;
63     }
64     unsigned int base = 10;
65     if (*s == '0') {
66         base = 8;
67         ++s;
68         if (*s == 'X' || *s == 'x') {
69             base = 16;
70             ++s;
71         }
72     }
73     sal_uInt64 val = 0;
74     for (; *s != 0; ++s) {
75         unsigned int n;
76         if (*s >= '0' && *s <= '9') {
77             n = *s - '0';
78         } else {
79             switch (*s) {
80             case 'A':
81             case 'a':
82                 n = 10;
83                 break;
84             case 'B':
85             case 'b':
86                 n = 11;
87                 break;
88             case 'C':
89             case 'c':
90                 n = 12;
91                 break;
92             case 'D':
93             case 'd':
94                 n = 13;
95                 break;
96             case 'E':
97             case 'e':
98                 n = 14;
99                 break;
100             case 'F':
101             case 'f':
102                 n = 15;
103                 break;
104             default:
105                 goto done;
106             }
107         }
108         // The following guarantees the invariant val <= SAL_MAX_UINT64 (because
109         // base and n are sufficiently small), *if*
110         // std::numeric_limits<sal_uInt64>::max() == SAL_MAX_UINT64:
111         sal_uInt64 nval = val * base + n;
112         if (nval < val) {
113             idlc()->error()->syntaxError(
114                 PS_NoState, idlc()->getLineNumber(),
115                 "integral constant too large");
116             val = 0;
117             break;
118         }
119         val = nval;
120     }
121  done:
122     if (neg) {
123         if (val < SAL_CONST_UINT64(0x8000000000000000)) {
124             *sval = -static_cast< sal_Int64 >(val);
125         } else if (val == SAL_CONST_UINT64(0x8000000000000000)) {
126             *sval = SAL_MIN_INT64;
127         } else {
128             idlc()->error()->syntaxError(
129                 PS_NoState, idlc()->getLineNumber(),
130                 "negative integral constant too large");
131             *sval = 0;
132         }
133         return IDL_INTEGER_LITERAL;
134     } else if (val <= static_cast< sal_uInt64 >(SAL_MAX_INT64)) {
135         *sval = static_cast< sal_Int64 >(val);
136         return IDL_INTEGER_LITERAL;
137     } else {
138         *uval = val;
139         return IDL_INTEGER_ULITERAL;
140     }
143 static double asciiToFloat(const sal_Char *s)
145         double          d = 0.0;
146         double          e, k;
147         sal_Int32       neg = 0, negexp = 0;
149         if (*s == '-')
150         {
151         neg = 1;
152         s++;
153         }
154         while (*s >= '0' && *s <= '9')
155         {
156         d = (d * 10) + *s - '0';
157         s++;
158         }
159         if (*s == '.')
160         {
161         s++;
162         e = 10;
163         while (*s >= '0' && *s <= '9')
164         {
165                 d += (*s - '0') / (e * 1.0);
166                 e *= 10;
167                 s++;
168         }
169         }
170         if (*s == 'e' || *s == 'E')
171         {
172         s++;
173         if (*s == '-')
174         {
175                 negexp = 1;
176                 s++;
177         } else
178         {
179                 if (*s == '+')
180                 s++;
181                 e = 0;
182                 while (*s >= '0' && *s <= '9')
183                 {
184                 e = (e * 10) + *s - '0';
185                 s++;
186                 }
187                 if (e > 0)
188                 {
189                 for (k = 1; e > 0; k *= 10, e--)
190                     ;
191                 if (negexp)
192                         d /= k;
193                 else
194                         d *= k;
195                 }
196                 }
197         }
198         if (neg) d *= -1.0;
199         return d;
202 static void     idlParsePragma(sal_Char* pPragma)
204         ::rtl::OString pragma(pPragma);
205         sal_Int32 index = pragma.indexOf("include");
206         sal_Char* begin = pPragma + index + 8;
207         sal_Char* offset = begin;
208         while (*offset != ',') offset++;
209         //::rtl::OString include = pragma.copy(index + 8, offset - begin);
210         //unused// idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin)));
211 }       
213 static void parseLineAndFile(sal_Char* pBuf)
215         sal_Char        *r = pBuf;
216         sal_Char    *h;
217         sal_Bool        bIsInMain = sal_False;
219         /* Skip initial '#' */
220         if (*r != '#')
221                 return;
223         /* Find line number */
224         for (r++; *r == ' ' || *r == '\t' || isalpha(*r); r++) ;
225         h = r;
226         for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ;
227         *r++ = 0;
228         idlc()->setLineNumber((sal_uInt32)atol(h));
229     yylineno = atol(h);
231         /* Find file name, if present */
232         for (; *r != '"'; r++)
233         {
234                 if (*r == '\n' || *r == '\0')
235                         return;
236         }
237         h = ++r;
238         for (; *r != '"'; r++) ;
239         *r = 0;
240         if (*h == '\0')
241                 idlc()->setFileName(::rtl::OString("standard input"));
242         else
243                 idlc()->setFileName(::rtl::OString(h));
245         bIsInMain = (idlc()->getFileName() == idlc()->getRealFileName()) ? sal_True : sal_False;
246         idlc()->setInMainfile(bIsInMain);               
247 }       
249 // Suppress any warnings from generated code:
250 #if defined __GNUC__
251 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
252 #pragma GCC diagnostic ignored "-Wunused-function"
253 #pragma GCC diagnostic ignored "-Wunused-label"
254 #endif
255 #elif defined __SUNPRO_CC
256 #pragma disable_warn
257 #elif defined _MSC_VER
258 #pragma warning(push, 1)
259 /**/
260 #ifdef yywrap
261 #undef  yywrap
262 #define yywrap() 1
263 #endif
264 /**/
265 #endif
268 %option noyywrap
269 %option never-interactive
271 %x DOCU
272 %x COMMENT
274 DIGIT           [0-9]
275 OCT_DIGIT       [0-7]
276 HEX_DIGIT       [a-fA-F0-9]
277 CAPITAL         [A-Z]
278 ALPHA           [a-zA-Z]
279 INT_LITERAL     [1-9][0-9]*
280 OCT_LITERAL     0{OCT_DIGIT}*
281 HEX_LITERAL     (0x|0X){HEX_DIGIT}*
283 IDENTIFIER_NEW  ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*)
284 IDENTIFIER      ("_"?({ALPHA}|{DIGIT})+)*
288 [ \t\r]+        ; /* eat up whitespace */
289 [\n]           {
290        idlc()->incLineNumber();
291        yycolumn = 1;
292        yylineno++;
295 attribute       return IDL_ATTRIBUTE;
296 bound           return IDL_BOUND;
297 case            return IDL_CASE;
298 const           return IDL_CONST;
299 constants       return IDL_CONSTANTS;
300 constrained     return IDL_CONSTRAINED;
301 default         return IDL_DEFAULT;
302 enum            return IDL_ENUM;
303 exception       return IDL_EXCEPTION;
304 interface       return IDL_INTERFACE;
305 maybeambiguous  return IDL_MAYBEAMBIGUOUS;
306 maybedefault    return IDL_MAYBEDEFAULT;
307 maybevoid       return IDL_MAYBEVOID;
308 module          return IDL_MODULE;
309 needs           return IDL_NEEDS;
310 observes        return IDL_OBSERVES;
311 optional        return IDL_OPTIONAL;
312 property        return IDL_PROPERTY;
313 raises          return IDL_RAISES;
314 readonly        return IDL_READONLY;
315 removable       return IDL_REMOVEABLE;
316 service         return IDL_SERVICE;
317 sequence        return IDL_SEQUENCE;
318 singleton       return IDL_SINGLETON;
319 struct          return IDL_STRUCT;
320 switch          return IDL_SWITCH;
321 transient       return IDL_TRANSIENT;
322 typedef         return IDL_TYPEDEF;
323 union           return IDL_UNION;
325 any             return IDL_ANY;                         
326 boolean         return IDL_BOOLEAN;
327 byte            return IDL_BYTE;
328 char            return IDL_CHAR;
329 double          return IDL_DOUBLE;
330 float           return IDL_FLOAT;
331 hyper           return IDL_HYPER;
332 long            return IDL_LONG;
333 short           return IDL_SHORT;
334 string          return IDL_STRING;
335 type            return IDL_TYPE;
336 unsigned        return IDL_UNSIGNED;
337 void            return IDL_VOID;
339 TRUE            return IDL_TRUE;
340 True            return IDL_TRUE;
341 FALSE           return IDL_FALSE;
342 False           return IDL_FALSE;
344 in              return IDL_IN;
345 out             return IDL_OUT;
346 inout           return IDL_INOUT;
348 get             return IDL_GET;
349 set             return IDL_SET;
351 published       return IDL_PUBLISHED;
353 "..."           return IDL_ELLIPSIS;
355 ("-")?{INT_LITERAL}+(l|L|u|U)?    {
356                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
357             }
359 ("-")?{OCT_LITERAL}+(l|L|u|U)?    {
360                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
361             }
363 ("-")?{HEX_LITERAL}+(l|L|u|U)?    {
364                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
365             }
367 ("-")?{DIGIT}+(e|E){1}(("+"|"-")?{DIGIT}+)+(f|F)?       |
368 ("-")?"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?       |
369 ("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?        {
370                 yylval.dval = asciiToFloat( yytext );
371                                 return IDL_FLOATING_PT_LITERAL;
372             }
374 {IDENTIFIER}    {
375                                 yylval.sval = new ::rtl::OString(yytext);
376                                 return IDL_IDENTIFIER;
377                         }
379 \<\<    {
380                 yylval.strval = yytext;
381                 return IDL_LEFTSHIFT;
382         }
383 \>\>    {
384                 yylval.strval = yytext;
385                 return IDL_RIGHTSHIFT;
386         }
387 \:\:    {
388                 yylval.strval = yytext;
389                 return IDL_SCOPESEPARATOR;
390         }
392 "/*"    { 
393                         BEGIN( COMMENT );
394                         docu = ::rtl::OString();
395                         beginLine = idlc()->getLineNumber();
396                 }
398 "/***"  { 
399                         BEGIN( COMMENT );
400                         docu = ::rtl::OString();
401                         beginLine = idlc()->getLineNumber();
402                 }
404 <COMMENT>[^*]+  {
405                                 docu += ::rtl::OString(yytext);
406                         } 
408 <COMMENT>"*"[^*/]+      {
409                                 docu += ::rtl::OString(yytext);
410                         }
412 <COMMENT>"**"   {
413                                 docu += ::rtl::OString(yytext);
414                         }
416 <COMMENT>[*]+"/"  {
417                                 docu = docu.trim();
418                 sal_Int32 nIndex = 0;
419                 int count = 0;
420                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
421                                 idlc()->setLineNumber( beginLine + count - 1);
422                                 BEGIN( INITIAL );
423                         }
425 "/**"   {
426                         BEGIN( DOCU );
427                         docu = ::rtl::OString();
428                         beginLine = idlc()->getLineNumber();
429                 }
431 <DOCU>[^*\n]+   {
432                                 docu += ::rtl::OString(yytext);
433                         }
435 <DOCU>"\n"[ \t]*"*"{1}  {
436                                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
437                                 docu += ::rtl::OString("\n");
438                         }
440 <DOCU>"\n"      {
441                                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
442                                 docu += ::rtl::OString(yytext);
443                         }
445 <DOCU>"*"[^*^/\n]*      {
446                                 docu += ::rtl::OString(yytext);
447                         }
449 <DOCU>"\n"[ \t]*"*/"    {
450                                 docu = docu.trim();
451                                 sal_Int32 nIndex = 0;
452                                 int count = 0;
453                                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
454                                 idlc()->setLineNumber( beginLine + count - 1);                
455                                 if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 )
456                                 {
457                     if ( 0 != nIndex &&
458                          (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
459                         idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
460                                                      "nested documentation strings are not allowed!");
461                                 }
462                                 idlc()->setDocumentation(docu);
463                                 BEGIN( INITIAL );
464                         }
466 <DOCU>"*/"      {
467                                 docu = docu.trim();
468                                 sal_Int32 nIndex = 0;
469                                 int count = 0;
470                                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
471                                 idlc()->setLineNumber( beginLine + count - 1);
472                                 if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 )
473                                 {
474                     if ( 0 != nIndex &&
475                          (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
476                         idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
477                                                      "nested documentation strings are not allowed!");
478                                 }
479                                 idlc()->setDocumentation(docu);
480                                 BEGIN( INITIAL );
481                         }
483 "//"[^/]{1}.*"\n" {
484                                 /* only a comment */
485                                 ::rtl::OString docStr(yytext);
486                                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
487                                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
488                                 docStr = docStr.trim();
489                                 idlc()->incLineNumber();
490                         }
492 "///".*"\n"  {
493                                 ::rtl::OString docStr(yytext);
494                                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
495                                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
496                                 docStr = docStr.trim();
497                                 idlc()->incLineNumber();
498                                 idlc()->setDocumentation(docStr);
499                         }
501 .       return yytext[0];
503 ^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n    {
504         parseLineAndFile(yytext);
507 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n {
508         parseLineAndFile(yytext);
511 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
512         parseLineAndFile(yytext);
515 ^#[ \t]*[0-9]*\n {
516         parseLineAndFile(yytext);
519 ^#[ \t]*ident.*\n {
520         /* ignore cpp ident */
521         idlc()->incLineNumber();
524 ^#[ \t]*pragma[ \t].*\n        {       /* remember pragma */
525         idlParsePragma(yytext);
526         idlc()->incLineNumber();