cmGeneratorExpressionParser.cxx 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2012 Stephen Kelly <[email protected]>
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmGeneratorExpressionParser.h"
  11. #include "cmGeneratorExpressionEvaluator.h"
  12. #include "assert.h"
  13. //----------------------------------------------------------------------------
  14. cmGeneratorExpressionParser::cmGeneratorExpressionParser(
  15. const std::vector<cmGeneratorExpressionToken> &tokens)
  16. : Tokens(tokens), NestingLevel(0)
  17. {
  18. }
  19. //----------------------------------------------------------------------------
  20. void cmGeneratorExpressionParser::Parse(
  21. std::vector<cmGeneratorExpressionEvaluator*> &result)
  22. {
  23. it = this->Tokens.begin();
  24. while (this->it != this->Tokens.end())
  25. {
  26. this->ParseContent(result);
  27. }
  28. }
  29. //----------------------------------------------------------------------------
  30. static void extendText(std::vector<cmGeneratorExpressionEvaluator*> &result,
  31. std::vector<cmGeneratorExpressionToken>::const_iterator it)
  32. {
  33. if (result.size() > 0
  34. && (*(result.end() - 1))->GetType()
  35. == cmGeneratorExpressionEvaluator::Text)
  36. {
  37. TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
  38. textContent->Extend(it->Length);
  39. }
  40. else
  41. {
  42. TextContent *textContent = new TextContent(it->Content, it->Length);
  43. result.push_back(textContent);
  44. }
  45. }
  46. //----------------------------------------------------------------------------
  47. static void extendResult(std::vector<cmGeneratorExpressionEvaluator*> &result,
  48. const std::vector<cmGeneratorExpressionEvaluator*> &contents)
  49. {
  50. if (result.size() > 0
  51. && (*(result.end() - 1))->GetType()
  52. == cmGeneratorExpressionEvaluator::Text
  53. && (*contents.begin())->GetType()
  54. == cmGeneratorExpressionEvaluator::Text)
  55. {
  56. TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
  57. textContent->Extend(
  58. static_cast<TextContent*>(*contents.begin())->GetLength());
  59. delete *contents.begin();
  60. result.insert(result.end(), contents.begin() + 1, contents.end());
  61. } else {
  62. result.insert(result.end(), contents.begin(), contents.end());
  63. }
  64. }
  65. //----------------------------------------------------------------------------
  66. void cmGeneratorExpressionParser::ParseGeneratorExpression(
  67. std::vector<cmGeneratorExpressionEvaluator*> &result)
  68. {
  69. assert(this->it != this->Tokens.end());
  70. unsigned int nestedLevel = this->NestingLevel;
  71. ++this->NestingLevel;
  72. std::vector<cmGeneratorExpressionToken>::const_iterator startToken
  73. = this->it - 1;
  74. std::vector<cmGeneratorExpressionEvaluator*> identifier;
  75. while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression
  76. && this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator)
  77. {
  78. if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  79. {
  80. extendText(identifier, this->it);
  81. ++this->it;
  82. }
  83. else
  84. {
  85. this->ParseContent(identifier);
  86. }
  87. if (this->it == this->Tokens.end())
  88. {
  89. break;
  90. }
  91. }
  92. if (identifier.empty())
  93. {
  94. // ERROR
  95. }
  96. if (this->it != this->Tokens.end() &&
  97. this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
  98. {
  99. GeneratorExpressionContent *content = new GeneratorExpressionContent(
  100. startToken->Content, this->it->Content
  101. - startToken->Content
  102. + this->it->Length);
  103. assert(this->it != this->Tokens.end());
  104. ++this->it;
  105. --this->NestingLevel;
  106. content->SetIdentifier(identifier);
  107. result.push_back(content);
  108. return;
  109. }
  110. std::vector<std::vector<cmGeneratorExpressionEvaluator*> > parameters;
  111. std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
  112. commaTokens;
  113. std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
  114. if (this->it != this->Tokens.end() &&
  115. this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  116. {
  117. colonToken = this->it;
  118. parameters.resize(parameters.size() + 1);
  119. assert(this->it != this->Tokens.end());
  120. ++this->it;
  121. while (this->it != this->Tokens.end() &&
  122. this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  123. {
  124. commaTokens.push_back(this->it);
  125. parameters.resize(parameters.size() + 1);
  126. assert(this->it != this->Tokens.end());
  127. ++this->it;
  128. }
  129. while (this->it != this->Tokens.end() &&
  130. this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  131. {
  132. extendText(*(parameters.end() - 1), this->it);
  133. assert(this->it != this->Tokens.end());
  134. ++this->it;
  135. }
  136. while (this->it != this->Tokens.end() &&
  137. this->it->TokenType != cmGeneratorExpressionToken::EndExpression)
  138. {
  139. this->ParseContent(*(parameters.end() - 1));
  140. if (this->it == this->Tokens.end())
  141. {
  142. break;
  143. }
  144. while (this->it != this->Tokens.end() &&
  145. this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  146. {
  147. commaTokens.push_back(this->it);
  148. parameters.resize(parameters.size() + 1);
  149. assert(this->it != this->Tokens.end());
  150. ++this->it;
  151. }
  152. while (this->it != this->Tokens.end() &&
  153. this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  154. {
  155. extendText(*(parameters.end() - 1), this->it);
  156. assert(this->it != this->Tokens.end());
  157. ++this->it;
  158. }
  159. }
  160. if(this->it != this->Tokens.end()
  161. && this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
  162. {
  163. --this->NestingLevel;
  164. assert(this->it != this->Tokens.end());
  165. ++this->it;
  166. }
  167. }
  168. if (nestedLevel != this->NestingLevel)
  169. {
  170. // There was a '$<' in the text, but no corresponding '>'. Rebuild to
  171. // treat the '$<' as having been plain text, along with the
  172. // corresponding : and , tokens that might have been found.
  173. extendText(result, startToken);
  174. extendResult(result, identifier);
  175. if (!parameters.empty())
  176. {
  177. extendText(result, colonToken);
  178. typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
  179. typedef std::vector<cmGeneratorExpressionToken> TokenVector;
  180. std::vector<EvaluatorVector>::const_iterator pit = parameters.begin();
  181. const std::vector<EvaluatorVector>::const_iterator pend =
  182. parameters.end();
  183. std::vector<TokenVector::const_iterator>::const_iterator commaIt =
  184. commaTokens.begin();
  185. assert(parameters.size() > commaTokens.size());
  186. for ( ; pit != pend; ++pit, ++commaIt)
  187. {
  188. extendResult(result, *pit);
  189. if (commaIt != commaTokens.end())
  190. {
  191. extendText(result, *commaIt);
  192. }
  193. else
  194. {
  195. break;
  196. }
  197. }
  198. }
  199. return;
  200. }
  201. int contentLength = ((this->it - 1)->Content
  202. - startToken->Content)
  203. + (this->it - 1)->Length;
  204. GeneratorExpressionContent *content = new GeneratorExpressionContent(
  205. startToken->Content, contentLength);
  206. content->SetIdentifier(identifier);
  207. content->SetParameters(parameters);
  208. result.push_back(content);
  209. }
  210. //----------------------------------------------------------------------------
  211. void cmGeneratorExpressionParser::ParseContent(
  212. std::vector<cmGeneratorExpressionEvaluator*> &result)
  213. {
  214. assert(this->it != this->Tokens.end());
  215. switch(this->it->TokenType)
  216. {
  217. case cmGeneratorExpressionToken::Text:
  218. {
  219. if (this->NestingLevel == 0)
  220. {
  221. if (result.size() > 0
  222. && (*(result.end() - 1))->GetType()
  223. == cmGeneratorExpressionEvaluator::Text)
  224. {
  225. // A comma in 'plain text' could have split text that should
  226. // otherwise be continuous. Extend the last text content instead of
  227. // creating a new one.
  228. TextContent *textContent =
  229. static_cast<TextContent*>(*(result.end() - 1));
  230. textContent->Extend(this->it->Length);
  231. assert(this->it != this->Tokens.end());
  232. ++this->it;
  233. return;
  234. }
  235. }
  236. cmGeneratorExpressionEvaluator* n = new TextContent(this->it->Content,
  237. this->it->Length);
  238. result.push_back(n);
  239. assert(this->it != this->Tokens.end());
  240. ++this->it;
  241. return ;
  242. }
  243. case cmGeneratorExpressionToken::BeginExpression:
  244. assert(this->it != this->Tokens.end());
  245. ++this->it;
  246. this->ParseGeneratorExpression(result);
  247. return;
  248. case cmGeneratorExpressionToken::EndExpression:
  249. case cmGeneratorExpressionToken::ColonSeparator:
  250. case cmGeneratorExpressionToken::CommaSeparator:
  251. if (this->NestingLevel == 0)
  252. {
  253. extendText(result, this->it);
  254. }
  255. else
  256. {
  257. assert(!"Got unexpected syntax token.");
  258. }
  259. assert(this->it != this->Tokens.end());
  260. ++this->it;
  261. return;
  262. }
  263. assert(!"Unhandled token in generator expression.");
  264. }