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 */
19
20 %option yylineno
21
22 %{
23 /*
24 * scanner.ll - Lexical scanner for IDLC 1.0
25 */
26
27 #include <sal/config.h>
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include <rtl/character.hxx>
33
34 #if defined _MSC_VER
35 #pragma warning ( push )
36 // Silence warnings about redefinition of INT8_MIN etc in stdint.h
37 // The flex-generated workdir/LexTarget/idlc/source/scanner.cxx defines them prior to these includes
38 #pragma warning ( disable : 4005 )
39 #endif
40 #include <idlc.hxx>
41 #if defined _MSC_VER
42 #pragma warning ( pop )
43 #endif
44 #include <errorhandler.hxx>
45 #include <fehelper.hxx>
46
47 #include "attributeexceptions.hxx"
48
49
50 class AstExpression;
51 class AstMember;
52
53 #include <parser.hxx>
54
55 /* handle locations */
56 static int yycolumn = 1;
57
58 #define YY_USER_ACTION idlc()->setOffset(yycolumn, yycolumn+yyleng-1); \
59 yycolumn += yyleng;
60
61 static sal_Int32 beginLine = 0;
62 static OString docu;
63
asciiToInteger(char const * s,sal_Int64 * sval,sal_uInt64 * uval)64 static int asciiToInteger(char const * s, sal_Int64 * sval, sal_uInt64 * uval) {
65 bool neg = false;
66 if (*s == '-') {
67 neg = true;
68 ++s;
69 }
70 unsigned int base = 10;
71 if (*s == '0') {
72 base = 8;
73 ++s;
74 if (*s == 'X' || *s == 'x') {
75 base = 16;
76 ++s;
77 }
78 }
79 sal_uInt64 val = 0;
80 for (; *s != 0; ++s) {
81 unsigned int n;
82 if (*s >= '0' && *s <= '9') {
83 n = *s - '0';
84 } else {
85 switch (*s) {
86 case 'A':
87 case 'a':
88 n = 10;
89 break;
90 case 'B':
91 case 'b':
92 n = 11;
93 break;
94 case 'C':
95 case 'c':
96 n = 12;
97 break;
98 case 'D':
99 case 'd':
100 n = 13;
101 break;
102 case 'E':
103 case 'e':
104 n = 14;
105 break;
106 case 'F':
107 case 'f':
108 n = 15;
109 break;
110 default:
111 goto done;
112 }
113 }
114 // The following guarantees the invariant val <= SAL_MAX_UINT64 (because
115 // base and n are sufficiently small), *if*
116 // std::numeric_limits<sal_uInt64>::max() == SAL_MAX_UINT64:
117 sal_uInt64 nval = val * base + n;
118 if (nval < val) {
119 ErrorHandler::syntaxError(
120 PS_NoState, idlc()->getLineNumber(),
121 "integral constant too large");
122 val = 0;
123 break;
124 }
125 val = nval;
126 }
127 done:
128 if (neg) {
129 if (val < SAL_CONST_UINT64(0x8000000000000000)) {
130 *sval = -static_cast< sal_Int64 >(val);
131 } else if (val == SAL_CONST_UINT64(0x8000000000000000)) {
132 *sval = SAL_MIN_INT64;
133 } else {
134 ErrorHandler::syntaxError(
135 PS_NoState, idlc()->getLineNumber(),
136 "negative integral constant too large");
137 *sval = 0;
138 }
139 return IDL_INTEGER_LITERAL;
140 } else if (val <= static_cast< sal_uInt64 >(SAL_MAX_INT64)) {
141 *sval = static_cast< sal_Int64 >(val);
142 return IDL_INTEGER_LITERAL;
143 } else {
144 *uval = val;
145 return IDL_INTEGER_ULITERAL;
146 }
147 }
148
asciiToFloat(const sal_Char * s)149 static double asciiToFloat(const sal_Char *s)
150 {
151 double d = 0.0;
152 double e, k;
153 sal_Int32 neg = 0;
154
155 if (*s == '-')
156 {
157 neg = 1;
158 s++;
159 }
160 while (*s >= '0' && *s <= '9')
161 {
162 d = (d * 10) + *s - '0';
163 s++;
164 }
165 if (*s == '.')
166 {
167 s++;
168 e = 10;
169 while (*s >= '0' && *s <= '9')
170 {
171 d += (*s - '0') / (e * 1.0);
172 e *= 10;
173 s++;
174 }
175 }
176 if (*s == 'e' || *s == 'E')
177 {
178 s++;
179 if (*s == '-')
180 {
181 s++;
182 } else
183 {
184 if (*s == '+')
185 s++;
186 e = 0;
187 while (*s >= '0' && *s <= '9')
188 {
189 e = (e * 10) + *s - '0';
190 s++;
191 }
192 if (e > 0)
193 {
194 for (k = 1; e > 0; k *= 10, e--)
195 ;
196 d /= k;
197 }
198 }
199 }
200 if (neg) d *= -1.0;
201 return d;
202 }
203
idlParsePragma(sal_Char * pPragma)204 static void idlParsePragma(sal_Char* pPragma)
205 {
206 OString pragma(pPragma);
207 sal_Int32 index = pragma.indexOf("include");
208 sal_Char* begin = pPragma + index + 8;
209 sal_Char* offset = begin;
210 while (*offset != ',') offset++;
211 //OString include = pragma.copy(index + 8, offset - begin);
212 //unused// idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin)));
213 }
214
parseLineAndFile(sal_Char * pBuf)215 static void parseLineAndFile(sal_Char* pBuf)
216 {
217 sal_Char *r = pBuf;
218 sal_Char *h;
219 bool bIsInMain = false;
220
221 /* Skip initial '#' */
222 if (*r != '#')
223 return;
224
225 /* Find line number */
226 for (r++; *r == ' ' || *r == '\t' || rtl::isAsciiAlpha(static_cast<unsigned char>(*r)); r++) ;
227 h = r;
228 for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ;
229 *r++ = 0;
230 idlc()->setLineNumber(sal_uInt32(atol(h)));
231 yylineno = atol(h);
232
233 /* Find file name, if present */
234 for (; *r != '"'; r++)
235 {
236 if (*r == '\n' || *r == '\0')
237 return;
238 }
239 h = ++r;
240 for (; *r != '"'; r++) ;
241 *r = 0;
242 if (*h == '\0')
243 idlc()->setFileName("standard input");
244 else
245 idlc()->setFileName(OString(h));
246
247 bIsInMain = idlc()->getFileName() == idlc()->getRealFileName();
248 idlc()->setInMainfile(bIsInMain);
249 }
250
251 // Suppress any warnings from generated code:
252 #ifdef __GNUC__
253 #pragma GCC diagnostic ignored "-Wunused-function"
254 #pragma GCC diagnostic ignored "-Wunused-label"
255 #elif defined _MSC_VER
256 /**/
257 #ifdef yywrap
258 #undef yywrap
259 #define yywrap() 1
260 #endif
261 /**/
262 #endif
263 #define YY_NO_UNISTD_H
264 %}
265
266 %option noyywrap
267 %option never-interactive
268
269 %x DOCU
270 %x COMMENT
271
272 DIGIT [0-9]
273 OCT_DIGIT [0-7]
274 HEX_DIGIT [a-fA-F0-9]
275 CAPITAL [A-Z]
276 ALPHA [a-zA-Z]
277 INT_LITERAL [1-9][0-9]*
278 OCT_LITERAL 0{OCT_DIGIT}*
279 HEX_LITERAL (0x|0X){HEX_DIGIT}*
280
281 IDENTIFIER_NEW ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*)
282 IDENTIFIER ("_"?({ALPHA}|{DIGIT})+)*
283
284 %%
285
286 [ \t\r]+ ; /* eat up whitespace */
287 [\n] {
288 idlc()->incLineNumber();
289 yycolumn = 1;
290 yylineno++;
291 }
292
293 attribute return IDL_ATTRIBUTE;
294 bound return IDL_BOUND;
295 const return IDL_CONST;
296 constants return IDL_CONSTANTS;
297 constrained return IDL_CONSTRAINED;
298 enum return IDL_ENUM;
299 exception return IDL_EXCEPTION;
300 interface return IDL_INTERFACE;
301 maybeambiguous return IDL_MAYBEAMBIGUOUS;
302 maybedefault return IDL_MAYBEDEFAULT;
303 maybevoid return IDL_MAYBEVOID;
304 module return IDL_MODULE;
305 needs return IDL_NEEDS;
306 observes return IDL_OBSERVES;
307 optional return IDL_OPTIONAL;
308 property return IDL_PROPERTY;
309 raises return IDL_RAISES;
310 readonly return IDL_READONLY;
311 removable return IDL_REMOVABLE;
312 service return IDL_SERVICE;
313 sequence return IDL_SEQUENCE;
314 singleton return IDL_SINGLETON;
315 struct return IDL_STRUCT;
316 transient return IDL_TRANSIENT;
317 typedef return IDL_TYPEDEF;
318
319 any return IDL_ANY;
320 boolean return IDL_BOOLEAN;
321 byte return IDL_BYTE;
322 char return IDL_CHAR;
323 double return IDL_DOUBLE;
324 float return IDL_FLOAT;
325 hyper return IDL_HYPER;
326 long return IDL_LONG;
327 short return IDL_SHORT;
328 string return IDL_STRING;
329 type return IDL_TYPE;
330 unsigned return IDL_UNSIGNED;
331 void return IDL_VOID;
332
333 TRUE return IDL_TRUE;
334 True return IDL_TRUE;
335 FALSE return IDL_FALSE;
336 False return IDL_FALSE;
337
338 in return IDL_IN;
339 out return IDL_OUT;
340 inout return IDL_INOUT;
341
342 get return IDL_GET;
343 set return IDL_SET;
344
345 published 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)(("+"|"-")?{DIGIT}+)?(f|F)? |
362 ("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)? {
363 yylval.dval = asciiToFloat( yytext );
364 return IDL_FLOATING_PT_LITERAL;
365 }
366
367 {IDENTIFIER} {
368 yylval.sval = new OString(yytext);
369 return IDL_IDENTIFIER;
370 }
371
372 \<\< {
373 yylval.strval = yytext;
374 return IDL_LEFTSHIFT;
375 }
376 \>\> {
377 yylval.strval = yytext;
378 return IDL_RIGHTSHIFT;
379 }
380 \:\: {
381 yylval.strval = yytext;
382 return IDL_SCOPESEPARATOR;
383 }
384
385 "/*" {
386 BEGIN( COMMENT );
387 docu = OString();
388 beginLine = idlc()->getLineNumber();
389 }
390
391 "/***" {
392 BEGIN( COMMENT );
393 docu = OString();
394 beginLine = idlc()->getLineNumber();
395 }
396
397 <COMMENT>[^*]+ {
398 docu += OString(yytext);
399 }
400
401 <COMMENT>"*"[^*/]+ {
402 docu += OString(yytext);
403 }
404
405 <COMMENT>"**" {
406 docu += OString(yytext);
407 }
408
409 <COMMENT>[*]+"/" {
410 docu = docu.trim();
411 sal_Int32 nIndex = 0;
412 int count = 0;
413 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
414 idlc()->setLineNumber( beginLine + count - 1);
415 BEGIN( INITIAL );
416 }
417
418 "/**" {
419 BEGIN( DOCU );
420 docu = OString();
421 beginLine = idlc()->getLineNumber();
422 }
423
424 <DOCU>[^*\n]+ {
425 docu += OString(yytext);
426 }
427
428 <DOCU>"\n"[ \t]*"*"{1} {
429 idlc()->setLineNumber( idlc()->getLineNumber() + 1);
430 docu += OString("\n");
431 }
432
433 <DOCU>"\n" {
434 idlc()->setLineNumber( idlc()->getLineNumber() + 1);
435 docu += OString(yytext);
436 }
437
438 <DOCU>"*"[^*^/\n]* {
439 docu += OString(yytext);
440 }
441
442 <DOCU>"\n"[ \t]*"*/" {
443 docu = docu.trim();
444 sal_Int32 nIndex = 0;
445 int count = 0;
446 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
447 idlc()->setLineNumber( beginLine + count - 1);
448 if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 )
449 {
450 if ( 0 != nIndex &&
451 (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') )
452 ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(),
453 "nested documentation strings are not allowed!");
454 }
455 idlc()->setDocumentation(docu);
456 BEGIN( INITIAL );
457 }
458
459 <DOCU>"*/" {
460 docu = docu.trim();
461 sal_Int32 nIndex = 0;
462 int count = 0;
463 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
464 idlc()->setLineNumber( beginLine + count - 1);
465 if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 )
466 {
467 if ( 0 != nIndex &&
468 (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') )
469 ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(),
470 "nested documentation strings are not allowed!");
471 }
472 idlc()->setDocumentation(docu);
473 BEGIN( INITIAL );
474 }
475
476 "//"[^/]{1}.*"\n" {
477 /* only a comment */
478 OString docStr(yytext);
479 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
480 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
481 docStr = docStr.trim();
482 idlc()->incLineNumber();
483 }
484
485 "///".*"\n" {
486 OString docStr(yytext);
487 docStr = docStr.copy( 0, docStr.lastIndexOf('\n') );
488 docStr = docStr.copy( docStr.lastIndexOf('/')+1 );
489 docStr = docStr.trim();
490 idlc()->incLineNumber();
491 idlc()->setDocumentation(docStr);
492 }
493
494 . return yytext[0];
495
496 ^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
497 parseLineAndFile(yytext);
498 }
499
500 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n {
501 parseLineAndFile(yytext);
502 }
503
504 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
505 parseLineAndFile(yytext);
506 }
507
508 ^#[ \t]*[0-9]*\n {
509 parseLineAndFile(yytext);
510 }
511
512 ^#[ \t]*ident.*\n {
513 /* ignore cpp ident */
514 idlc()->incLineNumber();
515 }
516
517 ^#[ \t]*pragma[ \t].*\n { /* remember pragma */
518 idlParsePragma(yytext);
519 idlc()->incLineNumber();
520 }
521
522 %%
523
524 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
525