cmGeneratorExpressionParser.cxx 8.5 KB

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