/** * 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 #include #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"); }