%{ // ********************************************************************** // // Copyright (c) 2001 // Mutable Realms, Inc. // Huntsville, AL, USA // // All Rights Reserved // // ********************************************************************** #include // Before Grammer.h, so that YYSTYPE is defined #include #include #include #include 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(); } #define YY_USER_INIT initScanner(); %} %option noyywrap %option never-interactive 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]? %% ^"#"[[:blank:]]*[[:digit:]]+[[:blank:]]*$ { unit->scanPosition(yytext); } ^"#"[[:blank:]]*[[:digit:]]+[[:blank:]]+"\""[^\"]*"\"".*$ { unit->scanPosition(yytext); } ^"#"[[:blank:]]*"line"[[:blank:]]+[[:digit:]]+[[:blank:]]*$ { unit->scanPosition(yytext); } ^"#"[[:blank:]]*"line"[[:blank:]]+[[:digit:]]+[[:blank:]]+"\""[^\"]*"\"".*$ { unit->scanPosition(yytext); } "//" { // C++-style comment int c; do { c = yyinput(); if(c == '\n') { unit->nextLine(); } } while(c != '\n' && c != EOF); } "/*" { // C-style comment 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); } } "::" { return ICE_SCOPE_DELIMITOR; } \\?[[:alpha:]_][[:alnum:]_]* { StringTokPtr ident = new StringTok; if(*yytext == '\\') // Backslash escapes keyword meaning { ident->v = yytext + 1; *yylvalp = ident; return ICE_IDENTIFIER; } else { ident->v = yytext; *yylvalp = ident; } StringTokenMap::const_iterator pos = keywordMap.find(ident->v); if(pos != keywordMap.end()) { if(pos->first != ident->v) { string msg; msg = "illegal identifier: `" + ident->v + "' differs from keyword `"; msg += pos->first + "' only in capitalization"; unit->error(msg); ident->v = pos->first; } return pos->second; } return ICE_IDENTIFIER; } \" { StringTokPtr str = new StringTok; while(true) { char c = static_cast(yyinput()); 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()); 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) { 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); } str->v += static_cast(us); break; } case 'x': { IceUtil::Int64 ull = 0; while(isxdigit(next = static_cast(yyinput()))) { ull *= 16; if(isdigit(next)) { ull += next - '0'; } else if(islower(next)) { ull += next - 'a' + 10; } else { ull += next - 'A' + 10; } } unput(next); 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} { IntegerTokPtr itp = new IntegerTok; *yylvalp = itp; errno = 0; itp->v = IceUtil::strToInt64(yytext, 0, 0); if(errno == ERANGE && (itp->v == IceUtil::Int64Min || itp->v == IceUtil::Int64Max)) { string msg = "integer constant `"; msg += yytext; msg += "' out of range"; unit->error(msg); } return ICE_INTEGER_LITERAL; } {floating_literal} { errno = 0; FloatingTokPtr ftp = new FloatingTok; *yylvalp = ftp; string literal(yytext); 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:]] { // Igore white-space if(yytext[0] == '\n') { unit->nextLine(); } } . { 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; } }