Merge topic 'dev/faster-parsers'
048be205
Help: Add release notes for the 'faster-parsers' topic7c565d2f
cmGeneratorExpression: Improve parsing in StripEmptyListElements68eb1757
cmGeneratorExpressionLexer: Use a switch statement to parse67253133
ExpandListArguments: Optimize the parser
This commit is contained in:
commit
958cd84431
|
@ -0,0 +1,6 @@
|
||||||
|
faster-parsers
|
||||||
|
--------------
|
||||||
|
|
||||||
|
* The :manual:`cmake-language(7)` internal implementation of generator
|
||||||
|
expression and list expansion parsers have been optimized and shows
|
||||||
|
non-trivial speedup on large projects.
|
|
@ -157,17 +157,24 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
|
||||||
std::string cmGeneratorExpression::StripEmptyListElements(
|
std::string cmGeneratorExpression::StripEmptyListElements(
|
||||||
const std::string &input)
|
const std::string &input)
|
||||||
{
|
{
|
||||||
|
if (input.find(';') == input.npos)
|
||||||
|
{
|
||||||
|
return input;
|
||||||
|
}
|
||||||
std::string result;
|
std::string result;
|
||||||
|
result.reserve(input.size());
|
||||||
|
|
||||||
const char *c = input.c_str();
|
const char *c = input.c_str();
|
||||||
|
const char *last = c;
|
||||||
bool skipSemiColons = true;
|
bool skipSemiColons = true;
|
||||||
for ( ; *c; ++c)
|
for ( ; *c; ++c)
|
||||||
{
|
{
|
||||||
if(c[0] == ';')
|
if(*c == ';')
|
||||||
{
|
{
|
||||||
if(skipSemiColons)
|
if(skipSemiColons)
|
||||||
{
|
{
|
||||||
continue;
|
result.append(last, c - last);
|
||||||
|
last = c + 1;
|
||||||
}
|
}
|
||||||
skipSemiColons = true;
|
skipSemiColons = true;
|
||||||
}
|
}
|
||||||
|
@ -175,8 +182,8 @@ std::string cmGeneratorExpression::StripEmptyListElements(
|
||||||
{
|
{
|
||||||
skipSemiColons = false;
|
skipSemiColons = false;
|
||||||
}
|
}
|
||||||
result += *c;
|
|
||||||
}
|
}
|
||||||
|
result.append(last);
|
||||||
|
|
||||||
if (!result.empty() && *(result.end() - 1) == ';')
|
if (!result.empty() && *(result.end() - 1) == ';')
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,40 +43,40 @@ cmGeneratorExpressionLexer::Tokenize(const char *input)
|
||||||
|
|
||||||
for ( ; *c; ++c)
|
for ( ; *c; ++c)
|
||||||
{
|
{
|
||||||
if(c[0] == '$' && c[1] == '<')
|
switch(*c)
|
||||||
|
{
|
||||||
|
case '$':
|
||||||
|
if(c[1] == '<')
|
||||||
{
|
{
|
||||||
InsertText(upto, c, result);
|
InsertText(upto, c, result);
|
||||||
upto = c;
|
|
||||||
result.push_back(cmGeneratorExpressionToken(
|
result.push_back(cmGeneratorExpressionToken(
|
||||||
cmGeneratorExpressionToken::BeginExpression, upto, 2));
|
cmGeneratorExpressionToken::BeginExpression, c, 2));
|
||||||
upto = c + 2;
|
upto = c + 2;
|
||||||
++c;
|
++c;
|
||||||
SawBeginExpression = true;
|
SawBeginExpression = true;
|
||||||
}
|
}
|
||||||
else if(c[0] == '>')
|
break;
|
||||||
{
|
case '>':
|
||||||
InsertText(upto, c, result);
|
InsertText(upto, c, result);
|
||||||
upto = c;
|
|
||||||
result.push_back(cmGeneratorExpressionToken(
|
result.push_back(cmGeneratorExpressionToken(
|
||||||
cmGeneratorExpressionToken::EndExpression, upto, 1));
|
cmGeneratorExpressionToken::EndExpression, c, 1));
|
||||||
upto = c + 1;
|
upto = c + 1;
|
||||||
SawGeneratorExpression = SawBeginExpression;
|
SawGeneratorExpression = SawBeginExpression;
|
||||||
}
|
break;
|
||||||
else if(c[0] == ':')
|
case ':':
|
||||||
{
|
|
||||||
InsertText(upto, c, result);
|
InsertText(upto, c, result);
|
||||||
upto = c;
|
|
||||||
result.push_back(cmGeneratorExpressionToken(
|
result.push_back(cmGeneratorExpressionToken(
|
||||||
cmGeneratorExpressionToken::ColonSeparator, upto, 1));
|
cmGeneratorExpressionToken::ColonSeparator, c, 1));
|
||||||
upto = c + 1;
|
upto = c + 1;
|
||||||
}
|
break;
|
||||||
else if(c[0] == ',')
|
case ',':
|
||||||
{
|
|
||||||
InsertText(upto, c, result);
|
InsertText(upto, c, result);
|
||||||
upto = c;
|
|
||||||
result.push_back(cmGeneratorExpressionToken(
|
result.push_back(cmGeneratorExpressionToken(
|
||||||
cmGeneratorExpressionToken::CommaSeparator, upto, 1));
|
cmGeneratorExpressionToken::CommaSeparator, c, 1));
|
||||||
upto = c + 1;
|
upto = c + 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InsertText(upto, c, result);
|
InsertText(upto, c, result);
|
||||||
|
|
|
@ -1044,7 +1044,7 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
|
||||||
bool emptyArgs)
|
bool emptyArgs)
|
||||||
{
|
{
|
||||||
// If argument is empty, it is an empty list.
|
// If argument is empty, it is an empty list.
|
||||||
if(arg.length() == 0 && !emptyArgs)
|
if(!emptyArgs && arg.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1054,10 +1054,11 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
|
||||||
newargs.push_back(arg);
|
newargs.push_back(arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<char> newArgVec;
|
std::string newArg;
|
||||||
|
const char *last = arg.c_str();
|
||||||
// Break the string at non-escaped semicolons not nested in [].
|
// Break the string at non-escaped semicolons not nested in [].
|
||||||
int squareNesting = 0;
|
int squareNesting = 0;
|
||||||
for(const char* c = arg.c_str(); *c; ++c)
|
for(const char* c = last; *c; ++c)
|
||||||
{
|
{
|
||||||
switch(*c)
|
switch(*c)
|
||||||
{
|
{
|
||||||
|
@ -1065,34 +1066,21 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
|
||||||
{
|
{
|
||||||
// We only want to allow escaping of semicolons. Other
|
// We only want to allow escaping of semicolons. Other
|
||||||
// escapes should not be processed here.
|
// escapes should not be processed here.
|
||||||
++c;
|
const char* next = c + 1;
|
||||||
if(*c == ';')
|
if(*next == ';')
|
||||||
{
|
{
|
||||||
newArgVec.push_back(*c);
|
newArg.append(last, c - last);
|
||||||
}
|
// Skip over the escape character
|
||||||
else
|
last = c = next;
|
||||||
{
|
|
||||||
newArgVec.push_back('\\');
|
|
||||||
if(*c)
|
|
||||||
{
|
|
||||||
newArgVec.push_back(*c);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Terminate the loop properly.
|
|
||||||
--c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case '[':
|
case '[':
|
||||||
{
|
{
|
||||||
++squareNesting;
|
++squareNesting;
|
||||||
newArgVec.push_back(*c);
|
|
||||||
} break;
|
} break;
|
||||||
case ']':
|
case ']':
|
||||||
{
|
{
|
||||||
--squareNesting;
|
--squareNesting;
|
||||||
newArgVec.push_back(*c);
|
|
||||||
} break;
|
} break;
|
||||||
case ';':
|
case ';':
|
||||||
{
|
{
|
||||||
|
@ -1100,31 +1088,28 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
|
||||||
// brackets.
|
// brackets.
|
||||||
if(squareNesting == 0)
|
if(squareNesting == 0)
|
||||||
{
|
{
|
||||||
if ( newArgVec.size() || emptyArgs )
|
newArg.append(last, c - last);
|
||||||
|
// Skip over the semicolon
|
||||||
|
last = c + 1;
|
||||||
|
if ( !newArg.empty() || emptyArgs )
|
||||||
{
|
{
|
||||||
// Add the last argument if the string is not empty.
|
// Add the last argument if the string is not empty.
|
||||||
newArgVec.push_back(0);
|
newargs.push_back(newArg);
|
||||||
newargs.push_back(&*newArgVec.begin());
|
newArg = "";
|
||||||
newArgVec.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
newArgVec.push_back(*c);
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// Just append this character.
|
// Just append this character.
|
||||||
newArgVec.push_back(*c);
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( newArgVec.size() || emptyArgs )
|
newArg.append(last);
|
||||||
|
if ( !newArg.empty() || emptyArgs )
|
||||||
{
|
{
|
||||||
// Add the last argument if the string is not empty.
|
// Add the last argument if the string is not empty.
|
||||||
newArgVec.push_back(0);
|
newargs.push_back(newArg);
|
||||||
newargs.push_back(&*newArgVec.begin());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue