%{ // ********************************************************************** // // Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #include // Before Grammer.h, so that YYSTYPE is defined #include #include #include #include #if defined(_MSC_VER) && defined(ICE_64) // // '=' : conversion from 'size_t' to 'int', possible loss of data // The result of fread() is a size_t and gets inserted into an int // # pragma warning( 4 : 4267 ) // // 'initializing' : conversion from '__int64' to 'int', possible loss of data // Puts a pointer-difference into an int // # pragma warning( 4 : 4244 ) #endif #ifdef _MSC_VER # ifdef slice_wrap # undef slice_wrap # define slice_wrap() 1 # endif # define YY_NO_UNISTD_H #endif using namespace std; using namespace Slice; namespace Slice { // // Definitions for the case-insensitive keyword-token map. // typedef std::map StringTokenMap; static StringTokenMap keywordMap; void initScanner(); int checkKeyword(string&); } #define YY_USER_INIT initScanner(); %} %option noyywrap %option never-interactive %option prefix="slice_" %option outfile="lex.yy.c" identifier \\?[[:alpha:]_][[:alnum:]_]* integer_constant (\+|-)?((0[0-7]+)|(0x[[:xdigit:]]+)|([[:digit:]]+)) fractional_constant (\+|-)?(([[:digit:]]*\.[[:digit:]]+)|([[:digit:]]+\.)) exponent_part (e|E)(\+|-)?[[:digit:]]+ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{exponent_part}))[fF]? %s BOMSCAN %s MAINSCAN %% ^"#"[[:blank:]]*[[:digit:]]+[[:blank:]]*$ { if(unit->scanPosition(yytext)) { BEGIN(BOMSCAN); } } ^"#"[[:blank:]]*[[:digit:]]+[[:blank:]]+"\""[^\"]*"\"".*$ { if(unit->scanPosition(yytext)) { BEGIN(BOMSCAN); } } ^"#"[[:blank:]]*"line"[[:blank:]]+[[:digit:]]+[[:blank:]]*$ { if(unit->scanPosition(yytext)) { BEGIN(BOMSCAN); } } ^"#"[[:blank:]]*"line"[[:blank:]]+[[:digit:]]+[[:blank:]]+"\""[^\"]*"\"".*$ { if(unit->scanPosition(yytext)) { BEGIN(BOMSCAN); } } "//" { // C++-style comment BEGIN(MAINSCAN); int c; do { c = yyinput(); if(c == '\n') { unit->nextLine(); } } while(c != '\n' && c != EOF); } "/*" { // C-style comment BEGIN(MAINSCAN); string comment = yytext + 2; while(true) { int c = yyinput(); if(c == '\n') { comment += static_cast(c); unit->nextLine(); } else if(c == '*') { int next = yyinput(); if(next == '/') { break; } else { comment += static_cast(c); unput(next); } } else if(c == EOF) { unit->warning("EOF in comment"); break; } else { comment += static_cast(c); } } if(comment[0] == '*') { unit->setComment(comment); } } "::" { BEGIN(MAINSCAN); return ICE_SCOPE_DELIMITER; } "[" { BEGIN(MAINSCAN); return ICE_METADATA_OPEN; } "]" { BEGIN(MAINSCAN); return ICE_METADATA_CLOSE; } "[[" { BEGIN(MAINSCAN); return ICE_GLOBAL_METADATA_OPEN; } "]]" { BEGIN(MAINSCAN); return ICE_GLOBAL_METADATA_CLOSE; } {identifier}[[:space:]]*"(" { BEGIN(MAINSCAN); StringTokPtr ident = new StringTok; ident->v = *yytext == '\\' ? yytext + 1 : yytext; ident->v.erase(ident->v.find_first_of(" \t\v\n\r\f(")); *yylvalp = ident; if(*yytext == '\\') { return ICE_IDENT_OP; } int st = checkKeyword(ident->v); if(st == ICE_IDENTIFIER) { return ICE_IDENT_OP; } else if(st == ICE_OPTIONAL) { return ICE_OPTIONAL_OP; } else { return ICE_KEYWORD_OP; } } {identifier} { BEGIN(MAINSCAN); StringTokPtr ident = new StringTok; ident->v = *yytext == '\\' ? yytext + 1 : yytext; *yylvalp = ident; return *yytext == '\\' ? ICE_IDENTIFIER : checkKeyword(ident->v); } \" { BEGIN(MAINSCAN); StringTokPtr str = new StringTok; str->literal = "\""; while(true) { char c = static_cast(yyinput()); str->literal += c; if(c == '"') { break; } else if(c == EOF) { unit->error("EOF in string"); break; } else if(c == '\n') { unit->error("newline in string"); } else if(c == '\\') { char next = static_cast(yyinput()); str->literal += next; switch(next) { case '\\': case '"': case '\'': { str->v += next; break; } case 'n': { str->v += '\n'; break; } case 'r': { str->v += '\r'; break; } case 't': { str->v += '\t'; break; } case 'v': { str->v += '\v'; break; } case 'f': { str->v += '\f'; break; } case 'a': { str->v += '\a'; break; } case 'b': { str->v += '\b'; break; } case '?': { str->v += '\?'; break; } case '0': case '1': case '2': case '3': { static string octalDigits = "01234567"; unsigned short us = next - '0'; if(octalDigits.find_first_of(next = static_cast(yyinput())) != string::npos) { str->literal += next; us = us * 8 + next - '0'; if(octalDigits.find_first_of(next = static_cast(yyinput())) != string::npos) { us = us * 8 + next - '0'; } else { unput(next); } } else { unput(next); } if(us == 0) { unit->error("illegal NUL character in string constant"); } str->v += static_cast(us); break; } case 'x': { IceUtil::Int64 ull = 0; while(isxdigit(static_cast(next = static_cast(yyinput())))) { str->literal += next; ull *= 16; if(isdigit(static_cast(next))) { ull += next - '0'; } else if(islower(static_cast(next))) { ull += next - 'a' + 10; } else { ull += next - 'A' + 10; } } unput(next); if(ull == 0) { unit->error("illegal NUL character in string constant"); } str->v += static_cast(ull); break; } // TODO: add universal character names default: { str->v += c; unput(next); } } } else { str->v += c; } } *yylvalp = str; return ICE_STRING_LITERAL; } {integer_constant} { BEGIN(MAINSCAN); IntegerTokPtr itp = new IntegerTok; itp->literal = string(yytext); *yylvalp = itp; if(!IceUtilInternal::stringToInt64(string(yytext), itp->v)) { assert(itp->v != 0); string msg = "integer constant `"; msg += yytext; msg += "' out of range"; unit->error(msg); } return ICE_INTEGER_LITERAL; } {floating_literal} { BEGIN(MAINSCAN); errno = 0; FloatingTokPtr ftp = new FloatingTok; *yylvalp = ftp; string literal(yytext); ftp->literal = literal; char lastChar = literal[literal.size() - 1]; if(lastChar == 'f' || lastChar == 'F') { literal = literal.substr(0, literal.size() - 1); // Clobber trailing 'f' or 'F' suffix } ftp->v = strtod(literal.c_str(), 0); if((ftp->v == HUGE_VAL || ftp->v == -HUGE_VAL) && errno == ERANGE) { string msg = "floating-point constant `"; msg += yytext; msg += "' too large (overflow)"; unit->error(msg); } else if(ftp->v == 0 && errno == ERANGE) { string msg = "floating-point constant `"; msg += yytext; msg += "' too small (underflow)"; unit->error(msg); } return ICE_FLOATING_POINT_LITERAL; } [[:space:]] { // Ignore white-space if(unit->currentLine() != 0) { BEGIN(MAINSCAN); } if(yytext[0] == '\n') { unit->nextLine(); } } ^"\357\273\277" { // Ignore UTF-8 BOM, rule only active when parsing start of file. BEGIN(MAINSCAN); } . { BEGIN(MAINSCAN); if(yytext[0] < 32 || yytext[0] > 126) { stringstream s; s << "illegal input character: '\\"; s.width(3); s.fill('0'); s << oct << static_cast(static_cast(yytext[0])); s << "'"; unit->error(s.str()); return BAD_CHAR; } return yytext[0]; } %% namespace Slice { // // initScanner() fills the keyword map with all keyword-token pairs. // void initScanner() { keywordMap["module"] = ICE_MODULE; keywordMap["class"] = ICE_CLASS; keywordMap["interface"] = ICE_INTERFACE; keywordMap["exception"] = ICE_EXCEPTION; keywordMap["struct"] = ICE_STRUCT; keywordMap["sequence"] = ICE_SEQUENCE; keywordMap["dictionary"] = ICE_DICTIONARY; keywordMap["enum"] = ICE_ENUM; keywordMap["out"] = ICE_OUT; keywordMap["extends"] = ICE_EXTENDS; keywordMap["implements"] = ICE_IMPLEMENTS; keywordMap["throws"] = ICE_THROWS; keywordMap["void"] = ICE_VOID; keywordMap["byte"] = ICE_BYTE; keywordMap["bool"] = ICE_BOOL; keywordMap["short"] = ICE_SHORT; keywordMap["int"] = ICE_INT; keywordMap["long"] = ICE_LONG; keywordMap["float"] = ICE_FLOAT; keywordMap["double"] = ICE_DOUBLE; keywordMap["string"] = ICE_STRING; keywordMap["Object"] = ICE_OBJECT; keywordMap["LocalObject"] = ICE_LOCAL_OBJECT; keywordMap["local"] = ICE_LOCAL; keywordMap["const"] = ICE_CONST; keywordMap["false"] = ICE_FALSE; keywordMap["true"] = ICE_TRUE; keywordMap["idempotent"] = ICE_IDEMPOTENT; keywordMap["optional"] = ICE_OPTIONAL; } // // Check if an identifier looks like a keyword. // If the identifier is a keyword, return the // corresponding keyword token; otherwise, return // an identifier token. // int checkKeyword(string& id) { StringTokenMap::const_iterator pos = keywordMap.find(id); if(pos != keywordMap.end()) { if(pos->first != id) { string msg; msg = "illegal identifier: `" + id + "' differs from keyword `"; msg += pos->first + "' only in capitalization"; unit->error(msg); id = pos->first; } return pos->second; } return ICE_IDENTIFIER; } }