summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/src/Slice/Grammar.y164
-rw-r--r--cpp/src/Slice/GrammarUtil.h28
-rw-r--r--cpp/src/Slice/Scanner.l160
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;
}
}