cmGeneratorExpressionParser.cxx 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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. this->ParseContent(identifier);
  79. if (this->it == this->Tokens.end())
  80. {
  81. break;
  82. }
  83. }
  84. if (identifier.empty())
  85. {
  86. // ERROR
  87. }
  88. if (this->it != this->Tokens.end() &&
  89. this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
  90. {
  91. GeneratorExpressionContent *content = new GeneratorExpressionContent(
  92. startToken->Content, this->it->Content
  93. - startToken->Content
  94. + this->it->Length);
  95. ++this->it;
  96. --this->NestingLevel;
  97. content->SetIdentifier(identifier);
  98. result.push_back(content);
  99. return;
  100. }
  101. std::vector<std::vector<cmGeneratorExpressionEvaluator*> > parameters;
  102. std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
  103. commaTokens;
  104. std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
  105. if (this->it != this->Tokens.end() &&
  106. this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  107. {
  108. colonToken = this->it;
  109. parameters.resize(parameters.size() + 1);
  110. ++this->it;
  111. while (this->it != this->Tokens.end() &&
  112. this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  113. {
  114. commaTokens.push_back(this->it);
  115. parameters.resize(parameters.size() + 1);
  116. ++this->it;
  117. }
  118. while (this->it != this->Tokens.end() &&
  119. this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  120. {
  121. extendText(*(parameters.end() - 1), this->it);
  122. ++this->it;
  123. }
  124. while (this->it != this->Tokens.end() &&
  125. this->it->TokenType != cmGeneratorExpressionToken::EndExpression)
  126. {
  127. this->ParseContent(*(parameters.end() - 1));
  128. if (this->it == this->Tokens.end())
  129. {
  130. break;
  131. }
  132. while (this->it != this->Tokens.end() &&
  133. this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  134. {
  135. commaTokens.push_back(this->it);
  136. parameters.resize(parameters.size() + 1);
  137. ++this->it;
  138. }
  139. while (this->it != this->Tokens.end() &&
  140. this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  141. {
  142. extendText(*(parameters.end() - 1), this->it);
  143. ++this->it;
  144. }
  145. }
  146. if(this->it != this->Tokens.end()
  147. && this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
  148. {
  149. --this->NestingLevel;
  150. ++this->it;
  151. }
  152. }
  153. if (nestedLevel != this->NestingLevel)
  154. {
  155. // There was a '$<' in the text, but no corresponding '>'. Rebuild to
  156. // treat the '$<' as having been plain text, along with the
  157. // corresponding : and , tokens that might have been found.
  158. extendText(result, startToken);
  159. extendResult(result, identifier);
  160. if (!parameters.empty())
  161. {
  162. extendText(result, colonToken);
  163. typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
  164. typedef std::vector<cmGeneratorExpressionToken> TokenVector;
  165. std::vector<EvaluatorVector>::const_iterator pit = parameters.begin();
  166. const std::vector<EvaluatorVector>::const_iterator pend =
  167. parameters.end();
  168. std::vector<TokenVector::const_iterator>::const_iterator commaIt =
  169. commaTokens.begin();
  170. for ( ; pit != pend; ++pit, ++commaIt)
  171. {
  172. extendResult(result, *pit);
  173. if (commaIt != commaTokens.end())
  174. {
  175. extendText(result, *commaIt);
  176. }
  177. }
  178. }
  179. return;
  180. }
  181. int contentLength = ((this->it - 1)->Content
  182. - startToken->Content)
  183. + (this->it - 1)->Length;
  184. GeneratorExpressionContent *content = new GeneratorExpressionContent(
  185. startToken->Content, contentLength);
  186. content->SetIdentifier(identifier);
  187. content->SetParameters(parameters);
  188. result.push_back(content);
  189. }
  190. //----------------------------------------------------------------------------
  191. void cmGeneratorExpressionParser::ParseContent(
  192. std::vector<cmGeneratorExpressionEvaluator*> &result)
  193. {
  194. assert(this->it != this->Tokens.end());
  195. switch(this->it->TokenType)
  196. {
  197. case cmGeneratorExpressionToken::Text:
  198. {
  199. if (this->NestingLevel == 0)
  200. {
  201. if (result.size() > 0
  202. && (*(result.end() - 1))->GetType()
  203. == cmGeneratorExpressionEvaluator::Text)
  204. {
  205. // A comma in 'plain text' could have split text that should
  206. // otherwise be continuous. Extend the last text content instead of
  207. // creating a new one.
  208. TextContent *textContent =
  209. static_cast<TextContent*>(*(result.end() - 1));
  210. textContent->Extend(this->it->Length);
  211. ++this->it;
  212. return;
  213. }
  214. }
  215. cmGeneratorExpressionEvaluator* n = new TextContent(this->it->Content,
  216. this->it->Length);
  217. result.push_back(n);
  218. ++this->it;
  219. return ;
  220. }
  221. case cmGeneratorExpressionToken::BeginExpression:
  222. ++this->it;
  223. this->ParseGeneratorExpression(result);
  224. return;
  225. case cmGeneratorExpressionToken::EndExpression:
  226. case cmGeneratorExpressionToken::ColonSeparator:
  227. case cmGeneratorExpressionToken::CommaSeparator:
  228. if (this->NestingLevel == 0)
  229. {
  230. extendText(result, this->it);
  231. }
  232. else
  233. {
  234. assert(!"Got unexpected syntax token.");
  235. }
  236. ++this->it;
  237. return;
  238. }
  239. assert(!"Unhandled token in generator expression.");
  240. }