1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
24 * scanner.ll - Lexical scanner for IDLC 1.0
27 #include <sal/config.h>
32 #include <o3tl/safeint.hxx>
33 #include <rtl/character.hxx>
36 #pragma warning ( push )
37 // Silence warnings about redefinition of INT8_MIN etc in stdint.h
38 // The flex-generated workdir/LexTarget/idlc/source/scanner.cxx defines them prior to these includes
39 #pragma warning ( disable : 4005 )
43 #pragma warning ( pop )
45 #include <errorhandler.hxx>
46 #include <fehelper.hxx>
48 #include "attributeexceptions.hxx"
56 /* handle locations */
57 static int yycolumn = 1;
59 #define YY_USER_ACTION idlc()->setOffset(yycolumn, yycolumn+yyleng-1); \
62 static sal_Int32 beginLine = 0;
65 static int asciiToInteger(char const * s, sal_Int64 * sval, sal_uInt64 * uval) {
71 unsigned int base = 10;
75 if (*s == 'X' || *s == 'x') {
81 for (; *s != 0; ++s) {
83 if (*s >= '0' && *s <= '9') {
115 // The following guarantees the invariant val <= SAL_MAX_UINT64 (because
116 // base and n are sufficiently small), *if*
117 // std::numeric_limits<sal_uInt64>::max() == SAL_MAX_UINT64:
118 sal_uInt64 nval = val * base + n;
120 ErrorHandler::syntaxError(
121 PS_NoState, idlc()->getLineNumber(),
122 "integral constant too large");
130 if (val < SAL_CONST_UINT64(0x8000000000000000)) {
131 *sval = -static_cast< sal_Int64 >(val);
132 } else if (val == SAL_CONST_UINT64(0x8000000000000000)) {
133 *sval = SAL_MIN_INT64;
135 ErrorHandler::syntaxError(
136 PS_NoState, idlc()->getLineNumber(),
137 "negative integral constant too large");
140 return IDL_INTEGER_LITERAL;
141 } else if (val <= o3tl::make_unsigned(SAL_MAX_INT64)) {
142 *sval = static_cast< sal_Int64 >(val);
143 return IDL_INTEGER_LITERAL;
146 return IDL_INTEGER_ULITERAL;
150 static double asciiToFloat(const char *s)
161 while (*s >= '0' && *s <= '9')
163 d = (d * 10) + *s - '0';
170 while (*s >= '0' && *s <= '9')
172 d += (*s - '0') / (e * 1.0);
177 if (*s == 'e' || *s == 'E')
188 while (*s >= '0' && *s <= '9')
190 e = (e * 10) + *s - '0';
195 for (k = 1; e > 0; k *= 10, e--)
205 static void idlParsePragma(char* pPragma)
207 OString pragma(pPragma);
208 sal_Int32 index = pragma.indexOf("include");
209 char* begin = pPragma + index + 8;
210 char* offset = begin;
211 while (*offset != ',') offset++;
212 //OString include = pragma.copy(index + 8, offset - begin);
213 //unused// idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin)));
216 static void parseLineAndFile(char* pBuf)
220 bool bIsInMain = false;
222 /* Skip initial '#' */
226 /* Find line number */
227 for (r++; *r == ' ' || *r == '\t' || rtl::isAsciiAlpha(static_cast<unsigned char>(*r)); r++) ;
229 for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ;
231 idlc()->setLineNumber(sal_uInt32(atol(h)));
234 /* Find file name, if present */
235 for (; *r != '"'; r++)
237 if (*r == '\n' || *r == '\0')
241 for (; *r != '"'; r++) ;
244 idlc()->setFileName("standard input");
246 idlc()->setFileName(OString(h));
248 bIsInMain = idlc()->getFileName() == idlc()->getRealFileName();
249 idlc()->setInMainfile(bIsInMain);
252 // Suppress any warnings from generated code:
254 #pragma GCC diagnostic ignored "-Wunused-function"
255 #pragma GCC diagnostic ignored "-Wunused-label"
256 #elif defined _MSC_VER
264 #define YY_NO_UNISTD_H
268 %option never-interactive
275 HEX_DIGIT [a-fA-F0-9]
278 INT_LITERAL [1-9][0-9]*
279 OCT_LITERAL 0{OCT_DIGIT}*
280 HEX_LITERAL (0x|0X){HEX_DIGIT}*
282 IDENTIFIER_NEW ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*)
283 IDENTIFIER ("_"?({ALPHA}|{DIGIT})+)*
287 [ \t\r]+ ; /* eat up whitespace */
289 idlc()->incLineNumber();
294 attribute return IDL_ATTRIBUTE;
295 bound return IDL_BOUND;
296 const return IDL_CONST;
297 constants return IDL_CONSTANTS;
298 constrained return IDL_CONSTRAINED;
299 enum return IDL_ENUM;
300 exception return IDL_EXCEPTION;
301 interface return IDL_INTERFACE;
302 maybeambiguous return IDL_MAYBEAMBIGUOUS;
303 maybedefault return IDL_MAYBEDEFAULT;
304 maybevoid return IDL_MAYBEVOID;
305 module return IDL_MODULE;
306 needs return IDL_NEEDS;
307 observes return IDL_OBSERVES;
308 optional return IDL_OPTIONAL;
309 property return IDL_PROPERTY;
310 raises return IDL_RAISES;
311 readonly return IDL_READONLY;
312 removable return IDL_REMOVABLE;
313 service return IDL_SERVICE;
314 sequence return IDL_SEQUENCE;
315 singleton return IDL_SINGLETON;
316 struct return IDL_STRUCT;
317 transient return IDL_TRANSIENT;
318 typedef return IDL_TYPEDEF;
321 boolean return IDL_BOOLEAN;
322 byte return IDL_BYTE;
323 char return IDL_CHAR;
324 double return IDL_DOUBLE;
325 float return IDL_FLOAT;
326 hyper return IDL_HYPER;
327 long return IDL_LONG;
328 short return IDL_SHORT;
329 string return IDL_STRING;
330 type return IDL_TYPE;
331 unsigned return IDL_UNSIGNED;
332 void return IDL_VOID;
334 TRUE return IDL_TRUE;
335 True return IDL_TRUE;
336 FALSE return IDL_FALSE;
337 False return IDL_FALSE;
341 inout return IDL_INOUT;
346 published return IDL_PUBLISHED;
348 "..." return IDL_ELLIPSIS;
350 ("-")?{INT_LITERAL}+(l|L|u|U)? {
351 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
354 ("-")?{OCT_LITERAL}+(l|L|u|U)? {
355 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
358 ("-")?{HEX_LITERAL}+(l|L|u|U)? {
359 return asciiToInteger(yytext, &yylval.ival, &yylval.uval);
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;
369 yylval.sval = new OString(yytext);
370 return IDL_IDENTIFIER;
374 yylval.strval = yytext;
375 return IDL_LEFTSHIFT;
378 yylval.strval = yytext;
379 return IDL_RIGHTSHIFT;
382 yylval.strval = yytext;
383 return IDL_SCOPESEPARATOR;
389 beginLine = idlc()->getLineNumber();
395 beginLine = idlc()->getLineNumber();
412 sal_Int32 nIndex = 0;
414 do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 );
415 idlc()->setLineNumber( beginLine + count - 1);
422 beginLine = idlc()->getLineNumber();
429 <DOCU>"\n"[ \t]*"*"{1} {
430 idlc()->setLineNumber( idlc()->getLineNumber() + 1);
435 idlc()->setLineNumber( idlc()->getLineNumber() + 1);
443 <DOCU>"\n"[ \t]*"*/" {
445 sal_Int32 nIndex = 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 )
452 (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') )
453 ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(),
454 "nested documentation strings are not allowed!");
456 idlc()->setDocumentation(docu);
462 sal_Int32 nIndex = 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 )
469 (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') )
470 ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(),
471 "nested documentation strings are not allowed!");
473 idlc()->setDocumentation(docu);
479 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();
487 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);
497 ^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
498 parseLineAndFile(yytext);
501 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n {
502 parseLineAndFile(yytext);
505 ^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n {
506 parseLineAndFile(yytext);
510 parseLineAndFile(yytext);
514 /* ignore cpp ident */
515 idlc()->incLineNumber();
518 ^#[ \t]*pragma[ \t].*\n { /* remember pragma */
519 idlParsePragma(yytext);
520 idlc()->incLineNumber();
525 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */