123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2012 Stephen Kelly <[email protected]>
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
- ============================================================================*/
- #include "cmGeneratorExpressionParser.h"
- #include "cmGeneratorExpressionEvaluator.h"
- //----------------------------------------------------------------------------
- cmGeneratorExpressionParser::cmGeneratorExpressionParser(
- const std::vector<cmGeneratorExpressionToken> &tokens)
- : Tokens(tokens), NestingLevel(0)
- {
- }
- //----------------------------------------------------------------------------
- void cmGeneratorExpressionParser::Parse(
- std::vector<cmGeneratorExpressionEvaluator*> &result)
- {
- it = this->Tokens.begin();
- while (this->it != this->Tokens.end())
- {
- this->ParseContent(result);
- }
- }
- //----------------------------------------------------------------------------
- static void extendText(std::vector<cmGeneratorExpressionEvaluator*> &result,
- std::vector<cmGeneratorExpressionToken>::const_iterator it)
- {
- if (result.size() > 0
- && (*(result.end() - 1))->GetType()
- == cmGeneratorExpressionEvaluator::Text)
- {
- TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
- textContent->Extend(it->Length);
- }
- else
- {
- TextContent *textContent = new TextContent(it->Content, it->Length);
- result.push_back(textContent);
- }
- }
- //----------------------------------------------------------------------------
- static void extendResult(std::vector<cmGeneratorExpressionEvaluator*> &result,
- const std::vector<cmGeneratorExpressionEvaluator*> &contents)
- {
- if (result.size() > 0
- && (*(result.end() - 1))->GetType()
- == cmGeneratorExpressionEvaluator::Text
- && (*contents.begin())->GetType()
- == cmGeneratorExpressionEvaluator::Text)
- {
- TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
- textContent->Extend(
- static_cast<TextContent*>(*contents.begin())->GetLength());
- delete *contents.begin();
- result.insert(result.end(), contents.begin() + 1, contents.end());
- } else {
- result.insert(result.end(), contents.begin(), contents.end());
- }
- }
- //----------------------------------------------------------------------------
- void cmGeneratorExpressionParser::ParseGeneratorExpression(
- std::vector<cmGeneratorExpressionEvaluator*> &result)
- {
- unsigned int nestedLevel = this->NestingLevel;
- ++this->NestingLevel;
- std::vector<cmGeneratorExpressionToken>::const_iterator startToken
- = this->it - 1;
- std::vector<cmGeneratorExpressionEvaluator*> identifier;
- while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression
- && this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator)
- {
- this->ParseContent(identifier);
- if (this->it == this->Tokens.end())
- {
- break;
- }
- }
- if (identifier.empty())
- {
- // ERROR
- }
- if (this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
- {
- GeneratorExpressionContent *content = new GeneratorExpressionContent(
- startToken->Content, this->it->Content
- - startToken->Content
- + this->it->Length);
- ++this->it;
- --this->NestingLevel;
- content->SetIdentifier(identifier);
- result.push_back(content);
- return;
- }
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> > parameters;
- std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
- commaTokens;
- std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
- if (this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
- {
- colonToken = this->it;
- parameters.resize(parameters.size() + 1);
- ++this->it;
- while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression)
- {
- this->ParseContent(*(parameters.end() - 1));
- if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
- {
- commaTokens.push_back(this->it);
- parameters.resize(parameters.size() + 1);
- ++this->it;
- }
- if (this->it == this->Tokens.end())
- {
- break;
- }
- }
- if(this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
- {
- --this->NestingLevel;
- ++this->it;
- }
- if (parameters.empty())
- {
- // ERROR
- }
- }
- if (nestedLevel != this->NestingLevel)
- {
- // 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);
- extendResult(result, identifier);
- if (!parameters.empty())
- {
- extendText(result, colonToken);
- typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
- typedef std::vector<cmGeneratorExpressionToken> TokenVector;
- std::vector<EvaluatorVector>::const_iterator pit = parameters.begin();
- const std::vector<EvaluatorVector>::const_iterator pend =
- parameters.end();
- std::vector<TokenVector::const_iterator>::const_iterator commaIt =
- commaTokens.begin();
- for ( ; pit != pend; ++pit, ++commaIt)
- {
- extendResult(result, *pit);
- if (commaIt != commaTokens.end())
- {
- extendText(result, *commaIt);
- }
- }
- }
- return;
- }
- int contentLength = ((this->it - 1)->Content
- - startToken->Content)
- + (this->it - 1)->Length;
- GeneratorExpressionContent *content = new GeneratorExpressionContent(
- startToken->Content, contentLength);
- content->SetIdentifier(identifier);
- content->SetParameters(parameters);
- result.push_back(content);
- }
- //----------------------------------------------------------------------------
- void cmGeneratorExpressionParser::ParseContent(
- std::vector<cmGeneratorExpressionEvaluator*> &result)
- {
- switch(this->it->TokenType)
- {
- case cmGeneratorExpressionToken::Text:
- {
- if (this->NestingLevel == 0)
- {
- if (result.size() > 0
- && (*(result.end() - 1))->GetType()
- == cmGeneratorExpressionEvaluator::Text)
- {
- // 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.
- TextContent *textContent =
- static_cast<TextContent*>(*(result.end() - 1));
- textContent->Extend(this->it->Length);
- ++this->it;
- return;
- }
- }
- cmGeneratorExpressionEvaluator* n = new TextContent(this->it->Content,
- this->it->Length);
- result.push_back(n);
- ++this->it;
- return ;
- }
- case cmGeneratorExpressionToken::BeginExpression:
- ++this->it;
- this->ParseGeneratorExpression(result);
- return;
- case cmGeneratorExpressionToken::EndExpression:
- case cmGeneratorExpressionToken::ColonSeparator:
- case cmGeneratorExpressionToken::CommaSeparator:
- if (this->NestingLevel == 0)
- {
- extendText(result, this->it);
- }
- else
- {
- // TODO: Unreachable. Assert?
- }
- ++this->it;
- return;
- }
- // Unreachable. Assert?
- }
|