update credits
[LibreOffice.git] / idlc / source / scanner.l
blob51204b8ade462750c62521e3890c6816c2560957
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 "sal/config.h"
28 #include <ctype.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include <idlc/idlc.hxx>
33 #include <idlc/errorhandler.hxx>
34 #include <idlc/fehelper.hxx>
36 #include "attributeexceptions.hxx"
39 class AstExpression;
40 class AstArray;
41 class AstMember;
43 #include <parser.hxx>
45 /* handle locations */
46 int yycolumn = 1;
48 #define YY_USER_ACTION idlc()->setOffset(yycolumn, yycolumn+yyleng-1); \
49     yycolumn += yyleng;
51 sal_Int32               beginLine = 0;
52 ::rtl::OString  docu;
54 static int asciiToInteger(char const * s, sal_Int64  * sval, sal_uInt64 * uval) {
55     bool neg = false;
56     if (*s == '-') {
57         neg = true;
58         ++s;
59     }
60     unsigned int base = 10;
61     if (*s == '0') {
62         base = 8;
63         ++s;
64         if (*s == 'X' || *s == 'x') {
65             base = 16;
66             ++s;
67         }
68     }
69     sal_uInt64 val = 0;
70     for (; *s != 0; ++s) {
71         unsigned int n;
72         if (*s >= '0' && *s <= '9') {
73             n = *s - '0';
74         } else {
75             switch (*s) {
76             case 'A':
77             case 'a':
78                 n = 10;
79                 break;
80             case 'B':
81             case 'b':
82                 n = 11;
83                 break;
84             case 'C':
85             case 'c':
86                 n = 12;
87                 break;
88             case 'D':
89             case 'd':
90                 n = 13;
91                 break;
92             case 'E':
93             case 'e':
94                 n = 14;
95                 break;
96             case 'F':
97             case 'f':
98                 n = 15;
99                 break;
100             default:
101                 goto done;
102             }
103         }
104         // The following guarantees the invariant val <= SAL_MAX_UINT64 (because
105         // base and n are sufficiently small), *if*
106         // std::numeric_limits<sal_uInt64>::max() == SAL_MAX_UINT64:
107         sal_uInt64 nval = val * base + n;
108         if (nval < val) {
109             idlc()->error()->syntaxError(
110                 PS_NoState, idlc()->getLineNumber(),
111                 "integral constant too large");
112             val = 0;
113             break;
114         }
115         val = nval;
116     }
117  done:
118     if (neg) {
119         if (val < SAL_CONST_UINT64(0x8000000000000000)) {
120             *sval = -static_cast< sal_Int64 >(val);
121         } else if (val == SAL_CONST_UINT64(0x8000000000000000)) {
122             *sval = SAL_MIN_INT64;
123         } else {
124             idlc()->error()->syntaxError(
125                 PS_NoState, idlc()->getLineNumber(),
126                 "negative integral constant too large");
127             *sval = 0;
128         }
129         return IDL_INTEGER_LITERAL;
130     } else if (val <= static_cast< sal_uInt64 >(SAL_MAX_INT64)) {
131         *sval = static_cast< sal_Int64 >(val);
132         return IDL_INTEGER_LITERAL;
133     } else {
134         *uval = val;
135         return IDL_INTEGER_ULITERAL;
136     }
139 static double asciiToFloat(const sal_Char *s)
141         double          d = 0.0;
142         double          e, k;
143         sal_Int32       neg = 0, negexp = 0;
145         if (*s == '-')
146         {
147         neg = 1;
148         s++;
149         }
150         while (*s >= '0' && *s <= '9')
151         {
152         d = (d * 10) + *s - '0';
153         s++;
154         }
155         if (*s == '.')
156         {
157         s++;
158         e = 10;
159         while (*s >= '0' && *s <= '9')
160         {
161                 d += (*s - '0') / (e * 1.0);
162                 e *= 10;
163                 s++;
164         }
165         }
166         if (*s == 'e' || *s == 'E')
167         {
168         s++;
169         if (*s == '-')
170         {
171                 negexp = 1;
172                 s++;
173         } else
174         {
175                 if (*s == '+')
176                 s++;
177                 e = 0;
178                 while (*s >= '0' && *s <= '9')
179                 {
180                 e = (e * 10) + *s - '0';
181                 s++;
182                 }
183                 if (e > 0)
184                 {
185                 for (k = 1; e > 0; k *= 10, e--)
186                     ;
187                 if (negexp)
188                         d /= k;
189                 else
190                         d *= k;
191                 }
192                 }
193         }
194         if (neg) d *= -1.0;
195         return d;
198 static void     idlParsePragma(sal_Char* pPragma)
200         ::rtl::OString pragma(pPragma);
201         sal_Int32 index = pragma.indexOf("include");
202         sal_Char* begin = pPragma + index + 8;
203         sal_Char* offset = begin;
204         while (*offset != ',') offset++;
205         //::rtl::OString include = pragma.copy(index + 8, offset - begin);
206         //unused// idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin)));
207 }       
209 static void parseLineAndFile(sal_Char* pBuf)
211         sal_Char        *r = pBuf;
212         sal_Char    *h;
213         sal_Bool        bIsInMain = sal_False;
215         /* Skip initial '#' */
216         if (*r != '#')
217                 return;
219         /* Find line number */
220         for (r++; *r == ' ' || *r == '\t' || isalpha(*r); r++) ;
221         h = r;
222         for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ;
223         *r++ = 0;
224         idlc()->setLineNumber((sal_uInt32)atol(h));
225     yylineno = atol(h);
227         /* Find file name, if present */
228         for (; *r != '"'; r++)
229         {
230                 if (*r == '\n' || *r == '\0')
231                         return;
232         }
233         h = ++r;
234         for (; *r != '"'; r++) ;
235         *r = 0;
236         if (*h == '\0')
237                 idlc()->setFileName(::rtl::OString("standard input"));
238         else
239                 idlc()->setFileName(::rtl::OString(h));
241         bIsInMain = (idlc()->getFileName() == idlc()->getRealFileName()) ? sal_True : sal_False;
242         idlc()->setInMainfile(bIsInMain);               
243 }       
245 // Suppress any warnings from generated code:
246 #if HAVE_GCC_PRAGMA_DIAGNOSTIC_MODIFY
247 #pragma GCC diagnostic ignored "-Wunused-function"
248 #pragma GCC diagnostic ignored "-Wunused-label"
249 #elif defined __SUNPRO_CC
250 #pragma disable_warn
251 #elif defined _MSC_VER
252 #pragma warning(push, 1)
253 /**/
254 #ifdef yywrap
255 #undef  yywrap
256 #define yywrap() 1
257 #endif
258 /**/
259 #endif
260 #define YY_NO_UNISTD_H
263 %option noyywrap
264 %option never-interactive
266 %x DOCU
267 %x COMMENT
269 DIGIT           [0-9]
270 OCT_DIGIT       [0-7]
271 HEX_DIGIT       [a-fA-F0-9]
272 CAPITAL         [A-Z]
273 ALPHA           [a-zA-Z]
274 INT_LITERAL     [1-9][0-9]*
275 OCT_LITERAL     0{OCT_DIGIT}*
276 HEX_LITERAL     (0x|0X){HEX_DIGIT}*
278 IDENTIFIER_NEW  ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*)
279 IDENTIFIER      ("_"?({ALPHA}|{DIGIT})+)*
283 [ \t\r]+        ; /* eat up whitespace */
284 [\n]           {
285        idlc()->incLineNumber();
286        yycolumn = 1;
287        yylineno++;
290 attribute       return IDL_ATTRIBUTE;
291 bound           return IDL_BOUND;
292 case            return IDL_CASE;
293 const           return IDL_CONST;
294 constants       return IDL_CONSTANTS;
295 constrained     return IDL_CONSTRAINED;
296 default         return IDL_DEFAULT;
297 enum            return IDL_ENUM;
298 exception       return IDL_EXCEPTION;
299 interface       return IDL_INTERFACE;
300 maybeambiguous  return IDL_MAYBEAMBIGUOUS;
301 maybedefault    return IDL_MAYBEDEFAULT;
302 maybevoid       return IDL_MAYBEVOID;
303 module          return IDL_MODULE;
304 needs           return IDL_NEEDS;
305 observes        return IDL_OBSERVES;
306 optional        return IDL_OPTIONAL;
307 property        return IDL_PROPERTY;
308 raises          return IDL_RAISES;
309 readonly        return IDL_READONLY;
310 removable       return IDL_REMOVEABLE;
311 service         return IDL_SERVICE;
312 sequence        return IDL_SEQUENCE;
313 singleton       return IDL_SINGLETON;
314 struct          return IDL_STRUCT;
315 switch          return IDL_SWITCH;
316 transient       return IDL_TRANSIENT;
317 typedef         return IDL_TYPEDEF;
318 union           return IDL_UNION;
320 any             return IDL_ANY;                         
321 boolean         return IDL_BOOLEAN;
322 byte            return IDL_BYTE;
323 char            return IDL_CHAR;
324 double          return IDL_DOUBLE;
325 float           return IDL_FLOAT;
326 hyper           return IDL_HYPER;
327 long            return IDL_LONG;
328 short           return IDL_SHORT;
329 string          return IDL_STRING;
330 type            return IDL_TYPE;
331 unsigned        return IDL_UNSIGNED;
332 void            return IDL_VOID;
334 TRUE            return IDL_TRUE;
335 True            return IDL_TRUE;
336 FALSE           return IDL_FALSE;
337 False           return IDL_FALSE;
339 in              return IDL_IN;
340 out             return IDL_OUT;
341 inout           return IDL_INOUT;
343 get             return IDL_GET;
344 set             return IDL_SET;
346 published       return IDL_PUBLISHED;
348 "..."           return IDL_ELLIPSIS;
350 ("-")?{INT_LITERAL}+(l|L|u|U)?    {
351                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
352             }
354 ("-")?{OCT_LITERAL}+(l|L|u|U)?    {
355                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
356             }
358 ("-")?{HEX_LITERAL}+(l|L|u|U)?    {
359                 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
360             }
362 ("-")?{DIGIT}+(e|E){1}(("+"|"-")?{DIGIT}+)+(f|F)?       |
363 ("-")?"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?       |
364 ("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?        {
365                 yylval.dval = asciiToFloat( yytext );
366                                 return IDL_FLOATING_PT_LITERAL;
367             }
369 {IDENTIFIER}    {
370                                 yylval.sval = new ::rtl::OString(yytext);
371                                 return IDL_IDENTIFIER;
372                         }
374 \<\<    {
375                 yylval.strval = yytext;
376                 return IDL_LEFTSHIFT;
377         }
378 \>\>    {
379                 yylval.strval = yytext;
380                 return IDL_RIGHTSHIFT;
381         }
382 \:\:    {
383                 yylval.strval = yytext;
384                 return IDL_SCOPESEPARATOR;
385         }
387 "/*"    { 
388                         BEGIN( COMMENT );
389                         docu = ::rtl::OString();
390                         beginLine = idlc()->getLineNumber();
391                 }
393 "/***"  { 
394                         BEGIN( COMMENT );
395                         docu = ::rtl::OString();
396                         beginLine = idlc()->getLineNumber();
397                 }
399 <COMMENT>[^*]+  {
400                                 docu += ::rtl::OString(yytext);
401                         } 
403 <COMMENT>"*"[^*/]+      {
404                                 docu += ::rtl::OString(yytext);
405                         }
407 <COMMENT>"**"   {
408                                 docu += ::rtl::OString(yytext);
409                         }
411 <COMMENT>[*]+"/"  {
412                                 docu = docu.trim();
413                 sal_Int32 nIndex = 0;
414                 int count = 0;
415                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
416                                 idlc()->setLineNumber( beginLine + count - 1);
417                                 BEGIN( INITIAL );
418                         }
420 "/**"   {
421                         BEGIN( DOCU );
422                         docu = ::rtl::OString();
423                         beginLine = idlc()->getLineNumber();
424                 }
426 <DOCU>[^*\n]+   {
427                                 docu += ::rtl::OString(yytext);
428                         }
430 <DOCU>"\n"[ \t]*"*"{1}  {
431                                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
432                                 docu += ::rtl::OString("\n");
433                         }
435 <DOCU>"\n"      {
436                                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
437                                 docu += ::rtl::OString(yytext);
438                         }
440 <DOCU>"*"[^*^/\n]*      {
441                                 docu += ::rtl::OString(yytext);
442                         }
444 <DOCU>"\n"[ \t]*"*/"    {
445                                 docu = docu.trim();
446                                 sal_Int32 nIndex = 0;
447                                 int count = 0;
448                                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
449                                 idlc()->setLineNumber( beginLine + count - 1);                
450                                 if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 )
451                                 {
452                     if ( 0 != nIndex &&
453                          (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
454                         idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
455                                                      "nested documentation strings are not allowed!");
456                                 }
457                                 idlc()->setDocumentation(docu);
458                                 BEGIN( INITIAL );
459                         }
461 <DOCU>"*/"      {
462                                 docu = docu.trim();
463                                 sal_Int32 nIndex = 0;
464                                 int count = 0;
465                                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
466                                 idlc()->setLineNumber( beginLine + count - 1);
467                                 if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 )
468                                 {
469                     if ( 0 != nIndex &&
470                          (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
471                         idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
472                                                      "nested documentation strings are not allowed!");
473                                 }
474                                 idlc()->setDocumentation(docu);
475                                 BEGIN( INITIAL );
476                         }
478 "//"[^/]{1}.*"\n" {
479                                 /* only a comment */
480                                 ::rtl::OString docStr(yytext);
481                                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
482                                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
483                                 docStr = docStr.trim();
484                                 idlc()->incLineNumber();
485                         }
487 "///".*"\n"  {
488                                 ::rtl::OString docStr(yytext);
489                                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
490                                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
491                                 docStr = docStr.trim();
492                                 idlc()->incLineNumber();
493                                 idlc()->setDocumentation(docStr);
494                         }
496 .       return yytext[0];
498 ^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n    {
499         parseLineAndFile(yytext);
502 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n {
503         parseLineAndFile(yytext);
506 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
507         parseLineAndFile(yytext);
510 ^#[ \t]*[0-9]*\n {
511         parseLineAndFile(yytext);
514 ^#[ \t]*ident.*\n {
515         /* ignore cpp ident */
516         idlc()->incLineNumber();
519 ^#[ \t]*pragma[ \t].*\n        {       /* remember pragma */
520         idlParsePragma(yytext);
521         idlc()->incLineNumber();