cmGeneratorExpressionParser.cxx 8.2 KB

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