summaryrefslogtreecommitdiff
path: root/cpp/src/Slice/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/Slice/Parser.cpp')
-rwxr-xr-xcpp/src/Slice/Parser.cpp172
1 files changed, 143 insertions, 29 deletions
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp
index d8418db67c1..881353ef07b 100755
--- a/cpp/src/Slice/Parser.cpp
+++ b/cpp/src/Slice/Parser.cpp
@@ -1054,37 +1054,27 @@ Slice::Container::createEnum(const string& name, bool local, NodeType nt)
EnumeratorPtr
Slice::Container::createEnumerator(const string& name)
{
- checkIdentifier(name);
-
- ContainedList matches = _unit->findContents(thisScope() + name);
- if(!matches.empty())
+ EnumeratorPtr p = validateEnumerator(name);
+ if(p)
{
- EnumeratorPtr p = EnumeratorPtr::dynamicCast(matches.front());
- if(p)
- {
- if(_unit->ignRedefs())
- {
- p->updateIncludeLevel();
- return p;
- }
- }
- if(matches.front()->name() == name)
- {
- string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name();
- msg += "' as enumerator";
- _unit->error(msg);
- }
- else
- {
- string msg = "enumerator `" + name + "' differs only in capitalization from ";
- msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'";
- _unit->error(msg);
- }
+ return p;
}
- nameIsLegal(name, "enumerator"); // Don't return here -- we create the enumerator anyway.
+ p = new Enumerator(this, name);
+ _contents.push_back(p);
+ return p;
+}
- EnumeratorPtr p = new Enumerator(this, name);
+EnumeratorPtr
+Slice::Container::createEnumerator(const string& name, int value)
+{
+ EnumeratorPtr p = validateEnumerator(name);
+ if(p)
+ {
+ return p;
+ }
+
+ p = new Enumerator(this, name, value);
_contents.push_back(p);
return p;
}
@@ -2609,6 +2599,42 @@ Slice::Container::validateConstant(const string& name, const TypePtr& type, cons
return true;
}
+EnumeratorPtr
+Slice::Container::validateEnumerator(const string& name)
+{
+ checkIdentifier(name);
+
+ ContainedList matches = _unit->findContents(thisScope() + name);
+ if(!matches.empty())
+ {
+ EnumeratorPtr p = EnumeratorPtr::dynamicCast(matches.front());
+ if(p)
+ {
+ if(_unit->ignRedefs())
+ {
+ p->updateIncludeLevel();
+ return p;
+ }
+ }
+ if(matches.front()->name() == name)
+ {
+ string msg = "redefinition of " + matches.front()->kindOf() + " `" + matches.front()->name();
+ msg += "' as enumerator";
+ _unit->error(msg);
+ }
+ else
+ {
+ string msg = "enumerator `" + name + "' differs only in capitalization from ";
+ msg += matches.front()->kindOf() + " `" + matches.front()->name() + "'";
+ _unit->error(msg);
+ }
+ }
+
+ nameIsLegal(name, "enumerator"); // Don't return here -- we create the enumerator anyway.
+
+ return 0;
+}
+
// ----------------------------------------------------------------------
// Module
// ----------------------------------------------------------------------
@@ -4586,12 +4612,75 @@ void
Slice::Enum::setEnumerators(const EnumeratorList& ens)
{
_enumerators = ens;
+ int lastValue = -1;
+ set<int> values;
for(EnumeratorList::iterator p = _enumerators.begin(); p != _enumerators.end(); ++p)
{
(*p)->_type = this;
+
+ if((*p)->_explicitValue)
+ {
+ _explicitValue = true;
+
+ if((*p)->_value < 0)
+ {
+ string msg = "value for enumerator `" + (*p)->name() + "' is out of range";
+ _unit->error(msg);
+ }
+ }
+ else
+ {
+ if(lastValue == Int32Max)
+ {
+ string msg = "value for enumerator `" + (*p)->name() + "' is out of range";
+ _unit->error(msg);
+ }
+
+ //
+ // If the enumerator was not assigned an explicit value, we automatically assign
+ // it one more than the previous enumerator.
+ //
+ (*p)->_value = lastValue + 1;
+ }
+
+ if(values.count((*p)->_value) != 0)
+ {
+ string msg = "enumerator `" + (*p)->name() + "' has a duplicate value";
+ _unit->error(msg);
+ }
+ values.insert((*p)->_value);
+
+ lastValue = (*p)->_value;
+
+ if(lastValue > _maxValue)
+ {
+ _maxValue = lastValue;
+ }
+ if(lastValue < _minValue)
+ {
+ _minValue = lastValue;
+ }
}
}
+bool
+Slice::Enum::explicitValue() const
+{
+ return _explicitValue;
+}
+
+int
+Slice::Enum::minValue() const
+{
+ return static_cast<int>(_minValue);
+}
+
+int
+Slice::Enum::maxValue() const
+{
+ return static_cast<int>(_maxValue);
+}
+
Contained::ContainedType
Slice::Enum::containedType() const
{
@@ -4644,7 +4733,10 @@ Slice::Enum::Enum(const ContainerPtr& container, const string& name, bool local)
SyntaxTreeBase(container->unit()),
Type(container->unit()),
Contained(container, name),
- Constructed(container, name, local)
+ Constructed(container, name, local),
+ _explicitValue(false),
+ _minValue(Int32Max),
+ _maxValue(0)
{
}
@@ -4676,9 +4768,31 @@ Slice::Enumerator::kindOf() const
return "enumerator";
}
+bool
+Slice::Enumerator::explicitValue() const
+{
+ return _explicitValue;
+}
+
+int
+Slice::Enumerator::value() const
+{
+ return _value;
+}
+
Slice::Enumerator::Enumerator(const ContainerPtr& container, const string& name) :
SyntaxTreeBase(container->unit()),
- Contained(container, name)
+ Contained(container, name),
+ _explicitValue(false),
+ _value(-1)
+{
+}
+
+Slice::Enumerator::Enumerator(const ContainerPtr& container, const string& name, int value) :
+ SyntaxTreeBase(container->unit()),
+ Contained(container, name),
+ _explicitValue(true),
+ _value(value)
{
}