1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Multi-$ string interpolation

This commit is contained in:
Brian Fiete 2022-04-19 17:49:28 -07:00
parent 3ef627e3e2
commit 5fd9552331

View file

@ -1397,7 +1397,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
bool isLineStart = true; bool isLineStart = true;
bool isVerbatim = false; bool isVerbatim = false;
bool isInterpolate = false; int interpolateSetting = 0;
int stringStart = -1; int stringStart = -1;
while (true) while (true)
@ -1754,7 +1754,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
case '$': case '$':
c = mSrc[mSrcIdx]; c = mSrc[mSrcIdx];
if ((c == '\"') || (c == '@')) if ((c == '\"') || (c == '@') || (c == '$'))
{ {
setInterpolate = true; setInterpolate = true;
} }
@ -1966,6 +1966,14 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
case '\'': case '\'':
strLiteral += c; strLiteral += c;
break; break;
case '{':
case '}':
strLiteral += c;
if (interpolateSetting > 0)
strLiteral += c;
else
Fail("Invalid escape sequence");
break;
case 'x': case 'x':
{ {
int wantHexChars = 2; int wantHexChars = 2;
@ -2061,24 +2069,28 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
Fail("Unrecognized escape sequence"); Fail("Unrecognized escape sequence");
strLiteral += c; strLiteral += c;
} }
} }
else else
{ {
strLiteral += c; strLiteral += c;
if (isInterpolate) if (interpolateSetting > 0)
{ {
if (c == '{') if (c == '{')
{ {
if (mSrc[mSrcIdx] == '{') int braceCount = 1;
while (mSrc[mSrcIdx] == '{')
{ {
strLiteral += '{'; braceCount++;
mSrcIdx++; mSrcIdx++;
} }
else
int literalBraces = braceCount;
if (((interpolateSetting == 1) && (braceCount % 2 == 1)) ||
((interpolateSetting > 1) && (braceCount >= interpolateSetting)))
{ {
BfUnscopedBlock* newBlock = mAlloc->Alloc<BfUnscopedBlock>(); BfUnscopedBlock* newBlock = mAlloc->Alloc<BfUnscopedBlock>();
mTokenStart = mSrcIdx - 1; mTokenStart = mSrcIdx - interpolateSetting;
mTriviaStart = mTokenStart; mTriviaStart = mTokenStart;
mTokenEnd = mTokenStart + 1; mTokenEnd = mTokenStart + 1;
mToken = BfToken_LBrace; mToken = BfToken_LBrace;
@ -2089,7 +2101,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
{ {
newBlock->mCloseBrace = (BfTokenNode*)CreateNode(); newBlock->mCloseBrace = (BfTokenNode*)CreateNode();
newBlock->SetSrcEnd(mSrcIdx); newBlock->SetSrcEnd(mSrcIdx);
strLiteral += "}"; mSrcIdx--;
} }
else if ((mSyntaxToken == BfSyntaxToken_EOF) || (mSyntaxToken == BfSyntaxToken_StringQuote)) else if ((mSyntaxToken == BfSyntaxToken_EOF) || (mSyntaxToken == BfSyntaxToken_StringQuote))
{ {
@ -2097,17 +2109,40 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
mPassInstance->FailAfterAt("Expected '}'", mSourceData, newBlock->GetSrcEnd() - 1); mPassInstance->FailAfterAt("Expected '}'", mSourceData, newBlock->GetSrcEnd() - 1);
} }
mInAsmBlock = false; mInAsmBlock = false;
interpolateExpressions.Add(newBlock); interpolateExpressions.Add(newBlock);
}
if (interpolateSetting == 1)
{
for (int i = 0; i < braceCount - 1; i++)
strLiteral += '{';
}
else
{
if (braceCount >= interpolateSetting)
{
for (int i = 0; i < (braceCount - interpolateSetting) * 2; i++)
strLiteral += '{';
}
else
{
for (int i = 0; i < braceCount * 2 - 1; i++)
strLiteral += '{';
}
} }
} }
else if (c == '}') else if (c == '}')
{ {
if (mSrc[mSrcIdx] == '}') int braceCount = 1;
while (mSrc[mSrcIdx] == '}')
{ {
strLiteral += '}'; braceCount++;
mSrcIdx++; mSrcIdx++;
} }
else if (!interpolateExpressions.IsEmpty())
bool isClosingBrace = false;
if (!interpolateExpressions.IsEmpty())
{ {
auto block = interpolateExpressions.back(); auto block = interpolateExpressions.back();
if (block->mCloseBrace == NULL) if (block->mCloseBrace == NULL)
@ -2118,6 +2153,34 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
mToken = BfToken_RBrace; mToken = BfToken_RBrace;
block->mCloseBrace = (BfTokenNode*)CreateNode(); block->mCloseBrace = (BfTokenNode*)CreateNode();
block->SetSrcEnd(mSrcIdx); block->SetSrcEnd(mSrcIdx);
isClosingBrace = true;
}
else if (block->mCloseBrace->mSrcStart == mSrcIdx - braceCount)
{
block->mCloseBrace->mSrcEnd = mSrcIdx - braceCount + interpolateSetting;
isClosingBrace = true;
}
}
if (interpolateSetting == 1)
{
for (int i = 0; i < braceCount - 1; i++)
strLiteral += '}';
}
else
{
if (isClosingBrace)
{
if (braceCount < interpolateSetting)
Fail("Mismatched closing brace set");
for (int i = 0; i < (braceCount - interpolateSetting) * 2; i++)
strLiteral += '}';
}
else
{
for (int i = 0; i < braceCount * 2 - 1; i++)
strLiteral += '}';
} }
} }
} }
@ -2187,7 +2250,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
mLiteral.mString = strLiteralPtr; mLiteral.mString = strLiteralPtr;
} }
if (isInterpolate) if (interpolateSetting > 0)
{ {
if (mLiteral.mTypeCode == BfTypeCode_CharPtr) if (mLiteral.mTypeCode == BfTypeCode_CharPtr)
{ {
@ -2196,7 +2259,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
interpolateExpr->mTriviaStart = mTriviaStart; interpolateExpr->mTriviaStart = mTriviaStart;
interpolateExpr->mSrcStart = mTokenStart; interpolateExpr->mSrcStart = mTokenStart;
interpolateExpr->mSrcEnd = mSrcIdx; interpolateExpr->mSrcEnd = mSrcIdx;
BfSizedArrayInitIndirect(interpolateExpr->mExpressions, interpolateExpressions, mAlloc); BfSizedArrayInitIndirect(interpolateExpr->mExpressions, interpolateExpressions, mAlloc);
mGeneratedNode = interpolateExpr; mGeneratedNode = interpolateExpr;
mSyntaxToken = BfSyntaxToken_GeneratedNode; mSyntaxToken = BfSyntaxToken_GeneratedNode;
mToken = BfToken_None; mToken = BfToken_None;
@ -3354,10 +3417,11 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
isVerbatim = true; isVerbatim = true;
stringStart = mTokenStart; stringStart = mTokenStart;
} }
if ((setInterpolate) && (!isInterpolate)) if (setInterpolate)
{ {
isInterpolate = true; if (interpolateSetting == 0)
stringStart = mTokenStart; stringStart = mTokenStart;
interpolateSetting++;
} }
} }
} }