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