xref: /trunk/main/idlc/source/scanner.ll (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1/*************************************************************************
2 *
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
6 *
7 * OpenOffice.org - a multi-platform office productivity suite
8 *
9 * This file is part of OpenOffice.org.
10 *
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
14 *
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org.  If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
25 *
26 ************************************************************************/
27
28%{
29/*
30 * scanner.ll - Lexical scanner for IDLC 1.0
31 */
32
33#include <ctype.h>
34#include <stdlib.h>
35#include <string.h>
36
37#ifndef _IDLC_IDLC_HXX_
38#include <idlc/idlc.hxx>
39#endif
40#ifndef _IDLC_ERRORHANDLER_HXX_
41#include <idlc/errorhandler.hxx>
42#endif
43#ifndef _IDLC_FEHELPER_HXX_
44#include <idlc/fehelper.hxx>
45#endif
46
47#include "attributeexceptions.hxx"
48
49class AstExpression;
50class AstArray;
51class AstMember;
52
53#include <parser.hxx>
54
55sal_Int32       beginLine = 0;
56::rtl::OString  docu;
57
58static 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    }
141}
142
143static double asciiToFloat(const sal_Char *s)
144{
145    double      d = 0.0;
146    double      e, k;
147    sal_Int32   neg = 0, negexp = 0;
148
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                if (negexp)
191                    d /= k;
192                else
193                    d *= k;
194            }
195        }
196    }
197    if (neg) d *= -1.0;
198    return d;
199}
200
201static void idlParsePragma(sal_Char* pPragma)
202{
203    ::rtl::OString pragma(pPragma);
204    sal_Int32 index = pragma.indexOf("include");
205    sal_Char* begin = pPragma + index + 8;
206    sal_Char* offset = begin;
207    while (*offset != ',') offset++;
208    //::rtl::OString include = pragma.copy(index + 8, offset - begin);
209    idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin)));
210}
211
212static void parseLineAndFile(sal_Char* pBuf)
213{
214    sal_Char    *r = pBuf;
215    sal_Char    *h;
216    sal_Bool    bIsInMain = sal_False;
217
218    /* Skip initial '#' */
219    if (*r != '#')
220        return;
221
222    /* Find line number */
223    for (r++; *r == ' ' || *r == '\t' || isalpha(*r); r++) ;
224    h = r;
225    for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ;
226    *r++ = 0;
227    idlc()->setLineNumber((sal_uInt32)atol(h));
228
229    /* Find file name, if present */
230    for (; *r != '"'; r++)
231    {
232        if (*r == '\n' || *r == '\0')
233            return;
234    }
235    h = ++r;
236    for (; *r != '"'; r++) ;
237    *r = 0;
238    if (*h == '\0')
239        idlc()->setFileName(::rtl::OString("standard input"));
240    else
241        idlc()->setFileName(::rtl::OString(h));
242
243    bIsInMain = (idlc()->getFileName() == idlc()->getRealFileName()) ? sal_True : sal_False;
244    idlc()->setInMainfile(bIsInMain);
245}
246
247// Suppress any warnings from generated code:
248#if defined __GNUC__
249#pragma GCC system_header
250#elif defined __SUNPRO_CC
251#pragma disable_warn
252#elif defined _MSC_VER
253#pragma warning(push, 1)
254/**/
255#ifdef yywrap
256#undef  yywrap
257#define yywrap() 1
258#endif
259/**/
260#endif
261%}
262
263%option noyywrap
264%option never-interactive
265
266%x DOCU
267%x COMMENT
268
269DIGIT           [0-9]
270OCT_DIGIT       [0-7]
271HEX_DIGIT       [a-fA-F0-9]
272CAPITAL         [A-Z]
273ALPHA           [a-zA-Z]
274INT_LITERAL     [1-9][0-9]*
275OCT_LITERAL     0{OCT_DIGIT}*
276HEX_LITERAL     (0x|0X){HEX_DIGIT}*
277
278IDENTIFIER_NEW  ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*)
279IDENTIFIER      ("_"?({ALPHA}|{DIGIT})+)*
280
281%%
282
283[ \t\r]+    ; /* eat up whitespace */
284[\n]        {
285    idlc()->incLineNumber();
286}
287
288attribute       return IDL_ATTRIBUTE;
289bound           return IDL_BOUND;
290case            return IDL_CASE;
291const           return IDL_CONST;
292constants       return IDL_CONSTANTS;
293constrained     return IDL_CONSTRAINED;
294default         return IDL_DEFAULT;
295enum            return IDL_ENUM;
296exception       return IDL_EXCEPTION;
297interface       return IDL_INTERFACE;
298maybeambiguous  return IDL_MAYBEAMBIGUOUS;
299maybedefault    return IDL_MAYBEDEFAULT;
300maybevoid       return IDL_MAYBEVOID;
301module          return IDL_MODULE;
302needs           return IDL_NEEDS;
303observes        return IDL_OBSERVES;
304optional        return IDL_OPTIONAL;
305property        return IDL_PROPERTY;
306raises          return IDL_RAISES;
307readonly        return IDL_READONLY;
308removable       return IDL_REMOVEABLE;
309service         return IDL_SERVICE;
310sequence        return IDL_SEQUENCE;
311singleton       return IDL_SINGLETON;
312struct          return IDL_STRUCT;
313switch          return IDL_SWITCH;
314transient       return IDL_TRANSIENT;
315typedef         return IDL_TYPEDEF;
316union           return IDL_UNION;
317
318any             return IDL_ANY;
319boolean         return IDL_BOOLEAN;
320byte            return IDL_BYTE;
321char            return IDL_CHAR;
322double          return IDL_DOUBLE;
323float           return IDL_FLOAT;
324hyper           return IDL_HYPER;
325long            return IDL_LONG;
326short           return IDL_SHORT;
327string          return IDL_STRING;
328type            return IDL_TYPE;
329unsigned        return IDL_UNSIGNED;
330void            return IDL_VOID;
331
332TRUE            return IDL_TRUE;
333True            return IDL_TRUE;
334FALSE           return IDL_FALSE;
335False           return IDL_FALSE;
336
337in              return IDL_IN;
338out             return IDL_OUT;
339inout           return IDL_INOUT;
340oneway          return IDL_ONEWAY;
341
342get             return IDL_GET;
343set             return IDL_SET;
344
345published       return IDL_PUBLISHED;
346
347"..."           return IDL_ELLIPSIS;
348
349("-")?{INT_LITERAL}+(l|L|u|U)?    {
350                return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
351            }
352
353("-")?{OCT_LITERAL}+(l|L|u|U)?    {
354                return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
355            }
356
357("-")?{HEX_LITERAL}+(l|L|u|U)?    {
358                return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
359            }
360
361("-")?{DIGIT}+(e|E){1}(("+"|"-")?{DIGIT}+)+(f|F)?   |
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            }
367
368{IDENTIFIER}    {
369                yylval.sval = new ::rtl::OString(yytext);
370                return IDL_IDENTIFIER;
371            }
372
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    }
385
386"/*"    {
387            BEGIN( COMMENT );
388            docu = ::rtl::OString();
389            beginLine = idlc()->getLineNumber();
390        }
391
392"/***"  {
393            BEGIN( COMMENT );
394            docu = ::rtl::OString();
395            beginLine = idlc()->getLineNumber();
396        }
397
398<COMMENT>[^*]+  {
399                docu += ::rtl::OString(yytext);
400            }
401
402<COMMENT>"*"[^*/]+  {
403                docu += ::rtl::OString(yytext);
404            }
405
406<COMMENT>"**"   {
407                docu += ::rtl::OString(yytext);
408            }
409
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            }
418
419"/**"   {
420            BEGIN( DOCU );
421            docu = ::rtl::OString();
422            beginLine = idlc()->getLineNumber();
423        }
424
425<DOCU>[^*\n]+   {
426                docu += ::rtl::OString(yytext);
427            }
428
429<DOCU>"\n"[ \t]*"*"{1}  {
430                idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
431                docu += ::rtl::OString("\n");
432            }
433
434<DOCU>"\n"  {
435                idlc()->setLineNumber( idlc()->getLineNumber()  + 1);
436                docu += ::rtl::OString(yytext);
437            }
438
439<DOCU>"*"[^*^/\n]*  {
440                docu += ::rtl::OString(yytext);
441            }
442
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.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
453                        idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
454                                                     "nested documentation strings are not allowed!");
455                }
456                idlc()->setDocumentation(docu);
457                BEGIN( INITIAL );
458            }
459
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.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') )
470                        idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(),
471                                                     "nested documentation strings are not allowed!");
472                }
473                idlc()->setDocumentation(docu);
474                BEGIN( INITIAL );
475            }
476
477"//"[^/]{1}.*"\n" {
478                /* only a comment */
479                ::rtl::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            }
485
486"///".*"\n"  {
487                ::rtl::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            }
494
495.   return yytext[0];
496
497^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n    {
498    parseLineAndFile(yytext);
499}
500
501^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n {
502    parseLineAndFile(yytext);
503}
504
505^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
506    parseLineAndFile(yytext);
507}
508
509^#[ \t]*[0-9]*\n {
510    parseLineAndFile(yytext);
511}
512
513^#[ \t]*ident.*\n {
514    /* ignore cpp ident */
515    idlc()->incLineNumber();
516}
517
518^#[ \t]*pragma[ \t].*\n        {       /* remember pragma */
519    idlParsePragma(yytext);
520    idlc()->incLineNumber();
521}
522
523%%
524