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