tars2node/third_partly/tarsparse/element.cpp
2020-03-15 18:09:51 +08:00

340 lines
8.2 KiB
C++

/**
* Tencent is pleased to support the open source community by making Tars available.
*
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
#include "element.h"
#include <iostream>
#include <cassert>
#include "parse.h"
#include "util/tc_file.h"
#include "util/tc_common.h"
/*************************************************************************************************/
const char* Builtin::builtinTable[] =
{
"void",
"bool",
"byte",
"short",
"int",
"long",
"float",
"double",
"string",
"vector",
"map"
};
Builtin::Builtin(Kind kind,bool isUnsigned = false) : _kind(kind),_isUnsigned(isUnsigned)
{
}
Builtin::Kind Builtin::kind() const
{
return _kind;
}
bool Builtin::isSimple() const
{
switch(_kind)
{
case Builtin::KindBool:
case Builtin::KindByte:
case Builtin::KindShort:
case Builtin::KindInt:
case Builtin::KindLong:
case Builtin::KindFloat:
case Builtin::KindDouble:
return true;
default:
return false;
}
return true;
}
string Builtin::def() const
{
switch(_kind)
{
case Builtin::KindBool:
return "true";
case Builtin::KindByte:
case Builtin::KindShort:
case Builtin::KindInt:
case Builtin::KindLong:
case Builtin::KindFloat:
case Builtin::KindDouble:
return "0";
case Builtin::KindString:
return "";
default:
assert(false);
}
return "";
}
/*************************************************************************************************/
Vector::Vector(const TypePtr& ptr) : _ptr(ptr)
{
}
/*************************************************************************************************/
Map::Map(const TypePtr& pleft, const TypePtr& pright): _pleft(pleft), _pright(pright)
{
}
/*************************************************************************************************/
TypeId::TypeId(const TypePtr& ptr, const string&id)
: _ptr(ptr)
, _id(id)
, _bRequire(true)
, _tag(0)
, _bHasDefault(false)
, _size(0)
, _array(false)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(_ptr);
if(bPtr)
{
_bHasDefault = true;
_default = bPtr->def();
}
}
void TypeId::setRequire(int tag)
{
_bRequire = true;
_tag = tag;
}
void TypeId::setDefault(const string &def)
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(_ptr);
EnumPtr ePtr = EnumPtr::dynamicCast(_ptr);
assert(bPtr || ePtr);
_bHasDefault = true;
_default = def;
}
void TypeId::disableDefault()
{
BuiltinPtr bPtr = BuiltinPtr::dynamicCast(_ptr);
assert(bPtr);
_bHasDefault = false;
}
void TypeId::setOptional(int tag)
{
_bRequire = false;
_tag = tag;
}
/*************************************************************************************************/
NamespacePtr Container::createNamespace(const string &id)
{
NamespacePtr np = NamespacePtr::dynamicCast(this);
if(np)
{
g_parse->error("namespace can't be nested!");
}
_ns.push_back(new Namespace(id));
g_parse->currentContextPtr()->addNamespacePtr(_ns.back());
return _ns.back();
}
/*************************************************************************************************/
ParamDeclPtr Operation::createParamDecl(const TypeIdPtr &typeIdPtr, bool v, bool k)
{
_itag++;
if(_itag > 255)
{
g_parse->error("operation '" + _id + "' can't have more than 255 paramters!");
}
if(typeIdPtr->getId() == getId())
{
g_parse->error("paramters name '" + _id + "' conflicts with operation name!");
}
typeIdPtr->setRequire(_itag);
_ps.push_back(new ParamDecl(typeIdPtr, v, k));
return _ps.back();
}
/*************************************************************************************************/
OperationPtr Interface::createOperation(const string &id, const TypePtr &typePtr)
{
for(size_t i = 0; i < _ops.size(); i++)
{
if(_ops[i]->getId() == id)
{
g_parse->error("operation '" + id + "' exists in interface '" + _id + "'");
return NULL;
}
}
_ops.push_back(new Operation(id, typePtr));
return _ops.back();
}
/*************************************************************************************************/
InterfacePtr Namespace::createInterface(const string &id)
{
for(size_t i = 0; i < _is.size(); i++)
{
if(_is[i]->getId() == id)
{
g_parse->error("interface '" + id + "' exists in namespace '" + _id + "'");
return NULL;
}
}
if(id == _id)
{
g_parse->error("interface '" + id + "' must not be same with namespace '" + _id + "'");
return NULL;
}
_is.push_back(new Interface(id));
return _is.back();
}
StructPtr Namespace::createStruct(const string& id)
{
g_parse->checkConflict(_id + "::" + id);
_ss.push_back(new Struct(id, _id + "::" + id));
g_parse->addStructPtr(_ss.back());
return _ss.back();
}
EnumPtr Namespace::createEnum(const string &id)
{
g_parse->checkConflict(_id + "::" + id);
_es.push_back(new Enum(id, _id + "::" + id));
g_parse->addEnumPtr(_es.back());
return _es.back();
}
ConstPtr Namespace::createConst(TypeIdPtr &pPtr, ConstGrammarPtr &cPtr)
{
for(size_t i = 0; i < _cs.size(); i++)
{
if(_cs[i]->getTypeIdPtr()->getId() == pPtr->getId())
{
g_parse->error("const type '" + pPtr->getId() + "' exists in namespace '" + _id + "'");
return NULL;
}
}
g_parse->checkConstValue(pPtr, cPtr->t);
_cs.push_back(new Const(pPtr, cPtr));
return _cs.back();
}
/*************************************************************************************************/
void Struct::addTypeId(const TypeIdPtr &typeIdPtr)
{
StructPtr sp = StructPtr::dynamicCast(typeIdPtr->getTypePtr());
if(sp)
{
if(sp->getSid() == getSid())
{
g_parse->error("struct can't take self as member data");
}
}
for(size_t i = 0; i < _members.size(); i++)
{
if(_members[i]->getId() == typeIdPtr->getId())
{
g_parse->error("data member '" + typeIdPtr->getId() + "' duplicate definition");
}
if(_members[i]->getTag() == typeIdPtr->getTag())
{
g_parse->error("data member '" + typeIdPtr->getId() + "' has equal tag with '" + _members[i]->getId() + "'");
}
if(_members[i]->getTag() > typeIdPtr->getTag())
{
_members.insert(_members.begin() + i, typeIdPtr);
return;
}
}
_members.push_back(typeIdPtr);
}
void Struct::addKey(const string &member)
{
size_t i;
for(i = 0; i < _members.size(); i++)
{
if(_members[i]->getId() == member)
{
break;
}
}
if(i == _members.size())
{
g_parse->error("key member '" + member + "' is not struct member");
}
_key.push_back(member);
}
/***********************************************************************************/
void Enum::addMember(const TypeIdPtr &typeIdPtr)
{
for(size_t i = 0; i < _members.size(); i++)
{
if(_members[i]->getId() == typeIdPtr->getId())
{
g_parse->error("enum member '" + typeIdPtr->getId() + "' duplicate definition");
}
}
_members.push_back(typeIdPtr);
}
/***********************************************************************************/
void Context::addInclude(const string &incl)
{
if(incl == _filename)
{
g_parse->error("can't include self");
}
_includes.push_back(tars::TC_File::excludeFileExt(incl) + ".h");
}