1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 20:12:21 +02:00

String interpolation

This commit is contained in:
Brian Fiete 2020-11-11 05:46:52 -08:00
parent 22cc81862b
commit 281f19e04c
15 changed files with 379 additions and 59 deletions

View file

@ -357,7 +357,8 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
mLineStart = 0;
//mCurToken = (BfSyntaxToken)0;
mToken = BfToken_None;
mSyntaxToken = BfSyntaxToken_None;
mSyntaxToken = BfSyntaxToken_None;
mTokenStart = 0;
mTokenEnd = 0;
mLineNum = 0;
@ -1360,7 +1361,7 @@ double BfParser::ParseLiteralDouble()
return strtod(buf, NULL);
}
void BfParser::NextToken(int endIdx)
void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
{
auto prevToken = mToken;
@ -1372,11 +1373,13 @@ void BfParser::NextToken(int endIdx)
bool isLineStart = true;
bool isVerbatim = false;
int verbatimStart = -1;
bool isInterpolate = false;
int stringStart = -1;
while (true)
{
bool setVerbatim = false;
bool setInterpolate = false;
uint32 checkTokenHash = 0;
if ((endIdx != -1) && (mSrcIdx >= endIdx))
@ -1389,6 +1392,15 @@ void BfParser::NextToken(int endIdx)
mTokenEnd = mSrcIdx + 1;
char c = mSrc[mSrcIdx++];
if (outerIsInterpolate)
{
if (c == '"')
{
mSyntaxToken = BfSyntaxToken_StringQuote;
return;
}
}
if ((mPreprocessorIgnoreDepth > 0) && (endIdx == -1))
{
if (c == 0)
@ -1668,7 +1680,7 @@ void BfParser::NextToken(int endIdx)
case '@':
setVerbatim = true;
c = mSrc[mSrcIdx];
if (c == '\"')
if ((c == '\"') || (c == '$'))
{
setVerbatim = true;
}
@ -1679,19 +1691,29 @@ void BfParser::NextToken(int endIdx)
else
{
mSyntaxToken = BfSyntaxToken_Identifier;
//mToken = BfToken_At;
//mSyntaxToken = BfSyntaxToken_Token;
//Fail("Keyword, identifier, or string expected after verbatim specifier: @"); // CS1646
return;
}
break;
case '$':
setInterpolate = true;
c = mSrc[mSrcIdx];
if ((c == '\"') || (c == '@'))
{
setInterpolate = true;
}
else
Fail("Expected to precede string");
break;
case '"':
case '\'':
{
SizedArray<BfBlock*, 4> interpolateExpressions;
String lineHeader;
String strLiteral;
char startChar = c;
bool isMultiline = false;
int triviaStart = mTriviaStart;
if ((mSrc[mSrcIdx] == '"') && (mSrc[mSrcIdx + 1] == '"'))
{
@ -1982,16 +2004,64 @@ void BfParser::NextToken(int endIdx)
Fail("Unrecognized escape sequence");
strLiteral += c;
}
}
}
else
{
strLiteral += c;
if (isInterpolate)
{
if (c == '{')
{
BfBlock* newBlock = mAlloc->Alloc<BfBlock>();
mTokenStart = mSrcIdx - 1;
mTriviaStart = mTokenStart;
mTokenEnd = mTokenStart + 1;
mToken = BfToken_LBrace;
newBlock->mOpenBrace = (BfTokenNode*)CreateNode();
newBlock->Init(this);
ParseBlock(newBlock, 1, true);
if (mToken == BfToken_RBrace)
{
newBlock->mCloseBrace = (BfTokenNode*)CreateNode();
newBlock->SetSrcEnd(mSrcIdx);
strLiteral += "}";
}
else if ((mSyntaxToken == BfSyntaxToken_EOF) || (mSyntaxToken == BfSyntaxToken_StringQuote))
{
mSrcIdx--;
mPassInstance->FailAfterAt("Expected '}'", mSourceData, newBlock->GetSrcEnd() - 1);
}
mInAsmBlock = false;
interpolateExpressions.Add(newBlock);
}
else if (c == '}')
{
if (!interpolateExpressions.IsEmpty())
{
auto block = interpolateExpressions.back();
if (block->mCloseBrace == NULL)
{
mTokenStart = mSrcIdx - 1;
mTriviaStart = mTokenStart;
mTokenEnd = mTokenStart + 1;
mToken = BfToken_RBrace;
block->mCloseBrace = (BfTokenNode*)CreateNode();
block->SetSrcEnd(mSrcIdx);
}
}
}
}
}
}
if (isVerbatim)
if (stringStart != -1)
{
mTokenStart--;
}
mTokenStart = stringStart;
stringStart = -1;
}
mTriviaStart = triviaStart;
mTokenEnd = mSrcIdx;
mSyntaxToken = BfSyntaxToken_Literal;
if (startChar == '\'')
@ -2046,6 +2116,20 @@ void BfParser::NextToken(int endIdx)
mLiteral.mTypeCode = BfTypeCode_CharPtr;
mLiteral.mString = strLiteralPtr;
}
if (isInterpolate)
{
auto interpolateExpr = mAlloc->Alloc<BfStringInterpolationExpression>();
interpolateExpr->mString = mLiteral.mString;
interpolateExpr->mTriviaStart = mTriviaStart;
interpolateExpr->mSrcStart = mTokenStart;
interpolateExpr->mSrcEnd = mSrcIdx;
BfSizedArrayInitIndirect(interpolateExpr->mExpressions, interpolateExpressions, mAlloc);
mGeneratedNode = interpolateExpr;
mSyntaxToken = BfSyntaxToken_GeneratedNode;
mToken = BfToken_None;
}
return;
}
break;
@ -3098,8 +3182,11 @@ void BfParser::NextToken(int endIdx)
((c >= 'a') && (c <= 'z')) ||
(c == '_'))
{
if (isVerbatim)
mTokenStart = verbatimStart;
if (stringStart != -1)
{
mTokenStart = stringStart;
stringStart = -1;
}
while (true)
{
@ -3163,7 +3250,12 @@ void BfParser::NextToken(int endIdx)
if ((setVerbatim) && (!isVerbatim))
{
isVerbatim = true;
verbatimStart = mTokenStart;
stringStart = mTokenStart;
}
if ((setInterpolate) && (!isInterpolate))
{
isInterpolate = true;
stringStart = mTokenStart;
}
}
}
@ -3171,7 +3263,7 @@ void BfParser::NextToken(int endIdx)
static int gParseBlockIdx = 0;
static int gParseMemberIdx = 0;
void BfParser::ParseBlock(BfBlock* astNode, int depth)
void BfParser::ParseBlock(BfBlock* astNode, int depth, bool isInterpolate)
{
gParseBlockIdx++;
int startParseBlockIdx = gParseBlockIdx;
@ -3180,6 +3272,8 @@ void BfParser::ParseBlock(BfBlock* astNode, int depth)
SizedArray<BfAstNode*, 32> childArr;
int parenDepth = 0;
while (true)
{
if ((mSyntaxToken == BfSyntaxToken_Token) && (mToken == BfToken_Asm))
@ -3190,7 +3284,8 @@ void BfParser::ParseBlock(BfBlock* astNode, int depth)
isAsmBlock = true;
}
NextToken();
NextToken(-1, isInterpolate);
if (mPreprocessorIgnoredSectionNode != NULL)
{
if (mSyntaxToken != BfSyntaxToken_EOF)
@ -3256,7 +3351,7 @@ void BfParser::ParseBlock(BfBlock* astNode, int depth)
mInAsmBlock = false;
astNode->Add(newBlock);
childArr.push_back(newBlock);
}
}
else if (mToken == BfToken_RBrace)
{
if (depth == 0)
@ -3265,6 +3360,20 @@ void BfParser::ParseBlock(BfBlock* astNode, int depth)
}
else
{
if (mToken == BfToken_LParen)
parenDepth++;
else if (mToken == BfToken_RParen)
parenDepth--;
if ((isInterpolate) && (parenDepth == 0))
{
if ((mToken == BfToken_Colon) || (mToken == BfToken_Comma))
{
mSrcIdx = mTokenStart;
break;
}
}
astNode->Add(childNode);
childArr.push_back(childNode);
@ -3310,6 +3419,8 @@ BfAstNode* BfParser::CreateNode()
mLiteral.mWarnType = 0;
return bfLiteralExpression;
}
case BfSyntaxToken_GeneratedNode:
return mGeneratedNode;
default: break;
}