diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Slice/Grammar.y | 164 | ||||
-rw-r--r-- | cpp/src/Slice/GrammarUtil.h | 28 | ||||
-rw-r--r-- | cpp/src/Slice/Scanner.l | 160 |
3 files changed, 315 insertions, 37 deletions
diff --git a/cpp/src/Slice/Grammar.y b/cpp/src/Slice/Grammar.y index 0a04428c39c..42784f560a1 100644 --- a/cpp/src/Slice/Grammar.y +++ b/cpp/src/Slice/Grammar.y @@ -60,6 +60,9 @@ yyerror(const char* s) %token ICE_OBJECT %token ICE_LOCAL_OBJECT %token ICE_LOCAL +%token ICE_CONST +%token ICE_FALSE +%token ICE_TRUE // // Other tokens. @@ -67,6 +70,8 @@ yyerror(const char* s) %token ICE_SCOPE_DELIMITOR %token ICE_IDENTIFIER %token ICE_STRING_LITERAL +%token ICE_INTEGER_LITERAL +%token ICE_FLOATING_POINT_LITERAL // // One shift/reduce conflict is caused by the presence of ICE_OUT @@ -103,10 +108,6 @@ meta_data { $$ = $2; } -| '[' ']' -{ - $$ = new StringListTok; -} | { $$ = new StringListTok; @@ -177,6 +178,9 @@ definition | enum_def { } +| const_def +{ +} ; // ---------------------------------------------------------------------- @@ -1236,16 +1240,30 @@ type ; // ---------------------------------------------------------------------- +string_literal +// ---------------------------------------------------------------------- +: ICE_STRING_LITERAL string_literal // Adjacent string literals are concatenated +{ + StringTokPtr str1 = StringTokPtr::dynamicCast($1); + StringTokPtr str2 = StringTokPtr::dynamicCast($2); + str1->v += str2->v; +} +| ICE_STRING_LITERAL +{ +} +; + +// ---------------------------------------------------------------------- string_list // ---------------------------------------------------------------------- -: ICE_STRING_LITERAL ',' string_list +: string_literal ',' string_list { StringTokPtr str = StringTokPtr::dynamicCast($1); StringListTokPtr stringList = StringListTokPtr::dynamicCast($3); stringList->v.push_back(str->v); $$ = stringList; } -| ICE_STRING_LITERAL +| string_literal { StringTokPtr str = StringTokPtr::dynamicCast($1); StringListTokPtr stringList = new StringListTok; @@ -1272,6 +1290,131 @@ local ; // ---------------------------------------------------------------------- +const_type +// ---------------------------------------------------------------------- +: ICE_BYTE +{ +} +// +// Note ICE_BOOL is deal with in const_def +// +| ICE_SHORT +{ +} +| ICE_INT +{ +} +| ICE_LONG +{ +} +| ICE_FLOAT +{ +} +| ICE_DOUBLE +{ +} +| ICE_STRING +{ +} +| ICE_ENUM +{ +} +; + +// ---------------------------------------------------------------------- +unary_plus_minus +// ---------------------------------------------------------------------- +: '+' +{ + IntegerTokPtr itp = new IntegerTok; + itp->v = 1; + $$ = itp; +} +| '-' +{ + IntegerTokPtr itp = new IntegerTok; + itp->v = -1; + $$ = itp; +} +| +{ + IntegerTokPtr itp = new IntegerTok; + itp->v = 1; + $$ = itp; +} +; + +// ---------------------------------------------------------------------- +numeric_literal +// ---------------------------------------------------------------------- +: ICE_INTEGER_LITERAL +{ +} +| ICE_FLOATING_POINT_LITERAL +{ +} +; + +// ---------------------------------------------------------------------- +const_literal +// ---------------------------------------------------------------------- +: unary_plus_minus numeric_literal +{ + IntegerTokPtr sign = IntegerTokPtr::dynamicCast($1); + IntegerTokPtr integer = IntegerTokPtr::dynamicCast($2); + if(integer) + { + if(sign->v == -1) + { + if(integer->v < 0 && integer->v == LONG_MIN) + { + string msg = "integer constant `" + integer->v; + msg += "' is too large in magnitude to convert to a positive number"; + unit->error(msg); + } + integer->v *= -1; + } + } + else + { + FloatingTokPtr floating = FloatingTokPtr::dynamicCast($2); + assert(floating); + floating->v *= sign->v; + } + $$ = $2; +} +| enumerator +{ +} +| ICE_STRING_LITERAL +{ +} +; + +// ---------------------------------------------------------------------- +const_def +// ---------------------------------------------------------------------- +: ICE_CONST const_type ICE_IDENTIFIER '=' const_literal +{ + // + //TODO: createConst, including semantic checks + // +} +| ICE_CONST ICE_BOOL ICE_IDENTIFIER '=' ICE_FALSE +{ + // + //TODO: createConst, including semantic checks + // +} +| ICE_CONST ICE_BOOL ICE_IDENTIFIER '=' ICE_TRUE +{ + // + //TODO: createConst, including semantic checks + // +} +; + +// ---------------------------------------------------------------------- keyword // ---------------------------------------------------------------------- : ICE_MODULE @@ -1346,6 +1489,15 @@ keyword | ICE_LOCAL { } +| ICE_CONST +{ +} +| ICE_FALSE +{ +} +| ICE_TRUE +{ +} ; %% diff --git a/cpp/src/Slice/GrammarUtil.h b/cpp/src/Slice/GrammarUtil.h index 591fa976eed..bc349184dc0 100644 --- a/cpp/src/Slice/GrammarUtil.h +++ b/cpp/src/Slice/GrammarUtil.h @@ -22,6 +22,8 @@ class StringListTok; class TypeStringTok; class TypeStringListTok; class BoolTok; +class IntegerTok; +class FloatingTok; class ExceptionListTok; class ClassListTok; class EnumeratorListTok; @@ -31,6 +33,8 @@ typedef ::IceUtil::Handle<StringListTok> StringListTokPtr; typedef ::IceUtil::Handle<TypeStringTok> TypeStringTokPtr; typedef ::IceUtil::Handle<TypeStringListTok> TypeStringListTokPtr; typedef ::IceUtil::Handle<BoolTok> BoolTokPtr; +typedef ::IceUtil::Handle<IntegerTok> IntegerTokPtr; +typedef ::IceUtil::Handle<FloatingTok> FloatingTokPtr; typedef ::IceUtil::Handle<ExceptionListTok> ExceptionListTokPtr; typedef ::IceUtil::Handle<ClassListTok> ClassListTokPtr; typedef ::IceUtil::Handle<EnumeratorListTok> EnumeratorListTokPtr; @@ -84,6 +88,30 @@ public: }; // ---------------------------------------------------------------------- +// IntegerTok +// ---------------------------------------------------------------------- + +class SLICE_API IntegerTok : public GrammarBase +{ +public: + + IntegerTok() { } + long v; +}; + +// ---------------------------------------------------------------------- +// FloatingTok +// ---------------------------------------------------------------------- + +class SLICE_API FloatingTok : public GrammarBase +{ +public: + + FloatingTok() { } + double v; +}; + +// ---------------------------------------------------------------------- // BoolTok // ---------------------------------------------------------------------- diff --git a/cpp/src/Slice/Scanner.l b/cpp/src/Slice/Scanner.l index 4fdc7b58d59..35264150d91 100644 --- a/cpp/src/Slice/Scanner.l +++ b/cpp/src/Slice/Scanner.l @@ -12,6 +12,7 @@ #include <Slice/GrammarUtil.h> // Before Grammer.h, so that YYSTYPE is defined #include <Slice/Grammar.h> +#include <math.h> using namespace std; using namespace Slice; @@ -36,6 +37,11 @@ void 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}))[fFlL]? + %% ^"#"[[:blank:]]*[[:digit:]]+[[:blank:]]*$ { @@ -114,15 +120,17 @@ void initScanner(); \\?[[:alpha:]_][[:alnum:]_]* { StringTokPtr ident = new StringTok; - if (*yytext == '\\') + if(*yytext == '\\') // Backslash escapes keyword meaning { ident->v = yytext + 1; + *yylvalp = ident; + return ICE_IDENTIFIER; } else { ident->v = yytext; + *yylvalp = ident; } - *yylvalp = ident; StringTokenMap::const_iterator pos = keywordMap.find(ident->v); if(pos != keywordMap.end()) @@ -141,7 +149,6 @@ void initScanner(); } \" { - // "..."-type strings StringTokPtr str = new StringTok; while(true) { @@ -152,13 +159,12 @@ void initScanner(); } else if(c == EOF) { - unit->warning("EOF in string"); + unit->error("EOF in string"); break; } else if(c == '\n') { - str->v += c; - unit->nextLine(); + unit->error("newline in string"); } else if(c == '\\') { @@ -167,6 +173,7 @@ void initScanner(); { case '\\': case '"': + case '\'': { str->v += next; break; @@ -201,6 +208,77 @@ void initScanner(); 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<char>(yyinput())) != string::npos) + { + us = us * 8 + next - '0'; + if(octalDigits.find_first_of(next = static_cast<char>(yyinput())) != string::npos) + { + us = us * 8 + next - '0'; + } + else + { + unput(next); + } + } + else + { + unput(next); + } + str->v += static_cast<char>(us); + break; + } + case 'x': + { + unsigned long ul = 0; + next = static_cast<char>(yyinput()); + if(isxdigit(next)) + { + ul *= 16; + if(isdigit(next)) + { + ul += next - '0'; + } + else if(islower(next)) + { + ul += next - 'a'; + } + else + { + ul += next - 'A'; + } + } + unput(next); + str->v += static_cast<char>(ul); + break; + } + + // TODO: add universal character names default: { @@ -218,33 +296,50 @@ void initScanner(); return ICE_STRING_LITERAL; } -\' { - // '...'-type strings - StringTokPtr str = new StringTok; - while(true) +{integer_constant} { + IntegerTokPtr itp = new IntegerTok; + *yylvalp = itp; + errno = 0; + itp->v = strtol(yytext, 0, 0); +// +// TODO: strtol() is broken under gcc: it returns an error for -2147483648 (but shouldn't) +// + if(errno == ERANGE && (itp->v == LONG_MAX || itp->v == LONG_MIN)) { - char c = static_cast<char>(yyinput()); - if(c == '\'') - { - break; - } - else if(c == EOF) - { - unit->warning("EOF in string"); - break; - } - else if(c == '\n') - { - str->v += c; - unit->nextLine(); - } - else - { - str->v += c; - } + string msg = "integer constant `"; + msg += yytext; + msg += "' too "; + msg += itp->v == LONG_MAX ? "large (overflow)" : "small (underflow)"; + unit->error(msg); } - *yylvalp = str; - return ICE_STRING_LITERAL; + return ICE_INTEGER_LITERAL; +} + +{floating_literal} { + FloatingTokPtr ftp = new FloatingTok; + *yylvalp = ftp; + errno = 0; + ftp->v = strtod(yytext, 0); + // + // TODO: think about what to do with infinity and NaN. Probably nothing because the slice compiler + // doesn't necessarily run on the same architecture as the compiled stubs/skeletons, but NaN and INF are + // architecture dependent... + // + 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:]] { @@ -295,6 +390,9 @@ initScanner() 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; } } |