xref: /trunk/main/idlc/source/scanner.ll (revision cdf0e10c)
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