xref: /AOO41X/main/idlc/source/scanner.ll (revision e26f32421ede4ae50ba26ef41f332da4ec2903b3)
1/**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements.  See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership.  The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License.  You may obtain a copy of the License at
10 *
11 *   http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied.  See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24%{
25/*
26 * scanner.ll - Lexical scanner for IDLC 1.0
27 */
28
29#include <ctype.h>
30#include <stdlib.h>
31#include <string.h>
32
33#ifndef _IDLC_IDLC_HXX_
34#include <idlc/idlc.hxx>
35#endif
36#ifndef _IDLC_ERRORHANDLER_HXX_
37#include <idlc/errorhandler.hxx>
38#endif
39#ifndef _IDLC_FEHELPER_HXX_
40#include <idlc/fehelper.hxx>
41#endif
42
43#include "attributeexceptions.hxx"
44
45class AstExpression;
46class AstArray;
47class AstMember;
48
49#include <parser.hxx>
50
51sal_Int32       beginLine = 0;
52::rtl::OString  docu;
53
54static 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    }
137}
138
139static double asciiToFloat(const sal_Char *s)
140{
141    double      d = 0.0;
142    double      e, k;
143    sal_Int32   neg = 0, negexp = 0;
144
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                if (negexp)
187                    d /= k;
188                else
189                    d *= k;
190            }
191        }
192    }
193    if (neg) d *= -1.0;
194    return d;
195}
196
197static void idlParsePragma(sal_Char* pPragma)
198{
199    ::rtl::OString pragma(pPragma);
200    sal_Int32 index = pragma.indexOf("include");
201    sal_Char* begin = pPragma + index + 8;
202    sal_Char* offset = begin;
203    while (*offset != ',') offset++;
204    //::rtl::OString include = pragma.copy(index + 8, offset - begin);
205    idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin)));
206}
207
208static void parseLineAndFile(sal_Char* pBuf)
209{
210    sal_Char    *r = pBuf;
211    sal_Char    *h;
212    sal_Bool    bIsInMain = sal_False;
213
214    /* Skip initial '#' */
215    if (*r != '#')
216        return;
217
218    /* Find line number */
219    for (r++; *r == ' ' || *r == '\t' || isalpha(*r); r++) ;
220    h = r;
221    for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ;
222    *r++ = 0;
223    idlc()->setLineNumber((sal_uInt32)atol(h));
224
225    /* Find file name, if present */
226    for (; *r != '"'; r++)
227    {
228        if (*r == '\n' || *r == '\0')
229            return;
230    }
231    h = ++r;
232    for (; *r != '"'; r++) ;
233    *r = 0;
234    if (*h == '\0')
235        idlc()->setFileName(::rtl::OString("standard input"));
236    else
237        idlc()->setFileName(::rtl::OString(h));
238
239    bIsInMain = (idlc()->getFileName() == idlc()->getRealFileName()) ? sal_True : sal_False;
240    idlc()->setInMainfile(bIsInMain);
241}
242
243// Suppress any warnings from generated code:
244#if defined __GNUC__
245#pragma GCC system_header
246#elif defined __SUNPRO_CC
247#pragma disable_warn
248#elif defined _MSC_VER
249#pragma warning(push, 1)
250/**/
251#ifdef yywrap
252#undef  yywrap
253#define yywrap() 1
254#endif
255/**/
256#endif
257%}
258
259%option noyywrap
260%option never-interactive
261
262%x DOCU
263%x COMMENT
264
265DIGIT           [0-9]
266OCT_DIGIT       [0-7]
267HEX_DIGIT       [a-fA-F0-9]
268CAPITAL         [A-Z]
269ALPHA           [a-zA-Z]
270INT_LITERAL     [1-9][0-9]*
271OCT_LITERAL     0{OCT_DIGIT}*
272HEX_LITERAL     (0x|0X){HEX_DIGIT}*
273
274IDENTIFIER_NEW  ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*)
275IDENTIFIER      ("_"?({ALPHA}|{DIGIT})+)*
276
277%%
278
279[ \t\r]+    ; /* eat up whitespace */
280[\n]        {
281    idlc()->incLineNumber();
282}
283
284attribute       return IDL_ATTRIBUTE;
285bound           return IDL_BOUND;
286case            return IDL_CASE;
287const           return IDL_CONST;
288constants       return IDL_CONSTANTS;
289constrained     return IDL_CONSTRAINED;
290default         return IDL_DEFAULT;
291enum            return IDL_ENUM;
292exception       return IDL_EXCEPTION;
293interface       return IDL_INTERFACE;
294maybeambiguous  return IDL_MAYBEAMBIGUOUS;
295maybedefault    return IDL_MAYBEDEFAULT;
296maybevoid       return IDL_MAYBEVOID;
297module          return IDL_MODULE;
298needs           return IDL_NEEDS;
299observes        return IDL_OBSERVES;
300optional        return IDL_OPTIONAL;
301property        return IDL_PROPERTY;
302raises          return IDL_RAISES;
303readonly        return IDL_READONLY;
304removable       return IDL_REMOVEABLE;
305service         return IDL_SERVICE;
306sequence        return IDL_SEQUENCE;
307singleton       return IDL_SINGLETON;
308struct          return IDL_STRUCT;
309switch          return IDL_SWITCH;
310transient       return IDL_TRANSIENT;
311typedef         return IDL_TYPEDEF;
312union           return IDL_UNION;
313
314any             return IDL_ANY;
315boolean         return IDL_BOOLEAN;
316byte            return IDL_BYTE;
317char            return IDL_CHAR;
318double          return IDL_DOUBLE;
319float           return IDL_FLOAT;
320hyper           return IDL_HYPER;
321long            return IDL_LONG;
322short           return IDL_SHORT;
323string          return IDL_STRING;
324type            return IDL_TYPE;
325unsigned        return IDL_UNSIGNED;
326void            return IDL_VOID;
327
328TRUE            return IDL_TRUE;
329True            return IDL_TRUE;
330FALSE           return IDL_FALSE;
331False           return IDL_FALSE;
332
333in              return IDL_IN;
334out             return IDL_OUT;
335inout           return IDL_INOUT;
336oneway          return IDL_ONEWAY;
337
338get             return IDL_GET;
339set             return IDL_SET;
340
341published       return IDL_PUBLISHED;
342
343"..."           return IDL_ELLIPSIS;
344
345("-")?{INT_LITERAL}+(l|L|u|U)?    {
346                return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
347            }
348
349("-")?{OCT_LITERAL}+(l|L|u|U)?    {
350                return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
351            }
352
353("-")?{HEX_LITERAL}+(l|L|u|U)?    {
354                return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
355            }
356
357("-")?{DIGIT}+(e|E){1}(("+"|"-")?{DIGIT}+)+(f|F)?   |
358("-")?"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?   |
359("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)?        {
360                yylval.dval = asciiToFloat( yytext );
361                return IDL_FLOATING_PT_LITERAL;
362            }
363
364{IDENTIFIER}    {
365                yylval.sval = new ::rtl::OString(yytext);
366                return IDL_IDENTIFIER;
367            }
368
369\<\<    {
370        yylval.strval = yytext;
371        return IDL_LEFTSHIFT;
372    }
373\>\>    {
374        yylval.strval = yytext;
375        return IDL_RIGHTSHIFT;
376    }
377\:\:    {
378        yylval.strval = yytext;
379        return IDL_SCOPESEPARATOR;
380    }
381
382"/*"    {
383            BEGIN( COMMENT );
384            docu = ::rtl::OString();
385            beginLine = idlc()->getLineNumber();
386        }
387
388"/***"  {
389            BEGIN( COMMENT );
390            docu = ::rtl::OString();
391            beginLine = idlc()->getLineNumber();
392        }
393
394<COMMENT>[^*]+  {
395                docu += ::rtl::OString(yytext);
396            }
397
398<COMMENT>"*"[^*/]+  {
399                docu += ::rtl::OString(yytext);
400            }
401
402<COMMENT>"**"   {
403                docu += ::rtl::OString(yytext);
404            }
405
406<COMMENT>[*]+"/"  {
407                docu = docu.trim();
408                sal_Int32 nIndex = 0;
409                int count = 0;
410                do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
411                idlc()->setLineNumber( beginLine + count - 1);
412                BEGIN( INITIAL );
413            }
414
415"/**"   {
416            BEGIN( DOCU );
417            docu = ::rtl::OString();
418            beginLine = idlc()->getLineNumber();
419        }
420
421<DOCU>[^*\n]+   {
422                docu += ::rtl::OString(yytext);
423            }
424
425<DOCU>"\n"[ \t]*"*"{1}  {
426                idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
427                docu += ::rtl::OString("\n");
428            }
429
430<DOCU>"\n"  {
431                idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
432                docu += ::rtl::OString(yytext);
433            }
434
435<DOCU>"*"[^*^/\n]*  {
436                docu += ::rtl::OString(yytext);
437            }
438
439<DOCU>"\n"[ \t]*"*/"    {
440                docu = docu.trim();
441                sal_Int32 nIndex = 0;
442                int count = 0;
443                do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
444                idlc()->setLineNumber( beginLine + count - 1);
445                if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 )
446                {
447                    if ( 0 != nIndex &&
448                         (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
449                        idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
450                                                     "nested documentation strings are not allowed!");
451                }
452                idlc()->setDocumentation(docu);
453                BEGIN( INITIAL );
454            }
455
456<DOCU>"*/"  {
457                docu = docu.trim();
458                sal_Int32 nIndex = 0;
459                int count = 0;
460                do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
461                idlc()->setLineNumber( beginLine + count - 1);
462                if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 )
463                {
464                    if ( 0 != nIndex &&
465                         (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
466                        idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
467                                                     "nested documentation strings are not allowed!");
468                }
469                idlc()->setDocumentation(docu);
470                BEGIN( INITIAL );
471            }
472
473"//"[^/]{1}.*"\n" {
474                /* only a comment */
475                ::rtl::OString docStr(yytext);
476                docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
477                docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
478                docStr = docStr.trim();
479                idlc()->incLineNumber();
480            }
481
482"///".*"\n"  {
483                ::rtl::OString docStr(yytext);
484                docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
485                docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
486                docStr = docStr.trim();
487                idlc()->incLineNumber();
488                idlc()->setDocumentation(docStr);
489            }
490
491.   return yytext[0];
492
493^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n    {
494    parseLineAndFile(yytext);
495}
496
497^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n {
498    parseLineAndFile(yytext);
499}
500
501^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
502    parseLineAndFile(yytext);
503}
504
505^#[ \t]*[0-9]*\n {
506    parseLineAndFile(yytext);
507}
508
509^#[ \t]*ident.*\n {
510    /* ignore cpp ident */
511    idlc()->incLineNumber();
512}
513
514^#[ \t]*pragma[ \t].*\n        {       /* remember pragma */
515    idlParsePragma(yytext);
516    idlc()->incLineNumber();
517}
518
519%%
520