cmGeneratorExpressionParser.cxx 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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. //----------------------------------------------------------------------------
  13. cmGeneratorExpressionParser::cmGeneratorExpressionParser(
  14. const std::vector<cmGeneratorExpressionToken> &tokens)
  15. : Tokens(tokens), NestingLevel(0)
  16. {
  17. }
  18. //----------------------------------------------------------------------------
  19. void cmGeneratorExpressionParser::Parse(
  20. std::vector<cmGeneratorExpressionEvaluator*> &result)
  21. {
  22. it = this->Tokens.begin();
  23. while (this->it != this->Tokens.end())
  24. {
  25. this->ParseContent(result);
  26. }
  27. }
  28. //----------------------------------------------------------------------------
  29. static void extendText(std::vector<cmGeneratorExpressionEvaluator*> &result,
  30. std::vector<cmGeneratorExpressionToken>::const_iterator it)
  31. {
  32. if (result.size() > 0
  33. && (*(result.end() - 1))->GetType()
  34. == cmGeneratorExpressionEvaluator::Text)
  35. {
  36. TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
  37. textContent->Extend(it->Length);
  38. }
  39. else
  40. {
  41. TextContent *textContent = new TextContent(it->Content, it->Length);
  42. result.push_back(textContent);
  43. }
  44. }
  45. //----------------------------------------------------------------------------
  46. static void extendResult(std::vector<cmGeneratorExpressionEvaluator*> &result,
  47. const std::vector<cmGeneratorExpressionEvaluator*> &contents)
  48. {
  49. if (result.size() > 0
  50. && (*(result.end() - 1))->GetType()
  51. == cmGeneratorExpressionEvaluator::Text
  52. && (*contents.begin())->GetType()
  53. == cmGeneratorExpressionEvaluator::Text)
  54. {
  55. TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
  56. textContent->Extend(
  57. static_cast<TextContent*>(*contents.begin())->GetLength());
  58. delete *contents.begin();
  59. result.insert(result.end(), contents.begin() + 1, contents.end());
  60. } else {
  61. result.insert(result.end(), contents.begin(), contents.end());
  62. }
  63. }
  64. //----------------------------------------------------------------------------
  65. void cmGeneratorExpressionParser::ParseGeneratorExpression(
  66. std::vector<cmGeneratorExpressionEvaluator*> &result)
  67. {
  68. unsigned int nestedLevel = this->NestingLevel;
  69. ++this->NestingLevel;
  70. std::vector<cmGeneratorExpressionToken>::const_iterator startToken
  71. = this->it - 1;
  72. std::vector<cmGeneratorExpressionEvaluator*> identifier;
  73. while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression
  74. && this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator)
  75. {
  76. this->ParseContent(identifier);
  77. if (this->it == this->Tokens.end())
  78. {
  79. break;
  80. }
  81. }
  82. if (identifier.empty())
  83. {
  84. // ERROR
  85. }
  86. if (this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
  87. {
  88. GeneratorExpressionContent *content = new GeneratorExpressionContent(
  89. startToken->Content, this->it->Content
  90. - startToken->Content
  91. + this->it->Length);
  92. ++this->it;
  93. --this->NestingLevel;
  94. content->SetIdentifier(identifier);
  95. result.push_back(content);
  96. return;
  97. }
  98. std::vector<std::vector<cmGeneratorExpressionEvaluator*> > parameters;
  99. std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
  100. commaTokens;
  101. std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
  102. if (this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  103. {
  104. colonToken = this->it;
  105. parameters.resize(parameters.size() + 1);
  106. ++this->it;
  107. while (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  108. {
  109. commaTokens.push_back(this->it);
  110. parameters.resize(parameters.size() + 1);
  111. ++this->it;
  112. }
  113. while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression)
  114. {
  115. this->ParseContent(*(parameters.end() - 1));
  116. while (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  117. {
  118. commaTokens.push_back(this->it);
  119. parameters.resize(parameters.size() + 1);
  120. ++this->it;
  121. }
  122. if (this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
  123. {
  124. extendText(*(parameters.end() - 1), this->it);
  125. ++this->it;
  126. }
  127. if (this->it == this->Tokens.end())
  128. {
  129. break;
  130. }
  131. }
  132. if(this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
  133. {
  134. --this->NestingLevel;
  135. ++this->it;
  136. }
  137. }
  138. if (nestedLevel != this->NestingLevel)
  139. {
  140. // There was a '$<' in the text, but no corresponding '>'. Rebuild to
  141. // treat the '$<' as having been plain text, along with the
  142. // corresponding : and , tokens that might have been found.
  143. extendText(result, startToken);
  144. extendResult(result, identifier);
  145. if (!parameters.empty())
  146. {
  147. extendText(result, colonToken);
  148. typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
  149. typedef std::vector<cmGeneratorExpressionToken> TokenVector;
  150. std::vector<EvaluatorVector>::const_iterator pit = parameters.begin();
  151. const std::vector<EvaluatorVector>::const_iterator pend =
  152. parameters.end();
  153. std::vector<TokenVector::const_iterator>::const_iterator commaIt =
  154. commaTokens.begin();
  155. for ( ; pit != pend; ++pit, ++commaIt)
  156. {
  157. extendResult(result, *pit);
  158. if (commaIt != commaTokens.end())
  159. {
  160. extendText(result, *commaIt);
  161. }
  162. }
  163. }
  164. return;
  165. }
  166. int contentLength = ((this->it - 1)->Content
  167. - startToken->Content)
  168. + (this->it - 1)->Length;
  169. GeneratorExpressionContent *content = new GeneratorExpressionContent(
  170. startToken->Content, contentLength);
  171. content->SetIdentifier(identifier);
  172. content->SetParameters(parameters);
  173. result.push_back(content);
  174. }
  175. //----------------------------------------------------------------------------
  176. void cmGeneratorExpressionParser::ParseContent(
  177. std::vector<cmGeneratorExpressionEvaluator*> &result)
  178. {
  179. switch(this->it->TokenType)
  180. {
  181. case cmGeneratorExpressionToken::Text:
  182. {
  183. if (this->NestingLevel == 0)
  184. {
  185. if (result.size() > 0
  186. && (*(result.end() - 1))->GetType()
  187. == cmGeneratorExpressionEvaluator::Text)
  188. {
  189. // A comma in 'plain text' could have split text that should
  190. // otherwise be continuous. Extend the last text content instead of
  191. // creating a new one.
  192. TextContent *textContent =
  193. static_cast<TextContent*>(*(result.end() - 1));
  194. textContent->Extend(this->it->Length);
  195. ++this->it;
  196. return;
  197. }
  198. }
  199. cmGeneratorExpressionEvaluator* n = new TextContent(this->it->Content,
  200. this->it->Length);
  201. result.push_back(n);
  202. ++this->it;
  203. return ;
  204. }
  205. case cmGeneratorExpressionToken::BeginExpression:
  206. ++this->it;
  207. this->ParseGeneratorExpression(result);
  208. return;
  209. case cmGeneratorExpressionToken::EndExpression:
  210. case cmGeneratorExpressionToken::ColonSeparator:
  211. case cmGeneratorExpressionToken::CommaSeparator:
  212. if (this->NestingLevel == 0)
  213. {
  214. extendText(result, this->it);
  215. }
  216. else
  217. {
  218. // TODO: Unreachable. Assert?
  219. }
  220. ++this->it;
  221. return;
  222. }
  223. // Unreachable. Assert?
  224. }