PP: Implement token pasting for PP identifiers.
Implement token pasting as per the C++ specification, within the current style of the PP code. Non-identifiers (turning 12 ## 10 into the numeral 1210) is not yet covered; they should be a simple incremental change built on this one. Addresses issue #255.
This commit is contained in:
parent
abf5057948
commit
d485e0b710
10 changed files with 304 additions and 34 deletions
|
|
@ -739,6 +739,11 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
|
|||
for(;;) {
|
||||
token = scanToken(ppToken);
|
||||
ppToken->token = token;
|
||||
|
||||
// Handle token-pasting logic
|
||||
token = tokenPaste(*ppToken);
|
||||
ppToken->token = token;
|
||||
|
||||
if (token == EndOfInput) {
|
||||
missingEndifCheck();
|
||||
return nullptr;
|
||||
|
|
@ -800,6 +805,47 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Do all token-pasting related combining of two pasted tokens when getting a
|
||||
// stream of tokens from a replacement list. Degenerates to no processing if a
|
||||
// replacement list is not the source of the token stream.
|
||||
//
|
||||
int TPpContext::tokenPaste(TPpToken& ppToken)
|
||||
{
|
||||
// starting with ## is illegal, skip to next token
|
||||
if (ppToken.token == PpAtomPaste) {
|
||||
parseContext.ppError(ppToken.loc, "unexpected location", "##", "");
|
||||
ppToken.token = scanToken(&ppToken);
|
||||
}
|
||||
|
||||
// ## can be chained, process all in the chain at once
|
||||
while (peekPasting()) {
|
||||
TPpToken pastedPpToken;
|
||||
|
||||
// next token has to be ##
|
||||
pastedPpToken.token = scanToken(&pastedPpToken);
|
||||
assert(pastedPpToken.token == PpAtomPaste);
|
||||
|
||||
if (endOfReplacementList()) {
|
||||
parseContext.ppError(ppToken.loc, "unexpected location; end of replacement list", "##", "");
|
||||
break;
|
||||
}
|
||||
|
||||
// get the token after the ##
|
||||
scanToken(&pastedPpToken);
|
||||
|
||||
// combine the tokens
|
||||
if (strlen(ppToken.name) + strlen(pastedPpToken.name) > MaxTokenLength)
|
||||
parseContext.ppError(ppToken.loc, "combined tokens are too long", "##", "");
|
||||
strncat(ppToken.name, pastedPpToken.name, MaxTokenLength - strlen(ppToken.name));
|
||||
ppToken.atom = LookUpAddString(ppToken.name);
|
||||
if (ppToken.token != PpAtomIdentifier)
|
||||
parseContext.ppError(ppToken.loc, "only supported for preprocessing identifiers", "##", "");
|
||||
}
|
||||
|
||||
return ppToken.token;
|
||||
}
|
||||
|
||||
// Checks if we've seen balanced #if...#endif
|
||||
void TPpContext::missingEndifCheck()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue