cmGeneratorExpressionParser.cxx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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. bool emptyParamTermination = false;
  115. if (this->it != this->Tokens.end() &&
  116. this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  117. {
  118. colonToken = this->it;
  119. parameters.resize(parameters.size() + 1);
  120. assert(this->it != this->Tokens.end());
  121. ++this->it;
  122. if(this->it == this->Tokens.end())
  123. {
  124. emptyParamTermination = true;
  125. }
  126. while (this->it != this->Tokens.end() &&
  127. this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  128. {
  129. commaTokens.push_back(this->it);
  130. parameters.resize(parameters.size() + 1);
  131. assert(this->it != this->Tokens.end());
  132. ++this->it;
  133. if(this->it == this->Tokens.end())
  134. {
  135. emptyParamTermination = true;
  136. }
  137. }
  138. while (this->it != this->Tokens.end() &&
  139. this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  140. {
  141. extendText(*(parameters.end() - 1), this->it);
  142. assert(this->it != this->Tokens.end());
  143. ++this->it;
  144. }
  145. while (this->it != this->Tokens.end() &&
  146. this->it->TokenType != cmGeneratorExpressionToken::EndExpression)
  147. {
  148. this->ParseContent(*(parameters.end() - 1));
  149. if (this->it == this->Tokens.end())
  150. {
  151. break;
  152. }
  153. while (this->it != this->Tokens.end() &&
  154. this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  155. {
  156. commaTokens.push_back(this->it);
  157. parameters.resize(parameters.size() + 1);
  158. assert(this->it != this->Tokens.end());
  159. ++this->it;
  160. if(this->it == this->Tokens.end())
  161. {
  162. emptyParamTermination = true;
  163. }
  164. }
  165. while (this->it != this->Tokens.end() &&
  166. this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  167. {
  168. extendText(*(parameters.end() - 1), this->it);
  169. assert(this->it != this->Tokens.end());
  170. ++this->it;
  171. }
  172. }
  173. if(this->it != this->Tokens.end()
  174. && this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
  175. {
  176. --this->NestingLevel;
  177. assert(this->it != this->Tokens.end());
  178. ++this->it;
  179. }
  180. }
  181. if (nestedLevel != this->NestingLevel)
  182. {
  183. // There was a '$<' in the text, but no corresponding '>'. Rebuild to
  184. // treat the '$<' as having been plain text, along with the
  185. // corresponding : and , tokens that might have been found.
  186. extendText(result, startToken);
  187. extendResult(result, identifier);
  188. if (!parameters.empty())
  189. {
  190. extendText(result, colonToken);
  191. typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
  192. typedef std::vector<cmGeneratorExpressionToken> TokenVector;
  193. std::vector<EvaluatorVector>::const_iterator pit = parameters.begin();
  194. const std::vector<EvaluatorVector>::const_iterator pend =
  195. parameters.end();
  196. std::vector<TokenVector::const_iterator>::const_iterator commaIt =
  197. commaTokens.begin();
  198. assert(parameters.size() > commaTokens.size());
  199. for ( ; pit != pend; ++pit, ++commaIt)
  200. {
  201. if (!pit->empty() && !emptyParamTermination)
  202. {
  203. extendResult(result, *pit);
  204. }
  205. if (commaIt != commaTokens.end())
  206. {
  207. extendText(result, *commaIt);
  208. }
  209. else
  210. {
  211. break;
  212. }
  213. }
  214. }
  215. return;
  216. }
  217. int contentLength = ((this->it - 1)->Content
  218. - startToken->Content)
  219. + (this->it - 1)->Length;
  220. GeneratorExpressionContent *content = new GeneratorExpressionContent(
  221. startToken->Content, contentLength);
  222. content->SetIdentifier(identifier);
  223. content->SetParameters(parameters);
  224. result.push_back(content);
  225. }
  226. //----------------------------------------------------------------------------
  227. void cmGeneratorExpressionParser::ParseContent(
  228. std::vector<cmGeneratorExpressionEvaluator*> &result)
  229. {
  230. assert(this->it != this->Tokens.end());
  231. switch(this->it->TokenType)
  232. {
  233. case cmGeneratorExpressionToken::Text:
  234. {
  235. if (this->NestingLevel == 0)
  236. {
  237. if (result.size() > 0
  238. && (*(result.end() - 1))->GetType()
  239. == cmGeneratorExpressionEvaluator::Text)
  240. {
  241. // A comma in 'plain text' could have split text that should
  242. // otherwise be continuous. Extend the last text content instead of
  243. // creating a new one.
  244. TextContent *textContent =
  245. static_cast<TextContent*>(*(result.end() - 1));
  246. textContent->Extend(this->it->Length);
  247. assert(this->it != this->Tokens.end());
  248. ++this->it;
  249. return;
  250. }
  251. }
  252. cmGeneratorExpressionEvaluator* n = new TextContent(this->it->Content,
  253. this->it->Length);
  254. result.push_back(n);
  255. assert(this->it != this->Tokens.end());
  256. ++this->it;
  257. return ;
  258. }
  259. case cmGeneratorExpressionToken::BeginExpression:
  260. assert(this->it != this->Tokens.end());
  261. ++this->it;
  262. this->ParseGeneratorExpression(result);
  263. return;
  264. case cmGeneratorExpressionToken::EndExpression:
  265. case cmGeneratorExpressionToken::ColonSeparator:
  266. case cmGeneratorExpressionToken::CommaSeparator:
  267. if (this->NestingLevel == 0)
  268. {
  269. extendText(result, this->it);
  270. }
  271. else
  272. {
  273. assert(!"Got unexpected syntax token.");
  274. }
  275. assert(this->it != this->Tokens.end());
  276. ++this->it;
  277. return;
  278. }
  279. assert(!"Unhandled token in generator expression.");
  280. }