parse.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. #include "parse.h"
  17. #include "tars.tab.hpp"
  18. #include <errno.h>
  19. #include <fstream>
  20. #include <string.h>
  21. #include "util/tc_common.h"
  22. #include "util/tc_file.h"
  23. TarsParsePtr g_parse = new TarsParse();
  24. void yyerror(char const *msg)
  25. {
  26. g_parse->error(msg);
  27. }
  28. TarsParse::TarsParse()
  29. {
  30. _bWithTars = false;
  31. _bUseCurrentPath = false;
  32. _itab = 0;
  33. _bUseCurrentPathFirst = false;
  34. initScanner();
  35. }
  36. void TarsParse::setTars(bool bWithTars)
  37. {
  38. _bWithTars = bWithTars;
  39. }
  40. void TarsParse::setHeader(const string &sHeader)
  41. {
  42. _sHeader = sHeader;
  43. }
  44. void TarsParse::setCurrentPriority(bool bFlag)
  45. {
  46. _bUseCurrentPathFirst = bFlag;
  47. }
  48. string TarsParse::getHeader()
  49. {
  50. if(_sHeader.empty())
  51. return _sHeader;
  52. return _sHeader + "/";
  53. }
  54. void TarsParse::clear()
  55. {
  56. while(!_contexts.empty()) _contexts.pop();
  57. while(!_contains.empty()) _contains.pop();
  58. _vcontexts.clear();
  59. _structs.clear();
  60. _enums.clear();
  61. _namespaces.clear();
  62. }
  63. void TarsParse::parse(const string& sFileName)
  64. {
  65. if (_bUseCurrentPath)
  66. {
  67. std::string sTemp = sFileName;
  68. bool isExist = tars::TC_File::isFileExist(sFileName);
  69. if (!isExist)
  70. {
  71. sTemp = tars::TC_File::extractFileName(sFileName);
  72. }
  73. clear();
  74. _contains.push(new Container(""));
  75. if(!(yyin = fopen(sTemp.c_str(), "r")))
  76. {
  77. error("open file '" + sFileName + "(" + sTemp + ")" + "' error :" + string(strerror(errno)));
  78. }
  79. pushFile(sFileName);
  80. yyparse();
  81. return ;
  82. }
  83. if (_bUseCurrentPathFirst)
  84. {
  85. std::string sTemp = tars::TC_File::extractFileName(sFileName);
  86. bool isExist = tars::TC_File::isFileExist(sTemp);
  87. if (!isExist)
  88. {
  89. sTemp = sFileName;
  90. }
  91. clear();
  92. _contains.push(new Container(""));
  93. if(!(yyin = fopen(sTemp.c_str(), "r")))
  94. {
  95. error("open file '" + sFileName + "(" + sTemp + ")" + "' error :" + string(strerror(errno)));
  96. }
  97. pushFile(sFileName);
  98. yyparse();
  99. return ;
  100. }
  101. {
  102. clear();
  103. _contains.push(new Container(""));
  104. if(!(yyin = fopen(sFileName.c_str(), "r")))
  105. {
  106. error("open file '" + sFileName + "' error :" + string(strerror(errno)));
  107. }
  108. pushFile(sFileName);
  109. yyparse();
  110. }
  111. }
  112. void TarsParse::pushFile(const string &file)
  113. {
  114. ContextPtr c = new Context(file);
  115. _contexts.push(c);
  116. _vcontexts.push_back(c);
  117. }
  118. ContextPtr TarsParse::popFile()
  119. {
  120. ContextPtr c = _contexts.top();
  121. _contexts.pop();
  122. return c;
  123. }
  124. bool TarsParse::getFilePath(const string &s, string &file)
  125. {
  126. if (_bUseCurrentPath)
  127. {
  128. if(s.length() < 2 || s[0] != '\"' || s[s.length()-1] != '\"')
  129. {
  130. error("#include need \"FILENAME\"");
  131. }
  132. file = s.substr(1, s.length() - 2);
  133. std::string sTemp = file;
  134. bool isExist = tars::TC_File::isFileExist(file);
  135. if (!isExist)
  136. {
  137. file = tars::TC_File::extractFileName(file);
  138. }
  139. for(size_t i = 0; i < _vcontexts.size(); i++)
  140. {
  141. if(_vcontexts[i]->getFileName() == file)
  142. {
  143. return false;
  144. }
  145. }
  146. return true;
  147. }
  148. if(_bUseCurrentPathFirst)
  149. {
  150. if(s.length() < 2 || s[0] != '\"' || s[s.length()-1] != '\"')
  151. {
  152. error("#include need \"FILENAME\"");
  153. }
  154. file = s.substr(1, s.length() - 2);
  155. std::string sTemp = tars::TC_File::extractFileName(file);
  156. bool isExist = tars::TC_File::isFileExist(sTemp);
  157. if (isExist)
  158. {
  159. file = sTemp;
  160. }
  161. for(size_t i = 0; i < _vcontexts.size(); i++)
  162. {
  163. if(_vcontexts[i]->getFileName() == file)
  164. {
  165. return false;
  166. }
  167. }
  168. return true;
  169. }
  170. if(s.length() < 2 || s[0] != '\"' || s[s.length()-1] != '\"')
  171. {
  172. error("#include need \"FILENAME\"");
  173. }
  174. file = s.substr(1, s.length() - 2);
  175. if (!tars::TC_File::isFileExist(file))
  176. {
  177. for (size_t i = 0; i < _vIncludePath.size(); i++)
  178. {
  179. if (tars::TC_File::isFileExist(_vIncludePath[i] + "/" + file))
  180. {
  181. file = _vIncludePath[i] + "/" + file;
  182. break;
  183. }
  184. }
  185. }
  186. for(size_t i = 0; i < _vcontexts.size(); i++)
  187. {
  188. if(_vcontexts[i]->getFileName() == file)
  189. {
  190. return false;
  191. }
  192. }
  193. return true;
  194. }
  195. string TarsParse::getCurrFileName()
  196. {
  197. return _contexts.top()->getFileName();
  198. }
  199. void TarsParse::nextLine()
  200. {
  201. _contexts.top()->nextLine();
  202. }
  203. ContextPtr TarsParse::currentContextPtr()
  204. {
  205. return _contexts.top();
  206. }
  207. void TarsParse::error(const string &msg)
  208. {
  209. cerr << _contexts.top()->getFileName() << ": " << _contexts.top()->getCurrLine() << ": error: " << msg << endl;
  210. exit(-1);
  211. }
  212. int TarsParse::checkKeyword(const string& s)
  213. {
  214. std::map<std::string, int>::const_iterator it = _keywordMap.find(s);
  215. if(it != _keywordMap.end())
  216. {
  217. return it->second;
  218. }
  219. if(!_bWithTars)
  220. {
  221. string sPrefix = "tars";
  222. //不能以tars开头
  223. if((s.length() >= sPrefix.length()) && (s.substr(0, sPrefix.length()) == sPrefix))
  224. {
  225. error("identifier can't start with 'tars'");
  226. }
  227. }
  228. return TARS_IDENTIFIER;
  229. }
  230. void TarsParse::initScanner()
  231. {
  232. _keywordMap["void"] = TARS_VOID;
  233. _keywordMap["struct"] = TARS_STRUCT;
  234. _keywordMap["bool"] = TARS_BOOL;
  235. _keywordMap["byte"] = TARS_BYTE;
  236. _keywordMap["short"] = TARS_SHORT;
  237. _keywordMap["int"] = TARS_INT;
  238. _keywordMap["double"] = TARS_DOUBLE;
  239. _keywordMap["float"] = TARS_FLOAT;
  240. _keywordMap["long"] = TARS_LONG;
  241. _keywordMap["string"] = TARS_STRING;
  242. _keywordMap["vector"] = TARS_VECTOR;
  243. _keywordMap["map"] = TARS_MAP;
  244. _keywordMap["key"] = TARS_KEY;
  245. _keywordMap["routekey"] = TARS_ROUTE_KEY;
  246. _keywordMap["module"] = TARS_NAMESPACE;
  247. _keywordMap["interface"]= TARS_INTERFACE;
  248. _keywordMap["out"] = TARS_OUT;
  249. _keywordMap["require"] = TARS_REQUIRE;
  250. _keywordMap["optional"] = TARS_OPTIONAL;
  251. _keywordMap["false"] = TARS_FALSE;
  252. _keywordMap["true"] = TARS_TRUE;
  253. _keywordMap["enum"] = TARS_ENUM;
  254. _keywordMap["const"] = TARS_CONST;
  255. _keywordMap["unsigned"] = TARS_UNSIGNED;
  256. }
  257. string TarsParse::getTab()
  258. {
  259. ostringstream s;
  260. for(int i = 0; i < _itab; i++)
  261. {
  262. s << " ";
  263. }
  264. return s.str();
  265. }
  266. BuiltinPtr TarsParse::createBuiltin(Builtin::Kind kind,bool isUnsigned)
  267. {
  268. return new Builtin(kind,isUnsigned);
  269. }
  270. VectorPtr TarsParse::createVector(const TypePtr &ptr)
  271. {
  272. return new Vector(ptr);
  273. }
  274. MapPtr TarsParse::createMap(const TypePtr &pleft, const TypePtr &pright)
  275. {
  276. return new Map(pleft, pright);
  277. }
  278. void TarsParse::addNamespacePtr(const NamespacePtr &nPtr)
  279. {
  280. _namespaces.push_back(nPtr);
  281. }
  282. NamespacePtr TarsParse::findNamespace(const string &id)
  283. {
  284. for(size_t i = 0; i < _namespaces.size(); i++)
  285. {
  286. if(_namespaces[i]->getId() == id)
  287. {
  288. return _namespaces[i];
  289. }
  290. }
  291. return NULL;
  292. }
  293. NamespacePtr TarsParse::currentNamespace()
  294. {
  295. return _namespaces.back();
  296. }
  297. void TarsParse::addStructPtr(const StructPtr &sPtr)
  298. {
  299. _structs.push_back(sPtr);
  300. }
  301. void TarsParse::addEnumPtr(const EnumPtr &ePtr)
  302. {
  303. _enums.push_back(ePtr);
  304. }
  305. StructPtr TarsParse::findStruct(const string &sid)
  306. {
  307. string ssid = sid;
  308. //在当前namespace中查找
  309. NamespacePtr np = currentNamespace();
  310. if(ssid.find("::") == string::npos)
  311. {
  312. ssid = np->getId() + "::" + ssid;
  313. }
  314. for(size_t i = 0; i < _structs.size(); i++)
  315. {
  316. if(_structs[i]->getSid() == ssid)
  317. {
  318. return _structs[i];
  319. }
  320. }
  321. return NULL;
  322. }
  323. EnumPtr TarsParse::findEnum(const string &sid)
  324. {
  325. string ssid = sid;
  326. //在当前namespace中查找
  327. NamespacePtr np = currentNamespace();
  328. if(ssid.find("::") == string::npos)
  329. {
  330. ssid = np->getId() + "::" + sid;
  331. }
  332. for(size_t i = 0; i < _enums.size(); i++)
  333. {
  334. if(_enums[i]->getSid() == ssid)
  335. {
  336. return _enums[i];
  337. }
  338. }
  339. return NULL;
  340. }
  341. bool TarsParse::checkEnum(const string &idName)
  342. {
  343. for(size_t i = 0; i < _enums.size(); i++)
  344. {
  345. vector<TypeIdPtr> & list = _enums[i]->getAllMemberPtr();
  346. for (size_t j = 0; j < list.size(); j++)
  347. {
  348. if (list[j]->getId() == idName)
  349. {
  350. return true;
  351. }
  352. }
  353. }
  354. return false;
  355. }
  356. void TarsParse::checkConflict(const string &sid)
  357. {
  358. //是否和枚举重名
  359. if(findEnum(sid))
  360. {
  361. error("conflicts with enum '" + sid + "'");
  362. }
  363. //是否和结构重名
  364. if(findStruct(sid))
  365. {
  366. error("conflicts with struct '" + sid + "'");
  367. }
  368. }
  369. TypePtr TarsParse::findUserType(const string &sid)
  370. {
  371. StructPtr sPtr = findStruct(sid);
  372. if(sPtr) return sPtr;
  373. EnumPtr ePtr = findEnum(sid);
  374. if(ePtr) return ePtr;
  375. return NULL;
  376. }
  377. ContainerPtr TarsParse::currentContainer()
  378. {
  379. return _contains.top();
  380. }
  381. void TarsParse::pushContainer(const ContainerPtr &c)
  382. {
  383. _contains.push(c);
  384. NamespacePtr np = NamespacePtr::dynamicCast(c);
  385. if(np)
  386. {
  387. addNamespacePtr(np);
  388. }
  389. }
  390. ContainerPtr TarsParse::popContainer()
  391. {
  392. ContainerPtr c = _contains.top();
  393. _contains.pop();
  394. return c;
  395. }
  396. void TarsParse::checkTag(int i)
  397. {
  398. if(i >= 256)
  399. {
  400. error("struct memeber tag can't beyond 256");
  401. }
  402. if(i < 0)
  403. {
  404. error("struct memeber tag can't less then 0");
  405. }
  406. }
  407. void TarsParse::checkSize(int i)
  408. {
  409. if(i >= 1024*1024)
  410. {
  411. error("struct memeber size can't beyond 1M");
  412. }
  413. if(i < 1)
  414. {
  415. error("struct memeber size can't less than 1");
  416. }
  417. }
  418. void TarsParse::checkArrayVaid(TypePtr &tPtr,int size)
  419. {
  420. checkSize(size);
  421. //只有string/vector可以为array类型
  422. //vector不可以嵌套array类型 例如不允许vector<string:8>:2;
  423. VectorPtr vPtr = VectorPtr::dynamicCast(tPtr);
  424. if(vPtr )
  425. {
  426. if(vPtr->getTypePtr()->isArray())
  427. {
  428. error("fixed array type can not be nested");
  429. }
  430. return;
  431. }
  432. BuiltinPtr bPtr = BuiltinPtr::dynamicCast(tPtr);
  433. if(bPtr && bPtr->kind()== Builtin::KindString)
  434. {
  435. return;
  436. }
  437. error("only string or vector can use fix array");
  438. }
  439. void TarsParse::checkPointerVaid(TypePtr &tPtr)
  440. {
  441. //必须为vector<Byte>类型
  442. VectorPtr vPtr = VectorPtr::dynamicCast(tPtr);
  443. if(vPtr)
  444. {
  445. BuiltinPtr bPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr());
  446. if( bPtr && bPtr->kind()== Builtin::KindByte)
  447. return;
  448. }
  449. error("only 'byte *' can be pointer type");
  450. }
  451. void TarsParse::checkConstValue(TypeIdPtr &tPtr, int c)
  452. {
  453. //只有内建类型才能有缺省值
  454. BuiltinPtr bPtr = BuiltinPtr::dynamicCast(tPtr->getTypePtr());
  455. EnumPtr ePtr = EnumPtr::dynamicCast(tPtr->getTypePtr());
  456. if(!bPtr && !ePtr)
  457. {
  458. error("only base/enum type can have default value");
  459. }
  460. if (ePtr)
  461. {
  462. if (c != ConstGrammar::VALUE && c != ConstGrammar::ENUM)
  463. {
  464. error("default value of enum only be int or enum_type");
  465. }
  466. return ;
  467. }
  468. int b = bPtr->kind();
  469. if(c == ConstGrammar::VALUE)
  470. {
  471. if(b == Builtin::KindBool)
  472. {
  473. error("default value of bool can only be true or false");
  474. }
  475. if(b == Builtin::KindString)
  476. {
  477. error("default value of string can only be \"string\"");
  478. }
  479. }
  480. else if(c == ConstGrammar::BOOL)
  481. {
  482. if(b != Builtin::KindBool)
  483. {
  484. error("only bool type can be true or false");
  485. }
  486. }
  487. else if(c == ConstGrammar::STRING)
  488. {
  489. if(b != Builtin::KindString)
  490. {
  491. error("only string type can be \"string\"");
  492. }
  493. }
  494. }
  495. string TarsParse::printHeaderRemark()
  496. {
  497. ostringstream s;
  498. s << "// **********************************************************************" << endl;
  499. s << "// This file was generated by a TARS parser!" << endl;
  500. s << "// TARS version " << TARS_VERSION << "." << endl;
  501. s << "// **********************************************************************" << endl;
  502. s << endl;
  503. return s.str();
  504. }
  505. string TarsParse::getFileName(const string &fileName)
  506. {
  507. string tmpFileName = fileName;
  508. string::size_type pos = tmpFileName.rfind('/');
  509. if(pos != string::npos)
  510. {
  511. tmpFileName = tmpFileName.substr(pos + 1);
  512. }
  513. else
  514. {
  515. pos = tmpFileName.rfind('\\');
  516. if(pos != string::npos)
  517. {
  518. tmpFileName = tmpFileName.substr(pos + 1);
  519. }
  520. }
  521. return tars::TC_File::excludeFileExt(tmpFileName);
  522. }
  523. string TarsParse::replaceFileName(const string &fileName, const string &ext)
  524. {
  525. return tars::TC_File::excludeFileExt(getFileName(fileName)) + "." + ext;
  526. }
  527. string TarsParse::getAbsoluteFileName(const string &baseDir, const string &fileName)
  528. {
  529. return baseDir + FILE_SEP + fileName;
  530. }