/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ %{ /* * scanner.ll - Lexical scanner for IDLC 1.0 */ #include #include #include #ifndef _IDLC_IDLC_HXX_ #include #endif #ifndef _IDLC_ERRORHANDLER_HXX_ #include #endif #ifndef _IDLC_FEHELPER_HXX_ #include #endif #include "attributeexceptions.hxx" class AstExpression; class AstArray; class AstMember; #include sal_Int32 beginLine = 0; ::rtl::OString docu; static int asciiToInteger(char const * s, sal_Int64 * sval, sal_uInt64 * uval) { bool neg = false; if (*s == '-') { neg = true; ++s; } unsigned int base = 10; if (*s == '0') { base = 8; ++s; if (*s == 'X' || *s == 'x') { base = 16; ++s; } } sal_uInt64 val = 0; for (; *s != 0; ++s) { unsigned int n; if (*s >= '0' && *s <= '9') { n = *s - '0'; } else { switch (*s) { case 'A': case 'a': n = 10; break; case 'B': case 'b': n = 11; break; case 'C': case 'c': n = 12; break; case 'D': case 'd': n = 13; break; case 'E': case 'e': n = 14; break; case 'F': case 'f': n = 15; break; default: goto done; } } // The following guarantees the invariant val <= SAL_MAX_UINT64 (because // base and n are sufficiently small), *if* // std::numeric_limits::max() == SAL_MAX_UINT64: sal_uInt64 nval = val * base + n; if (nval < val) { idlc()->error()->syntaxError( PS_NoState, idlc()->getLineNumber(), "integral constant too large"); val = 0; break; } val = nval; } done: if (neg) { if (val < SAL_CONST_UINT64(0x8000000000000000)) { *sval = -static_cast< sal_Int64 >(val); } else if (val == SAL_CONST_UINT64(0x8000000000000000)) { *sval = SAL_MIN_INT64; } else { idlc()->error()->syntaxError( PS_NoState, idlc()->getLineNumber(), "negative integral constant too large"); *sval = 0; } return IDL_INTEGER_LITERAL; } else if (val <= static_cast< sal_uInt64 >(SAL_MAX_INT64)) { *sval = static_cast< sal_Int64 >(val); return IDL_INTEGER_LITERAL; } else { *uval = val; return IDL_INTEGER_ULITERAL; } } static double asciiToFloat(const sal_Char *s) { double d = 0.0; double e, k; sal_Int32 neg = 0, negexp = 0; if (*s == '-') { neg = 1; s++; } while (*s >= '0' && *s <= '9') { d = (d * 10) + *s - '0'; s++; } if (*s == '.') { s++; e = 10; while (*s >= '0' && *s <= '9') { d += (*s - '0') / (e * 1.0); e *= 10; s++; } } if (*s == 'e' || *s == 'E') { s++; if (*s == '-') { negexp = 1; s++; } else { if (*s == '+') s++; e = 0; while (*s >= '0' && *s <= '9') { e = (e * 10) + *s - '0'; s++; } if (e > 0) { for (k = 1; e > 0; k *= 10, e--) ; if (negexp) d /= k; else d *= k; } } } if (neg) d *= -1.0; return d; } static void idlParsePragma(sal_Char* pPragma) { ::rtl::OString pragma(pPragma); sal_Int32 index = pragma.indexOf("include"); sal_Char* begin = pPragma + index + 8; sal_Char* offset = begin; while (*offset != ',') offset++; //::rtl::OString include = pragma.copy(index + 8, offset - begin); idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin))); } static void parseLineAndFile(sal_Char* pBuf) { sal_Char *r = pBuf; sal_Char *h; sal_Bool bIsInMain = sal_False; /* Skip initial '#' */ if (*r != '#') return; /* Find line number */ for (r++; *r == ' ' || *r == '\t' || isalpha(*r); r++) ; h = r; for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ; *r++ = 0; idlc()->setLineNumber((sal_uInt32)atol(h)); /* Find file name, if present */ for (; *r != '"'; r++) { if (*r == '\n' || *r == '\0') return; } h = ++r; for (; *r != '"'; r++) ; *r = 0; if (*h == '\0') idlc()->setFileName(::rtl::OString("standard input")); else idlc()->setFileName(::rtl::OString(h)); bIsInMain = (idlc()->getFileName() == idlc()->getRealFileName()) ? sal_True : sal_False; idlc()->setInMainfile(bIsInMain); } // Suppress any warnings from generated code: #if defined __GNUC__ #pragma GCC system_header #elif defined __SUNPRO_CC #pragma disable_warn #elif defined _MSC_VER #pragma warning(push, 1) /**/ #ifdef yywrap #undef yywrap #define yywrap() 1 #endif /**/ #endif %} %option noyywrap %option never-interactive %x DOCU %x COMMENT DIGIT [0-9] OCT_DIGIT [0-7] HEX_DIGIT [a-fA-F0-9] CAPITAL [A-Z] ALPHA [a-zA-Z] INT_LITERAL [1-9][0-9]* OCT_LITERAL 0{OCT_DIGIT}* HEX_LITERAL (0x|0X){HEX_DIGIT}* IDENTIFIER_NEW ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*) IDENTIFIER ("_"?({ALPHA}|{DIGIT})+)* %% [ \t\r]+ ; /* eat up whitespace */ [\n] { idlc()->incLineNumber(); } attribute return IDL_ATTRIBUTE; bound return IDL_BOUND; case return IDL_CASE; const return IDL_CONST; constants return IDL_CONSTANTS; constrained return IDL_CONSTRAINED; default return IDL_DEFAULT; enum return IDL_ENUM; exception return IDL_EXCEPTION; interface return IDL_INTERFACE; maybeambiguous return IDL_MAYBEAMBIGUOUS; maybedefault return IDL_MAYBEDEFAULT; maybevoid return IDL_MAYBEVOID; module return IDL_MODULE; needs return IDL_NEEDS; observes return IDL_OBSERVES; optional return IDL_OPTIONAL; property return IDL_PROPERTY; raises return IDL_RAISES; readonly return IDL_READONLY; removable return IDL_REMOVEABLE; service return IDL_SERVICE; sequence return IDL_SEQUENCE; singleton return IDL_SINGLETON; struct return IDL_STRUCT; switch return IDL_SWITCH; transient return IDL_TRANSIENT; typedef return IDL_TYPEDEF; union return IDL_UNION; any return IDL_ANY; boolean return IDL_BOOLEAN; byte return IDL_BYTE; char return IDL_CHAR; double return IDL_DOUBLE; float return IDL_FLOAT; hyper return IDL_HYPER; long return IDL_LONG; short return IDL_SHORT; string return IDL_STRING; type return IDL_TYPE; unsigned return IDL_UNSIGNED; void return IDL_VOID; TRUE return IDL_TRUE; True return IDL_TRUE; FALSE return IDL_FALSE; False return IDL_FALSE; in return IDL_IN; out return IDL_OUT; inout return IDL_INOUT; oneway return IDL_ONEWAY; get return IDL_GET; set return IDL_SET; published return IDL_PUBLISHED; "..." return IDL_ELLIPSIS; ("-")?{INT_LITERAL}+(l|L|u|U)? { return asciiToInteger(yytext, &yylval.ival, &yylval.uval); } ("-")?{OCT_LITERAL}+(l|L|u|U)? { return asciiToInteger(yytext, &yylval.ival, &yylval.uval); } ("-")?{HEX_LITERAL}+(l|L|u|U)? { return asciiToInteger(yytext, &yylval.ival, &yylval.uval); } ("-")?{DIGIT}+(e|E){1}(("+"|"-")?{DIGIT}+)+(f|F)? | ("-")?"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)? | ("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)? { yylval.dval = asciiToFloat( yytext ); return IDL_FLOATING_PT_LITERAL; } {IDENTIFIER} { yylval.sval = new ::rtl::OString(yytext); return IDL_IDENTIFIER; } \<\< { yylval.strval = yytext; return IDL_LEFTSHIFT; } \>\> { yylval.strval = yytext; return IDL_RIGHTSHIFT; } \:\: { yylval.strval = yytext; return IDL_SCOPESEPARATOR; } "/*" { BEGIN( COMMENT ); docu = ::rtl::OString(); beginLine = idlc()->getLineNumber(); } "/***" { BEGIN( COMMENT ); docu = ::rtl::OString(); beginLine = idlc()->getLineNumber(); } [^*]+ { docu += ::rtl::OString(yytext); } "*"[^*/]+ { docu += ::rtl::OString(yytext); } "**" { docu += ::rtl::OString(yytext); } [*]+"/" { docu = docu.trim(); sal_Int32 nIndex = 0; int count = 0; do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 ); idlc()->setLineNumber( beginLine + count - 1); BEGIN( INITIAL ); } "/**" { BEGIN( DOCU ); docu = ::rtl::OString(); beginLine = idlc()->getLineNumber(); } [^*\n]+ { docu += ::rtl::OString(yytext); } "\n"[ \t]*"*"{1} { idlc()->setLineNumber( idlc()->getLineNumber() + 1); docu += ::rtl::OString("\n"); } "\n" { idlc()->setLineNumber( idlc()->getLineNumber() + 1); docu += ::rtl::OString(yytext); } "*"[^*^/\n]* { docu += ::rtl::OString(yytext); } "\n"[ \t]*"*/" { docu = docu.trim(); sal_Int32 nIndex = 0; int count = 0; do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 ); idlc()->setLineNumber( beginLine + count - 1); if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 ) { if ( 0 != nIndex && (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') ) idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(), "nested documentation strings are not allowed!"); } idlc()->setDocumentation(docu); BEGIN( INITIAL ); } "*/" { docu = docu.trim(); sal_Int32 nIndex = 0; int count = 0; do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 ); idlc()->setLineNumber( beginLine + count - 1); if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 ) { if ( 0 != nIndex && (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') ) idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(), "nested documentation strings are not allowed!"); } idlc()->setDocumentation(docu); BEGIN( INITIAL ); } "//"[^/]{1}.*"\n" { /* only a comment */ ::rtl::OString docStr(yytext); docStr = docStr.copy( 0, docStr.lastIndexOf('\n') ); docStr = docStr.copy( docStr.lastIndexOf('/')+1 ); docStr = docStr.trim(); idlc()->incLineNumber(); } "///".*"\n" { ::rtl::OString docStr(yytext); docStr = docStr.copy( 0, docStr.lastIndexOf('\n') ); docStr = docStr.copy( docStr.lastIndexOf('/')+1 ); docStr = docStr.trim(); idlc()->incLineNumber(); idlc()->setDocumentation(docStr); } . return yytext[0]; ^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n { parseLineAndFile(yytext); } ^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n { parseLineAndFile(yytext); } ^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n { parseLineAndFile(yytext); } ^#[ \t]*[0-9]*\n { parseLineAndFile(yytext); } ^#[ \t]*ident.*\n { /* ignore cpp ident */ idlc()->incLineNumber(); } ^#[ \t]*pragma[ \t].*\n { /* remember pragma */ idlParsePragma(yytext); idlc()->incLineNumber(); } %%