cmake/Source/cmGeneratorExpressionParser.cxx

249 lines
8.1 KiB
C++
Raw Normal View History

2016-10-30 18:24:19 +01:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
2013-03-16 19:13:01 +02:00
#include "cmGeneratorExpressionParser.h"
2020-02-01 23:06:01 +01:00
#include <cassert>
#include <cstddef>
#include <utility>
2020-08-30 11:54:41 +02:00
#include <cm/memory>
#include <cmext/algorithm>
#include <cmext/memory>
2013-03-16 19:13:01 +02:00
#include "cmGeneratorExpressionEvaluator.h"
cmGeneratorExpressionParser::cmGeneratorExpressionParser(
2019-11-11 23:01:05 +01:00
std::vector<cmGeneratorExpressionToken> tokens)
: Tokens(std::move(tokens))
2013-03-16 19:13:01 +02:00
{
}
void cmGeneratorExpressionParser::Parse(
2020-08-30 11:54:41 +02:00
cmGeneratorExpressionEvaluatorVector& result)
2013-03-16 19:13:01 +02:00
{
2021-09-14 00:13:48 +02:00
this->it = this->Tokens.begin();
2013-03-16 19:13:01 +02:00
2016-07-09 11:21:54 +02:00
while (this->it != this->Tokens.end()) {
2013-03-16 19:13:01 +02:00
this->ParseContent(result);
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
}
2016-07-09 11:21:54 +02:00
static void extendText(
2020-08-30 11:54:41 +02:00
cmGeneratorExpressionEvaluatorVector& result,
2016-07-09 11:21:54 +02:00
std::vector<cmGeneratorExpressionToken>::const_iterator it)
2013-03-16 19:13:01 +02:00
{
2016-07-09 11:21:54 +02:00
if (!result.empty() &&
(*(result.end() - 1))->GetType() ==
cmGeneratorExpressionEvaluator::Text) {
2020-08-30 11:54:41 +02:00
cm::static_reference_cast<TextContent>(*(result.end() - 1))
.Extend(it->Length);
2016-07-09 11:21:54 +02:00
} else {
2020-08-30 11:54:41 +02:00
auto textContent = cm::make_unique<TextContent>(it->Content, it->Length);
result.push_back(std::move(textContent));
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
}
2016-07-09 11:21:54 +02:00
static void extendResult(
2020-08-30 11:54:41 +02:00
cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector& result,
cmGeneratorExpressionParser::cmGeneratorExpressionEvaluatorVector&& contents)
2013-03-16 19:13:01 +02:00
{
2016-07-09 11:21:54 +02:00
if (!result.empty() &&
(*(result.end() - 1))->GetType() ==
cmGeneratorExpressionEvaluator::Text &&
2019-11-11 23:01:05 +01:00
contents.front()->GetType() == cmGeneratorExpressionEvaluator::Text) {
2020-08-30 11:54:41 +02:00
cm::static_reference_cast<TextContent>(*(result.end() - 1))
.Extend(
cm::static_reference_cast<TextContent>(contents.front()).GetLength());
contents.erase(contents.begin());
2013-03-16 19:13:01 +02:00
}
2020-08-30 11:54:41 +02:00
cm::append(result, std::move(contents));
2013-03-16 19:13:01 +02:00
}
void cmGeneratorExpressionParser::ParseGeneratorExpression(
2020-08-30 11:54:41 +02:00
cmGeneratorExpressionEvaluatorVector& result)
2013-03-16 19:13:01 +02:00
{
assert(this->it != this->Tokens.end());
unsigned int nestedLevel = this->NestingLevel;
++this->NestingLevel;
2020-02-01 23:06:01 +01:00
auto startToken = this->it - 1;
2013-03-16 19:13:01 +02:00
2020-08-30 11:54:41 +02:00
cmGeneratorExpressionEvaluatorVector identifier;
2016-07-09 11:21:54 +02:00
while (this->it->TokenType != cmGeneratorExpressionToken::EndExpression &&
this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator) {
if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) {
2013-03-16 19:13:01 +02:00
extendText(identifier, this->it);
++this->it;
2016-07-09 11:21:54 +02:00
} else {
2013-03-16 19:13:01 +02:00
this->ParseContent(identifier);
2016-07-09 11:21:54 +02:00
}
if (this->it == this->Tokens.end()) {
2013-03-16 19:13:01 +02:00
break;
}
2016-07-09 11:21:54 +02:00
}
if (identifier.empty()) {
2013-03-16 19:13:01 +02:00
// ERROR
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
if (this->it != this->Tokens.end() &&
2016-07-09 11:21:54 +02:00
this->it->TokenType == cmGeneratorExpressionToken::EndExpression) {
2020-08-30 11:54:41 +02:00
auto content = cm::make_unique<GeneratorExpressionContent>(
2018-08-09 18:06:22 +02:00
startToken->Content,
this->it->Content - startToken->Content + this->it->Length);
2013-03-16 19:13:01 +02:00
assert(this->it != this->Tokens.end());
++this->it;
--this->NestingLevel;
2018-08-09 18:06:22 +02:00
content->SetIdentifier(std::move(identifier));
2020-08-30 11:54:41 +02:00
result.push_back(std::move(content));
2013-03-16 19:13:01 +02:00
return;
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
2020-08-30 11:54:41 +02:00
std::vector<cmGeneratorExpressionEvaluatorVector> parameters;
2013-03-16 19:13:01 +02:00
std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
2016-07-09 11:21:54 +02:00
commaTokens;
2013-03-16 19:13:01 +02:00
std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
2013-11-03 12:27:13 +02:00
bool emptyParamTermination = false;
2013-03-16 19:13:01 +02:00
if (this->it != this->Tokens.end() &&
2016-07-09 11:21:54 +02:00
this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) {
2013-03-16 19:13:01 +02:00
colonToken = this->it;
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
2016-07-09 11:21:54 +02:00
if (this->it == this->Tokens.end()) {
2013-11-03 12:27:13 +02:00
emptyParamTermination = true;
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
while (this->it != this->Tokens.end() &&
2016-07-09 11:21:54 +02:00
this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator) {
2013-03-16 19:13:01 +02:00
commaTokens.push_back(this->it);
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
2016-07-09 11:21:54 +02:00
if (this->it == this->Tokens.end()) {
2013-11-03 12:27:13 +02:00
emptyParamTermination = true;
2013-03-16 19:13:01 +02:00
}
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
while (this->it != this->Tokens.end() &&
2016-07-09 11:21:54 +02:00
this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator) {
2013-03-16 19:13:01 +02:00
extendText(*(parameters.end() - 1), this->it);
assert(this->it != this->Tokens.end());
++this->it;
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
while (this->it != this->Tokens.end() &&
2016-07-09 11:21:54 +02:00
this->it->TokenType != cmGeneratorExpressionToken::EndExpression) {
2013-03-16 19:13:01 +02:00
this->ParseContent(*(parameters.end() - 1));
2016-07-09 11:21:54 +02:00
if (this->it == this->Tokens.end()) {
2013-03-16 19:13:01 +02:00
break;
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
while (this->it != this->Tokens.end() &&
2016-07-09 11:21:54 +02:00
this->it->TokenType ==
cmGeneratorExpressionToken::CommaSeparator) {
2013-03-16 19:13:01 +02:00
commaTokens.push_back(this->it);
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
2016-07-09 11:21:54 +02:00
if (this->it == this->Tokens.end()) {
2013-11-03 12:27:13 +02:00
emptyParamTermination = true;
2013-03-16 19:13:01 +02:00
}
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
while (this->it != this->Tokens.end() &&
2016-07-09 11:21:54 +02:00
this->it->TokenType ==
cmGeneratorExpressionToken::ColonSeparator) {
2013-03-16 19:13:01 +02:00
extendText(*(parameters.end() - 1), this->it);
assert(this->it != this->Tokens.end());
++this->it;
}
}
2016-07-09 11:21:54 +02:00
if (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::EndExpression) {
--this->NestingLevel;
assert(this->it != this->Tokens.end());
++this->it;
}
}
2013-03-16 19:13:01 +02:00
2016-07-09 11:21:54 +02:00
if (nestedLevel != this->NestingLevel) {
2013-03-16 19:13:01 +02:00
// There was a '$<' in the text, but no corresponding '>'. Rebuild to
// treat the '$<' as having been plain text, along with the
// corresponding : and , tokens that might have been found.
extendText(result, startToken);
2020-08-30 11:54:41 +02:00
extendResult(result, std::move(identifier));
2016-07-09 11:21:54 +02:00
if (!parameters.empty()) {
2013-03-16 19:13:01 +02:00
extendText(result, colonToken);
2020-02-01 23:06:01 +01:00
auto pit = parameters.begin();
const auto pend = parameters.end();
auto commaIt = commaTokens.begin();
2013-03-16 19:13:01 +02:00
assert(parameters.size() > commaTokens.size());
2016-07-09 11:21:54 +02:00
for (; pit != pend; ++pit, ++commaIt) {
if (!pit->empty() && !emptyParamTermination) {
2020-08-30 11:54:41 +02:00
extendResult(result, std::move(*pit));
2016-07-09 11:21:54 +02:00
}
if (commaIt != commaTokens.end()) {
2013-03-16 19:13:01 +02:00
extendText(result, *commaIt);
2016-07-09 11:21:54 +02:00
} else {
2013-03-16 19:13:01 +02:00
break;
}
}
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
return;
}
2016-07-09 11:21:54 +02:00
size_t contentLength =
((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length;
2020-08-30 11:54:41 +02:00
auto content = cm::make_unique<GeneratorExpressionContent>(
startToken->Content, contentLength);
2018-08-09 18:06:22 +02:00
content->SetIdentifier(std::move(identifier));
content->SetParameters(std::move(parameters));
2020-08-30 11:54:41 +02:00
result.push_back(std::move(content));
2013-03-16 19:13:01 +02:00
}
void cmGeneratorExpressionParser::ParseContent(
2020-08-30 11:54:41 +02:00
cmGeneratorExpressionEvaluatorVector& result)
2013-03-16 19:13:01 +02:00
{
assert(this->it != this->Tokens.end());
2016-07-09 11:21:54 +02:00
switch (this->it->TokenType) {
case cmGeneratorExpressionToken::Text: {
if (this->NestingLevel == 0) {
if (!result.empty() &&
(*(result.end() - 1))->GetType() ==
cmGeneratorExpressionEvaluator::Text) {
2013-03-16 19:13:01 +02:00
// A comma in 'plain text' could have split text that should
// otherwise be continuous. Extend the last text content instead of
// creating a new one.
2020-08-30 11:54:41 +02:00
cm::static_reference_cast<TextContent>(*(result.end() - 1))
.Extend(this->it->Length);
2013-03-16 19:13:01 +02:00
assert(this->it != this->Tokens.end());
++this->it;
return;
}
2016-07-09 11:21:54 +02:00
}
2020-08-30 11:54:41 +02:00
auto n =
cm::make_unique<TextContent>(this->it->Content, this->it->Length);
result.push_back(std::move(n));
2013-03-16 19:13:01 +02:00
assert(this->it != this->Tokens.end());
++this->it;
2016-07-09 11:21:54 +02:00
return;
2013-03-16 19:13:01 +02:00
}
case cmGeneratorExpressionToken::BeginExpression:
assert(this->it != this->Tokens.end());
++this->it;
this->ParseGeneratorExpression(result);
return;
case cmGeneratorExpressionToken::EndExpression:
case cmGeneratorExpressionToken::ColonSeparator:
case cmGeneratorExpressionToken::CommaSeparator:
2016-07-09 11:21:54 +02:00
if (this->NestingLevel == 0) {
2013-03-16 19:13:01 +02:00
extendText(result, this->it);
2016-07-09 11:21:54 +02:00
} else {
2017-04-14 19:02:05 +02:00
assert(false && "Got unexpected syntax token.");
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
assert(this->it != this->Tokens.end());
++this->it;
return;
2016-07-09 11:21:54 +02:00
}
2017-04-14 19:02:05 +02:00
assert(false && "Unhandled token in generator expression.");
2013-03-16 19:13:01 +02:00
}