cmGeneratorExpressionParser.cxx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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::EndExpression)
  108. {
  109. this->ParseContent(*(parameters.end() - 1));
  110. if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
  111. {
  112. commaTokens.push_back(this->it);
  113. parameters.resize(parameters.size() + 1);
  114. ++this->it;
  115. }
  116. if (this->it == this->Tokens.end())
  117. {
  118. break;
  119. }
  120. }
  121. if(this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
  122. {
  123. --this->NestingLevel;
  124. ++this->it;
  125. }
  126. if (parameters.empty())
  127. {
  128. // ERROR
  129. }
  130. }
  131. if (nestedLevel != this->NestingLevel)
  132. {
  133. // There was a '$<' in the text, but no corresponding '>'. Rebuild to
  134. // treat the '$<' as having been plain text, along with the
  135. // corresponding : and , tokens that might have been found.
  136. extendText(result, startToken);
  137. extendResult(result, identifier);
  138. if (!parameters.empty())
  139. {
  140. extendText(result, colonToken);
  141. typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
  142. typedef std::vector<cmGeneratorExpressionToken> TokenVector;
  143. std::vector<EvaluatorVector>::const_iterator pit = parameters.begin();
  144. const std::vector<EvaluatorVector>::const_iterator pend =
  145. parameters.end();
  146. std::vector<TokenVector::const_iterator>::const_iterator commaIt =
  147. commaTokens.begin();
  148. for ( ; pit != pend; ++pit, ++commaIt)
  149. {
  150. extendResult(result, *pit);
  151. if (commaIt != commaTokens.end())
  152. {
  153. extendText(result, *commaIt);
  154. }
  155. }
  156. }
  157. return;
  158. }
  159. int contentLength = ((this->it - 1)->Content
  160. - startToken->Content)
  161. + (this->it - 1)->Length;
  162. GeneratorExpressionContent *content = new GeneratorExpressionContent(
  163. startToken->Content, contentLength);
  164. content->SetIdentifier(identifier);
  165. content->SetParameters(parameters);
  166. result.push_back(content);
  167. }
  168. //----------------------------------------------------------------------------
  169. void cmGeneratorExpressionParser::ParseContent(
  170. std::vector<cmGeneratorExpressionEvaluator*> &result)
  171. {
  172. switch(this->it->TokenType)
  173. {
  174. case cmGeneratorExpressionToken::Text:
  175. {
  176. if (this->NestingLevel == 0)
  177. {
  178. if (result.size() > 0
  179. && (*(result.end() - 1))->GetType()
  180. == cmGeneratorExpressionEvaluator::Text)
  181. {
  182. // A comma in 'plain text' could have split text that should
  183. // otherwise be continuous. Extend the last text content instead of
  184. // creating a new one.
  185. TextContent *textContent =
  186. static_cast<TextContent*>(*(result.end() - 1));
  187. textContent->Extend(this->it->Length);
  188. ++this->it;
  189. return;
  190. }
  191. }
  192. cmGeneratorExpressionEvaluator* n = new TextContent(this->it->Content,
  193. this->it->Length);
  194. result.push_back(n);
  195. ++this->it;
  196. return ;
  197. }
  198. case cmGeneratorExpressionToken::BeginExpression:
  199. ++this->it;
  200. this->ParseGeneratorExpression(result);
  201. return;
  202. case cmGeneratorExpressionToken::EndExpression:
  203. case cmGeneratorExpressionToken::ColonSeparator:
  204. case cmGeneratorExpressionToken::CommaSeparator:
  205. if (this->NestingLevel == 0)
  206. {
  207. extendText(result, this->it);
  208. }
  209. else
  210. {
  211. // TODO: Unreachable. Assert?
  212. }
  213. ++this->it;
  214. return;
  215. }
  216. // Unreachable. Assert?
  217. }