bump product version to 7.2.5.1
[LibreOffice.git] / idlc / source / scanner.l
blobe7fff5ee31e6c4e23e59a8535eee3947074b2af4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
20 %option yylineno
24  * scanner.ll - Lexical scanner for IDLC 1.0
25  */
27 #include <sal/config.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include <o3tl/safeint.hxx>
33 #include <rtl/character.hxx>
35 #if defined _MSC_VER
36 #pragma warning ( push )
37 // Silence warnings about redefinition of INT8_MIN etc in stdint.h
38 // The flex-generated workdir/LexTarget/idlc/source/scanner.cxx defines them prior to these includes
39 #pragma warning ( disable : 4005 )
40 #endif
41 #include <idlc.hxx>
42 #if defined _MSC_VER
43 #pragma warning ( pop )
44 #endif
45 #include <errorhandler.hxx>
46 #include <fehelper.hxx>
48 #include "attributeexceptions.hxx"
51 class AstExpression;
52 class AstMember;
54 #include <parser.hxx>
56 /* handle locations */
57 static int yycolumn = 1;
59 #define YY_USER_ACTION idlc()->setOffset(yycolumn, yycolumn+yyleng-1); \
60     yycolumn += yyleng;
62 static sal_Int32       beginLine = 0;
63 static OString docu;
65 static int asciiToInteger(char const * s, sal_Int64  * sval, sal_uInt64 * uval) {
66     bool neg = false;
67     if (*s == '-') {
68         neg = true;
69         ++s;
70     }
71     unsigned int base = 10;
72     if (*s == '0') {
73         base = 8;
74         ++s;
75         if (*s == 'X' || *s == 'x') {
76             base = 16;
77             ++s;
78         }
79     }
80     sal_uInt64 val = 0;
81     for (; *s != 0; ++s) {
82         unsigned int n;
83         if (*s >= '0' && *s <= '9') {
84             n = *s - '0';
85         } else {
86             switch (*s) {
87             case 'A':
88             case 'a':
89                 n = 10;
90                 break;
91             case 'B':
92             case 'b':
93                 n = 11;
94                 break;
95             case 'C':
96             case 'c':
97                 n = 12;
98                 break;
99             case 'D':
100             case 'd':
101                 n = 13;
102                 break;
103             case 'E':
104             case 'e':
105                 n = 14;
106                 break;
107             case 'F':
108             case 'f':
109                 n = 15;
110                 break;
111             default:
112                 goto done;
113             }
114         }
115         // The following guarantees the invariant val <= SAL_MAX_UINT64 (because
116         // base and n are sufficiently small), *if*
117         // std::numeric_limits<sal_uInt64>::max() == SAL_MAX_UINT64:
118         sal_uInt64 nval = val * base + n;
119         if (nval < val) {
120             ErrorHandler::syntaxError(
121                 PS_NoState, idlc()->getLineNumber(),
122                 "integral constant too large");
123             val = 0;
124             break;
125         }
126         val = nval;
127     }
128  done:
129     if (neg) {
130         if (val < SAL_CONST_UINT64(0x8000000000000000)) {
131             *sval = -static_cast< sal_Int64 >(val);
132         } else if (val == SAL_CONST_UINT64(0x8000000000000000)) {
133             *sval = SAL_MIN_INT64;
134         } else {
135             ErrorHandler::syntaxError(
136                 PS_NoState, idlc()->getLineNumber(),
137                 "negative integral constant too large");
138             *sval = 0;
139         }
140         return IDL_INTEGER_LITERAL;
141     } else if (val <= o3tl::make_unsigned(SAL_MAX_INT64)) {
142         *sval = static_cast< sal_Int64 >(val);
143         return IDL_INTEGER_LITERAL;
144     } else {
145         *uval = val;
146         return IDL_INTEGER_ULITERAL;
147     }
150 static double asciiToFloat(const char *s)
152     double      d = 0.0;
153     double      e, k;
154     sal_Int32   neg = 0;
156     if (*s == '-')
157     {
158         neg = 1;
159         s++;
160     }
161     while (*s >= '0' && *s <= '9')
162     {
163         d = (d * 10) + *s - '0';
164         s++;
165     }
166     if (*s == '.')
167     {
168         s++;
169         e = 10;
170         while (*s >= '0' && *s <= '9')
171         {
172             d += (*s - '0') / (e * 1.0);
173             e *= 10;
174             s++;
175         }
176     }
177     if (*s == 'e' || *s == 'E')
178     {
179         s++;
180         if (*s == '-')
181         {
182             s++;
183         } else
184         {
185             if (*s == '+')
186                 s++;
187             e = 0;
188             while (*s >= '0' && *s <= '9')
189             {
190                 e = (e * 10) + *s - '0';
191                 s++;
192             }
193             if (e > 0)
194             {
195                 for (k = 1; e > 0; k *= 10, e--)
196                     ;
197                 d /= k;
198             }
199         }
200     }
201     if (neg) d *= -1.0;
202     return d;
205 static void idlParsePragma(char* pPragma)
207     OString pragma(pPragma);
208     sal_Int32 index = pragma.indexOf("include");
209     char* begin = pPragma + index + 8;
210     char* offset = begin;
211     while (*offset != ',') offset++;
212     //OString include = pragma.copy(index + 8, offset - begin);
213     //unused// idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin)));
214 }   
216 static void parseLineAndFile(char* pBuf)
218     char    *r = pBuf;
219     char    *h;
220     bool    bIsInMain = false;
222     /* Skip initial '#' */
223     if (*r != '#')
224         return;
226     /* Find line number */
227     for (r++; *r == ' ' || *r == '\t' || rtl::isAsciiAlpha(static_cast<unsigned char>(*r)); r++) ;
228     h = r;
229     for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ;
230     *r++ = 0;
231     idlc()->setLineNumber(sal_uInt32(atol(h)));
232     yylineno = atol(h);
234     /* Find file name, if present */
235     for (; *r != '"'; r++)
236     {
237         if (*r == '\n' || *r == '\0')
238             return;
239     }
240     h = ++r;
241     for (; *r != '"'; r++) ;
242     *r = 0;
243     if (*h == '\0')
244         idlc()->setFileName("standard input");
245     else
246         idlc()->setFileName(OString(h));
248     bIsInMain = idlc()->getFileName() == idlc()->getRealFileName();
249     idlc()->setInMainfile(bIsInMain);       
250 }   
252 // Suppress any warnings from generated code:
253 #ifdef __GNUC__
254 #pragma GCC diagnostic ignored "-Wunused-function"
255 #pragma GCC diagnostic ignored "-Wunused-label"
256 #elif defined _MSC_VER
257 /**/
258 #ifdef yywrap
259 #undef  yywrap
260 #define yywrap() 1
261 #endif
262 /**/
263 #endif
264 #define YY_NO_UNISTD_H
267 %option noyywrap
268 %option never-interactive
270 %x DOCU
271 %x COMMENT
273 DIGIT           [0-9]
274 OCT_DIGIT       [0-7]
275 HEX_DIGIT       [a-fA-F0-9]
276 CAPITAL         [A-Z]
277 ALPHA           [a-zA-Z]
278 INT_LITERAL     [1-9][0-9]*
279 OCT_LITERAL     0{OCT_DIGIT}*
280 HEX_LITERAL     (0x|0X){HEX_DIGIT}*
282 IDENTIFIER_NEW  ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*)
283 IDENTIFIER      ("_"?({ALPHA}|{DIGIT})+)*
287 [ \t\r]+    ; /* eat up whitespace */
288 [\n]           {
289        idlc()->incLineNumber();
290        yycolumn = 1;
291        yylineno++;
294 attribute       return IDL_ATTRIBUTE;
295 bound           return IDL_BOUND;
296 const           return IDL_CONST;
297 constants       return IDL_CONSTANTS;
298 constrained     return IDL_CONSTRAINED;
299 enum            return IDL_ENUM;
300 exception       return IDL_EXCEPTION;
301 interface       return IDL_INTERFACE;
302 maybeambiguous  return IDL_MAYBEAMBIGUOUS;
303 maybedefault    return IDL_MAYBEDEFAULT;
304 maybevoid       return IDL_MAYBEVOID;
305 module          return IDL_MODULE;
306 needs           return IDL_NEEDS;
307 observes        return IDL_OBSERVES;
308 optional        return IDL_OPTIONAL;
309 property        return IDL_PROPERTY;
310 raises          return IDL_RAISES;
311 readonly        return IDL_READONLY;
312 removable       return IDL_REMOVABLE;
313 service         return IDL_SERVICE;
314 sequence        return IDL_SEQUENCE;
315 singleton       return IDL_SINGLETON;
316 struct          return IDL_STRUCT;
317 transient       return IDL_TRANSIENT;
318 typedef         return IDL_TYPEDEF;
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)(("+"|"-")?{DIGIT}+)?(f|F)?  |
363 ("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?        {
364                 yylval.dval = asciiToFloat( yytext );
365                 return IDL_FLOATING_PT_LITERAL;
366             }
368 {IDENTIFIER}    {
369                 yylval.sval = new OString(yytext);
370                 return IDL_IDENTIFIER;
371             }
373 \<\<    {
374         yylval.strval = yytext;
375         return IDL_LEFTSHIFT;
376     }
377 \>\>    {
378         yylval.strval = yytext;
379         return IDL_RIGHTSHIFT;
380     }
381 \:\:    {
382         yylval.strval = yytext;
383         return IDL_SCOPESEPARATOR;
384     }
386 "/*"    { 
387             BEGIN( COMMENT );
388             docu = OString();
389             beginLine = idlc()->getLineNumber();
390         }
392 "/***"  { 
393             BEGIN( COMMENT );
394             docu = OString();
395             beginLine = idlc()->getLineNumber();
396         }
398 <COMMENT>[^*]+  {
399                 docu += yytext;
400             } 
402 <COMMENT>"*"[^*/]+  {
403                 docu += yytext;
404             }
406 <COMMENT>"**"   {
407                 docu += yytext;
408             }
410 <COMMENT>[*]+"/"  {
411                 docu = docu.trim();
412                 sal_Int32 nIndex = 0;
413                 int count = 0;
414                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
415                 idlc()->setLineNumber( beginLine + count - 1);
416                 BEGIN( INITIAL );
417             }
419 "/**"   {
420             BEGIN( DOCU );
421             docu = OString();
422             beginLine = idlc()->getLineNumber();
423         }
425 <DOCU>[^*\n]+   {
426                 docu += yytext;
427             }
429 <DOCU>"\n"[ \t]*"*"{1}  {
430                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
431                 docu += "\n";
432             }
434 <DOCU>"\n"  {
435                 idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
436                 docu += yytext;
437             }
439 <DOCU>"*"[^*^/\n]*  {
440                 docu += yytext;
441             }
443 <DOCU>"\n"[ \t]*"*/"    {
444                 docu = docu.trim();
445                 sal_Int32 nIndex = 0;
446                 int count = 0;
447                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
448                 idlc()->setLineNumber( beginLine + count - 1);                
449                 if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 )
450                 {
451                     if ( 0 != nIndex &&
452                          (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') )
453                         ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(),
454                                                      "nested documentation strings are not allowed!");
455                 }
456                 idlc()->setDocumentation(docu);
457                 BEGIN( INITIAL );
458             }
460 <DOCU>"*/"  {
461                 docu = docu.trim();
462                 sal_Int32 nIndex = 0;
463                 int count = 0;
464                 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
465                 idlc()->setLineNumber( beginLine + count - 1);
466                 if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 )
467                 {
468                     if ( 0 != nIndex &&
469                          (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') )
470                         ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(),
471                                                      "nested documentation strings are not allowed!");
472                 }
473                 idlc()->setDocumentation(docu);
474                 BEGIN( INITIAL );
475             }
477 "//"[^/]{1}.*"\n" {
478                 /* only a comment */
479                 OString docStr(yytext);
480                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
481                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
482                 docStr = docStr.trim();
483                 idlc()->incLineNumber();
484             }
486 "///".*"\n"  {
487                 OString docStr(yytext);
488                 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
489                 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
490                 docStr = docStr.trim();
491                 idlc()->incLineNumber();
492                 idlc()->setDocumentation(docStr);
493             }
495 .   return yytext[0];
497 ^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n    {
498     parseLineAndFile(yytext);
501 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n {
502     parseLineAndFile(yytext);
505 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
506     parseLineAndFile(yytext);
509 ^#[ \t]*[0-9]*\n {
510     parseLineAndFile(yytext);
513 ^#[ \t]*ident.*\n {
514     /* ignore cpp ident */
515     idlc()->incLineNumber();
518 ^#[ \t]*pragma[ \t].*\n        {       /* remember pragma */
519     idlParsePragma(yytext);
520     idlc()->incLineNumber();
525 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */