PageRenderTime 58ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/Dependencies/boo/lib/antlr-2.7.5/lib/cpp/src/ASTFactory.cpp

https://github.com/w4x/boolangstudio
C++ | 504 lines | 329 code | 74 blank | 101 comment | 60 complexity | 2fedc04ab8be3dc76e9a7c53b7f80133 MD5 | raw file
Possible License(s): GPL-2.0
  1. /* ANTLR Translator Generator
  2. * Project led by Terence Parr at http://www.jGuru.com
  3. * Software rights: http://www.antlr.org/license.html
  4. *
  5. * $Id: //depot/code/org.antlr/release/antlr-2.7.5/lib/cpp/src/ASTFactory.cpp#1 $
  6. */
  7. #include "antlr/CommonAST.hpp"
  8. #include "antlr/ANTLRException.hpp"
  9. #include "antlr/IOException.hpp"
  10. #include "antlr/ASTFactory.hpp"
  11. #include "antlr/ANTLRUtil.hpp"
  12. #include <iostream>
  13. #include <istream>
  14. using namespace std;
  15. #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
  16. namespace antlr {
  17. #endif
  18. /** AST Support code shared by TreeParser and Parser.
  19. * We use delegation to share code (and have only one
  20. * bit of code to maintain) rather than subclassing
  21. * or superclassing (forces AST support code to be
  22. * loaded even when you don't want to do AST stuff).
  23. *
  24. * This class collects all factories of AST types used inside the code.
  25. * New AST node types are registered with the registerFactory method.
  26. * On creation of an ASTFactory object a default AST node factory may be
  27. * specified.
  28. *
  29. * When registering types gaps between different types are filled with entries
  30. * for the default factory.
  31. */
  32. /// Initialize factory
  33. ASTFactory::ASTFactory()
  34. : default_factory_descriptor(ANTLR_USE_NAMESPACE(std)make_pair(CommonAST::TYPE_NAME,&CommonAST::factory))
  35. {
  36. nodeFactories.resize( Token::MIN_USER_TYPE, &default_factory_descriptor );
  37. }
  38. /** Initialize factory with a non default node type.
  39. * factory_node_name should be the name of the AST node type the factory
  40. * generates. (should exist during the existance of this ASTFactory instance)
  41. */
  42. ASTFactory::ASTFactory( const char* factory_node_name, factory_type fact )
  43. : default_factory_descriptor(ANTLR_USE_NAMESPACE(std)make_pair(factory_node_name, fact))
  44. {
  45. nodeFactories.resize( Token::MIN_USER_TYPE, &default_factory_descriptor );
  46. }
  47. /// Delete ASTFactory
  48. ASTFactory::~ASTFactory()
  49. {
  50. factory_descriptor_list::iterator i = nodeFactories.begin();
  51. while( i != nodeFactories.end() )
  52. {
  53. if( *i != &default_factory_descriptor )
  54. delete *i;
  55. i++;
  56. }
  57. }
  58. /// Register a factory for a given AST type
  59. void ASTFactory::registerFactory( int type, const char* ast_name, factory_type factory )
  60. {
  61. // check validity of arguments...
  62. if( type < Token::MIN_USER_TYPE )
  63. throw ANTLRException("Internal parser error invalid type passed to RegisterFactory");
  64. if( factory == 0 )
  65. throw ANTLRException("Internal parser error 0 factory passed to RegisterFactory");
  66. // resize up to and including 'type' and initalize any gaps to default
  67. // factory.
  68. if( nodeFactories.size() < (static_cast<unsigned int>(type)+1) )
  69. nodeFactories.resize( type+1, &default_factory_descriptor );
  70. // And add new thing..
  71. nodeFactories[type] = new ANTLR_USE_NAMESPACE(std)pair<const char*, factory_type>( ast_name, factory );
  72. }
  73. void ASTFactory::setMaxNodeType( int type )
  74. {
  75. if( nodeFactories.size() < (static_cast<unsigned int>(type)+1) )
  76. nodeFactories.resize( type+1, &default_factory_descriptor );
  77. }
  78. /** Create a new empty AST node; if the user did not specify
  79. * an AST node type, then create a default one: CommonAST.
  80. */
  81. RefAST ASTFactory::create()
  82. {
  83. RefAST node = nodeFactories[0]->second();
  84. node->setType(Token::INVALID_TYPE);
  85. return node;
  86. }
  87. RefAST ASTFactory::create(int type)
  88. {
  89. RefAST t = nodeFactories[type]->second();
  90. t->initialize(type,"");
  91. return t;
  92. }
  93. RefAST ASTFactory::create(int type, const ANTLR_USE_NAMESPACE(std)string& txt)
  94. {
  95. RefAST t = nodeFactories[type]->second();
  96. t->initialize(type,txt);
  97. return t;
  98. }
  99. #ifdef ANTLR_SUPPORT_XML
  100. RefAST ASTFactory::create(const ANTLR_USE_NAMESPACE(std)string& type_name, ANTLR_USE_NAMESPACE(std)istream& infile )
  101. {
  102. factory_descriptor_list::iterator fact = nodeFactories.begin();
  103. while( fact != nodeFactories.end() )
  104. {
  105. if( type_name == (*fact)->first )
  106. {
  107. RefAST t = (*fact)->second();
  108. t->initialize(infile);
  109. return t;
  110. }
  111. fact++;
  112. }
  113. string error = "ASTFactory::create: Unknown AST type '" + type_name + "'";
  114. throw ANTLRException(error);
  115. }
  116. #endif
  117. /** Create a new empty AST node; if the user did not specify
  118. * an AST node type, then create a default one: CommonAST.
  119. */
  120. RefAST ASTFactory::create(RefAST tr)
  121. {
  122. if (!tr)
  123. return nullAST;
  124. // cout << "create(tr)" << endl;
  125. RefAST t = nodeFactories[tr->getType()]->second();
  126. t->initialize(tr);
  127. return t;
  128. }
  129. RefAST ASTFactory::create(RefToken tok)
  130. {
  131. // cout << "create( tok="<< tok->getType() << ", " << tok->getText() << ")" << nodeFactories.size() << endl;
  132. RefAST t = nodeFactories[tok->getType()]->second();
  133. t->initialize(tok);
  134. return t;
  135. }
  136. /** Add a child to the current AST */
  137. void ASTFactory::addASTChild(ASTPair& currentAST, RefAST child)
  138. {
  139. if (child)
  140. {
  141. if (!currentAST.root)
  142. {
  143. // Make new child the current root
  144. currentAST.root = child;
  145. }
  146. else
  147. {
  148. if (!currentAST.child)
  149. {
  150. // Add new child to current root
  151. currentAST.root->setFirstChild(child);
  152. }
  153. else
  154. {
  155. currentAST.child->setNextSibling(child);
  156. }
  157. }
  158. // Make new child the current child
  159. currentAST.child = child;
  160. currentAST.advanceChildToEnd();
  161. }
  162. }
  163. /** Deep copy a single node. This function the new clone() methods in the AST
  164. * interface. Returns nullAST if t is null.
  165. */
  166. RefAST ASTFactory::dup(RefAST t)
  167. {
  168. if( t )
  169. return t->clone();
  170. else
  171. return RefAST(nullASTptr);
  172. }
  173. /** Duplicate tree including siblings of root. */
  174. RefAST ASTFactory::dupList(RefAST t)
  175. {
  176. RefAST result = dupTree(t); // if t == null, then result==null
  177. RefAST nt = result;
  178. while( t )
  179. { // for each sibling of the root
  180. t = t->getNextSibling();
  181. nt->setNextSibling(dupTree(t)); // dup each subtree, building new tree
  182. nt = nt->getNextSibling();
  183. }
  184. return result;
  185. }
  186. /** Duplicate a tree, assuming this is a root node of a tree
  187. * duplicate that node and what's below; ignore siblings of root node.
  188. */
  189. RefAST ASTFactory::dupTree(RefAST t)
  190. {
  191. RefAST result = dup(t); // make copy of root
  192. // copy all children of root.
  193. if( t )
  194. result->setFirstChild( dupList(t->getFirstChild()) );
  195. return result;
  196. }
  197. /** Make a tree from a list of nodes. The first element in the
  198. * array is the root. If the root is null, then the tree is
  199. * a simple list not a tree. Handles null children nodes correctly.
  200. * For example, make(a, b, null, c) yields tree (a b c). make(null,a,b)
  201. * yields tree (nil a b).
  202. */
  203. RefAST ASTFactory::make(ANTLR_USE_NAMESPACE(std)vector<RefAST>& nodes)
  204. {
  205. if ( nodes.size() == 0 )
  206. return RefAST(nullASTptr);
  207. RefAST root = nodes[0];
  208. RefAST tail = RefAST(nullASTptr);
  209. if( root )
  210. root->setFirstChild(RefAST(nullASTptr)); // don't leave any old pointers set
  211. // link in children;
  212. for( unsigned int i = 1; i < nodes.size(); i++ )
  213. {
  214. if ( nodes[i] == 0 ) // ignore null nodes
  215. continue;
  216. if ( root == 0 ) // Set the root and set it up for a flat list
  217. root = tail = nodes[i];
  218. else if ( tail == 0 )
  219. {
  220. root->setFirstChild(nodes[i]);
  221. tail = root->getFirstChild();
  222. }
  223. else
  224. {
  225. tail->setNextSibling(nodes[i]);
  226. tail = tail->getNextSibling();
  227. }
  228. if( tail ) // RK: I cannot fathom why this missing check didn't bite anyone else...
  229. {
  230. // Chase tail to last sibling
  231. while (tail->getNextSibling())
  232. tail = tail->getNextSibling();
  233. }
  234. }
  235. return root;
  236. }
  237. /** Make a tree from a list of nodes, where the nodes are contained
  238. * in an ASTArray object
  239. */
  240. RefAST ASTFactory::make(ASTArray* nodes)
  241. {
  242. RefAST ret = make(nodes->array);
  243. delete nodes;
  244. return ret;
  245. }
  246. /// Make an AST the root of current AST
  247. void ASTFactory::makeASTRoot( ASTPair& currentAST, RefAST root )
  248. {
  249. if (root)
  250. {
  251. // Add the current root as a child of new root
  252. root->addChild(currentAST.root);
  253. // The new current child is the last sibling of the old root
  254. currentAST.child = currentAST.root;
  255. currentAST.advanceChildToEnd();
  256. // Set the new root
  257. currentAST.root = root;
  258. }
  259. }
  260. void ASTFactory::setASTNodeFactory( const char* factory_node_name,
  261. factory_type factory )
  262. {
  263. default_factory_descriptor.first = factory_node_name;
  264. default_factory_descriptor.second = factory;
  265. }
  266. #ifdef ANTLR_SUPPORT_XML
  267. bool ASTFactory::checkCloseTag( ANTLR_USE_NAMESPACE(std)istream& in )
  268. {
  269. char ch;
  270. if( in.get(ch) )
  271. {
  272. if( ch == '<' )
  273. {
  274. char ch2;
  275. if( in.get(ch2) )
  276. {
  277. if( ch2 == '/' )
  278. {
  279. in.putback(ch2);
  280. in.putback(ch);
  281. return true;
  282. }
  283. in.putback(ch2);
  284. in.putback(ch);
  285. return false;
  286. }
  287. }
  288. in.putback(ch);
  289. return false;
  290. }
  291. return false;
  292. }
  293. void ASTFactory::loadChildren( ANTLR_USE_NAMESPACE(std)istream& infile,
  294. RefAST current )
  295. {
  296. char ch;
  297. for(;;) // for all children of this node....
  298. {
  299. eatwhite(infile);
  300. infile.get(ch); // '<'
  301. if( ch != '<' )
  302. {
  303. string error = "Invalid XML file... no '<' found (";
  304. error += ch + ")";
  305. throw IOException(error);
  306. }
  307. infile.get(ch); // / or text....
  308. if( ch == '/' ) // check for close tag...
  309. {
  310. string temp;
  311. // read until '>' and see if it matches the open tag... if not trouble
  312. temp = read_identifier( infile );
  313. if( strcmp(temp.c_str(), current->typeName() ) != 0 )
  314. {
  315. string error = "Invalid XML file... close tag does not match start tag: ";
  316. error += current->typeName();
  317. error += " closed by " + temp;
  318. throw IOException(error);
  319. }
  320. infile.get(ch); // must be a '>'
  321. if( ch != '>' )
  322. {
  323. string error = "Invalid XML file... no '>' found (";
  324. error += ch + ")";
  325. throw IOException(error);
  326. }
  327. // close tag => exit loop
  328. break;
  329. }
  330. // put our 'look ahead' back where it came from
  331. infile.putback(ch);
  332. infile.putback('<');
  333. // and recurse into the tree...
  334. RefAST child = LoadAST(infile);
  335. current->addChild( child );
  336. }
  337. }
  338. void ASTFactory::loadSiblings(ANTLR_USE_NAMESPACE(std)istream& infile,
  339. RefAST current )
  340. {
  341. for(;;)
  342. {
  343. eatwhite(infile);
  344. if( infile.eof() )
  345. break;
  346. if( checkCloseTag(infile) )
  347. break;
  348. RefAST sibling = LoadAST(infile);
  349. current->setNextSibling(sibling);
  350. }
  351. }
  352. RefAST ASTFactory::LoadAST( ANTLR_USE_NAMESPACE(std)istream& infile )
  353. {
  354. RefAST current = nullAST;
  355. char ch;
  356. eatwhite(infile);
  357. if( !infile.get(ch) )
  358. return nullAST;
  359. if( ch != '<' )
  360. {
  361. string error = "Invalid XML file... no '<' found (";
  362. error += ch + ")";
  363. throw IOException(error);
  364. }
  365. string ast_type = read_identifier(infile);
  366. // create the ast of type 'ast_type'
  367. current = create( ast_type, infile );
  368. if( current == nullAST )
  369. {
  370. string error = "Unsuported AST type: " + ast_type;
  371. throw IOException(error);
  372. }
  373. eatwhite(infile);
  374. infile.get(ch);
  375. // now if we have a '/' here it's a single node. If it's a '>' we get
  376. // a tree with children
  377. if( ch == '/' )
  378. {
  379. infile.get(ch); // get the closing '>'
  380. if( ch != '>' )
  381. {
  382. string error = "Invalid XML file... no '>' found after '/' (";
  383. error += ch + ")";
  384. throw IOException(error);
  385. }
  386. // get the rest on this level
  387. loadSiblings( infile, current );
  388. return current;
  389. }
  390. // and finaly see if we got the close tag...
  391. if( ch != '>' )
  392. {
  393. string error = "Invalid XML file... no '>' found (";
  394. error += ch + ")";
  395. throw IOException(error);
  396. }
  397. // handle the ones below this level..
  398. loadChildren( infile, current );
  399. // load the rest on this level...
  400. loadSiblings( infile, current );
  401. return current;
  402. }
  403. #endif // ANTLR_SUPPORT_XML
  404. #ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
  405. }
  406. #endif
  407. /* Heterogeneous AST/XML-I/O ramblings...
  408. *
  409. * So there is some heterogeneous AST support....
  410. * basically in the code generators a new custom ast is generated without
  411. * going throug the factory. It also expects the RefXAST to be defined.
  412. *
  413. * Is it maybe better to register all AST types with the ASTFactory class
  414. * together with the respective factory methods.
  415. *
  416. * More and more I get the impression that hetero ast was a kindoff hack
  417. * on top of ANTLR's normal AST system.
  418. *
  419. * The heteroast stuff will generate trouble for all astFactory.create( ... )
  420. * invocations. Most of this is handled via getASTCreateString methods in the
  421. * codegenerator. At the moment getASTCreateString(GrammarAtom, String) has
  422. * slightly to little info to do it's job (ok the hack that is in now
  423. * works, but it's an ugly hack)
  424. *
  425. * An extra caveat is the 'nice' action.g thing. Which also judiciously calls
  426. * getASTCreateString methods because it handles the #( ... ) syntax.
  427. * And converts that to ASTFactory calls.
  428. *
  429. *
  430. */