2019-08-23 11:56:54 -07:00
# include "BfAst.h"
# include "BfReducer.h"
# include "BfParser.h"
# include "BfSystem.h"
# include "BfUtil.h"
# include "BeefySysLib/util/BeefPerf.h"
# include "BeefySysLib/util/StackHelper.h"
# include "BeefySysLib/util/AllocDebug.h"
# include <functional>
USING_NS_BF ;
# define MEMBER_SET(dest, member, src) \
{ dest - > member = src ; \
MoveNode ( src , dest ) ; }
# define MEMBER_SET_CHECKED(dest, member, src) \
{ if ( src = = NULL ) return dest ; \
dest - > member = src ; \
MoveNode ( src , dest ) ; }
# define MEMBER_SET_CHECKED_BOOL(dest, member, src) \
{ if ( src = = NULL ) return false ; \
dest - > member = src ; \
MoveNode ( src , dest ) ; }
BfReducer : : BfReducer ( )
{
mCurTypeDecl = NULL ;
mLastTypeDecl = NULL ;
mCurMethodDecl = NULL ;
mSource = NULL ;
mClassDepth = 0 ;
mAlloc = NULL ;
mStmtHasError = false ;
mPrevStmtHadError = false ;
mPassInstance = NULL ;
mCompatMode = false ;
mAllowTypeWildcard = false ;
mIsFieldInitializer = false ;
mInParenExpr = false ;
mSkipCurrentNodeAssert = false ;
mAssertCurrentNodeIdx = 0 ;
mSystem = NULL ;
mResolvePassData = NULL ;
mMethodDepth = 0 ;
mDocumentCheckIdx = 0 ;
mTypeMemberNodeStart = NULL ;
}
bool BfReducer : : IsSemicolon ( BfAstNode * node )
{
auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) ;
return ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_Semicolon ) ;
}
bool BfReducer : : StringEquals ( BfAstNode * node , BfAstNode * node2 )
{
int len = node - > GetSrcLength ( ) ;
int len2 = node2 - > GetSrcLength ( ) ;
if ( len ! = len2 )
return false ;
int start = node - > GetSrcStart ( ) ;
int start2 = node2 - > GetSrcStart ( ) ;
const char * srcStr = node - > GetSourceData ( ) - > mSrc ;
for ( int i = 0 ; i < len ; i + + )
{
if ( srcStr [ start + i ] ! = srcStr [ start2 + i ] )
return false ;
}
return true ;
}
int gAssertCurrentNodeIdx = 0 ;
void BfReducer : : AssertCurrentNode ( BfAstNode * node )
{
if ( mSkipCurrentNodeAssert )
return ;
auto currentNode = mVisitorPos . GetCurrent ( ) ;
if ( currentNode = = NULL )
return ;
if ( ! node - > LocationEndEquals ( currentNode ) )
{
const char * lastCPtr = & node - > GetSourceData ( ) - > mSrc [ node - > GetSrcEnd ( ) - 1 ] ;
// We have an "exceptional" case where breaking a double chevron will look like a position error
if ( ( lastCPtr [ 0 ] ! = ' > ' ) | | ( lastCPtr [ 1 ] ! = ' > ' ) )
{
BF_FATAL ( " Internal parsing error " ) ;
}
}
gAssertCurrentNodeIdx + + ;
mAssertCurrentNodeIdx + + ;
}
// For autocomplete we only do a reduce on nodes the cursor is in
bool BfReducer : : IsNodeRelevant ( BfAstNode * astNode )
{
BfParser * bfParser = astNode - > GetSourceData ( ) - > ToParser ( ) ;
if ( bfParser = = NULL )
return true ;
int cursorPos = bfParser - > mCursorIdx ;
if ( ( cursorPos = = - 1 ) | | ( astNode - > Contains ( cursorPos , 1 , 0 ) ) )
return true ;
BF_ASSERT ( bfParser - > mParserData - > mRefCount = = - 1 ) ;
return false ;
}
bool BfReducer : : IsNodeRelevant ( BfAstNode * startNode , BfAstNode * endNode )
{
BfParser * bfParser = startNode - > GetSourceData ( ) - > ToParser ( ) ;
if ( bfParser = = NULL )
return true ;
int cursorPos = bfParser - > mCursorIdx ;
int lenAdd = 1 ;
if ( ( cursorPos = = - 1 ) | |
( ( cursorPos > = startNode - > GetSrcStart ( ) ) & & ( cursorPos < endNode - > GetSrcEnd ( ) + lenAdd ) ) )
return true ;
BF_ASSERT ( bfParser - > mParserData - > mRefCount = = - 1 ) ;
return false ;
}
void BfReducer : : MoveNode ( BfAstNode * srcNode , BfAstNode * newOwner )
{
# ifdef BF_AST_HAS_PARENT_MEMBER
srcNode - > mParent = newOwner ;
# endif
int srcStart = srcNode - > GetSrcStart ( ) ;
int srcEnd = srcNode - > GetSrcEnd ( ) ;
if ( srcStart < newOwner - > GetSrcStart ( ) )
newOwner - > SetSrcStart ( srcStart ) ;
if ( srcEnd > newOwner - > GetSrcEnd ( ) )
newOwner - > SetSrcEnd ( srcEnd ) ;
}
// Replaces prevNode with new node and adds prevNode to newNode's childrenj
// It can be considered that newNode encapsulated prevNode.
void BfReducer : : ReplaceNode ( BfAstNode * prevNode , BfAstNode * newNode )
{
# ifdef BF_AST_HAS_PARENT_MEMBER
newNode - > mParent = prevNode - > mParent ;
# endif
if ( ! newNode - > IsInitialized ( ) )
{
# ifdef BF_AST_COMPACT
if ( prevNode - > mIsCompact )
{
newNode - > mIsCompact = prevNode - > mIsCompact ;
newNode - > mCompact_SrcStart = prevNode - > mCompact_SrcStart ;
newNode - > mCompact_SrcLen = prevNode - > mCompact_SrcLen ;
newNode - > mCompact_TriviaLen = prevNode - > mCompact_TriviaLen ;
}
else
{
int prevTriviaStart ;
int prevSrcStart ;
int prevSrcEnd ;
prevNode - > GetSrcPositions ( prevTriviaStart , prevSrcStart , prevSrcEnd ) ;
newNode - > Init ( prevTriviaStart , prevSrcStart , prevSrcEnd ) ;
}
# else
newNode - > mTriviaStart = prevNode - > mTriviaStart ;
newNode - > mSrcStart = prevNode - > mSrcStart ;
newNode - > mSrcEnd = prevNode - > mSrcEnd ;
# endif
}
else
{
int newTriviaStart ;
int newSrcStart ;
int newSrcEnd ;
newNode - > GetSrcPositions ( newTriviaStart , newSrcStart , newSrcEnd ) ;
int prevTriviaStart ;
int prevSrcStart ;
int prevSrcEnd ;
prevNode - > GetSrcPositions ( prevTriviaStart , prevSrcStart , prevSrcEnd ) ;
if ( prevTriviaStart < newTriviaStart )
newNode - > SetTriviaStart ( prevTriviaStart ) ;
if ( prevSrcStart < newSrcStart )
newNode - > SetSrcStart ( prevSrcStart ) ;
if ( prevSrcEnd > newSrcEnd )
newNode - > SetSrcEnd ( prevSrcEnd ) ;
}
# ifdef BF_AST_HAS_PARENT_MEMBER
prevNode - > mParent = newNode ;
# endif
}
BfAstNode * BfReducer : : Fail ( const StringImpl & errorMsg , BfAstNode * refNode )
{
mStmtHasError = true ;
if ( mPassInstance - > HasLastFailedAt ( refNode ) ) // No duplicate failures
return NULL ;
mPassInstance - > Fail ( errorMsg , refNode ) ;
return NULL ;
}
BfAstNode * BfReducer : : FailAfter ( const StringImpl & errorMsg , BfAstNode * prevNode )
{
mStmtHasError = true ;
mPassInstance - > FailAfter ( errorMsg , prevNode ) ;
return NULL ;
}
void BfReducer : : AddErrorNode ( BfAstNode * astNode , bool removeNode )
{
if ( mSource ! = NULL )
mSource - > AddErrorNode ( astNode ) ;
if ( removeNode )
astNode - > RemoveSelf ( ) ;
}
bool BfReducer : : IsTypeReference ( BfAstNode * checkNode , BfToken successToken , int * outEndNode , bool * couldBeExpr , bool * isGenericType , bool * isTuple )
{
AssertCurrentNode ( checkNode ) ;
if ( couldBeExpr ! = NULL )
* couldBeExpr = true ;
if ( outEndNode ! = NULL )
* outEndNode = - 1 ;
auto firstNode = checkNode ;
if ( checkNode = = NULL )
return false ;
int checkIdx = mVisitorPos . mReadPos ;
if ( ( ! checkNode - > IsA < BfIdentifierNode > ( ) ) & & ( ! checkNode - > IsA < BfMemberReferenceExpression > ( ) ) )
{
if ( auto checkTokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) )
{
BfToken checkToken = checkTokenNode - > GetToken ( ) ;
if ( ( checkToken = = BfToken_Ref ) | | ( checkToken = = BfToken_Mut ) )
{
checkIdx + + ;
if ( mVisitorPos . Get ( checkIdx ) = = NULL )
return false ;
}
else if ( ( checkToken = = BfToken_Var ) | | ( checkToken = = BfToken_Let ) )
{
checkIdx + + ;
checkNode = mVisitorPos . Get ( checkIdx ) ;
checkTokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) ;
if ( outEndNode )
* outEndNode = checkIdx ;
if ( successToken = = BfToken_None )
return true ;
return ( checkToken = = successToken ) ;
}
else if ( checkToken = = BfToken_Unsigned )
{
// Unsigned val start
}
else if ( checkToken = = BfToken_LParen )
{
// Tuple start
}
else if ( checkToken = = BfToken_Decltype )
{
// Decltype start
}
else if ( ( checkToken = = BfToken_Delegate ) | | ( checkToken = = BfToken_Function ) )
{
int startNode = mVisitorPos . mReadPos ;
mVisitorPos . mReadPos + + ;
int endNode = - 1 ;
// Return type
auto checkNode = mVisitorPos . GetCurrent ( ) ;
if ( ( checkNode = = NULL ) | | ( ! IsTypeReference ( checkNode , BfToken_LParen , & endNode , couldBeExpr , isGenericType , isTuple ) ) )
{
if ( outEndNode ! = NULL )
* outEndNode = endNode ;
mVisitorPos . mReadPos = startNode ;
return false ;
}
// Take in params as a tuple
mVisitorPos . mReadPos = endNode ;
auto currentNode = mVisitorPos . GetCurrent ( ) ;
bool hasParams = false ;
if ( currentNode ! = NULL )
{
if ( auto openToken = BfNodeDynCast < BfTokenNode > ( currentNode ) )
{
if ( openToken - > GetToken ( ) = = BfToken_LParen )
{
int parenDepth = 1 ;
// Do a smarter check?
checkIdx = endNode + 1 ;
while ( true )
{
auto checkNode = mVisitorPos . Get ( checkIdx ) ;
if ( checkNode = = NULL )
break ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) )
{
bool done = false ;
switch ( tokenNode - > GetToken ( ) )
{
case BfToken_LParen :
parenDepth + + ;
break ;
case BfToken_RParen :
parenDepth - - ;
if ( parenDepth = = 0 )
{
endNode = checkIdx + 1 ;
done = true ;
}
break ;
case BfToken_Semicolon :
// Failed
done = true ;
break ;
2019-10-14 14:08:29 -07:00
default : break ;
2019-08-23 11:56:54 -07:00
}
if ( done )
break ;
}
checkIdx + + ;
}
hasParams = parenDepth = = 0 ;
}
}
}
if ( ! hasParams )
{
if ( outEndNode ! = NULL )
* outEndNode = endNode ;
mVisitorPos . mReadPos = startNode ;
return false ;
}
if ( outEndNode ! = NULL )
* outEndNode = endNode ;
mVisitorPos . mReadPos = startNode ;
return true ;
}
else
return false ;
}
else
return false ;
}
int chevronDepth = 0 ;
bool identifierExpected = true ;
bool hadEndBracket = false ;
int bracketDepth = 0 ;
int parenDepth = 0 ;
bool hadTupleComma = false ;
bool hadIdentifier = false ;
bool foundSuccessToken = false ;
BfTokenNode * lastToken = NULL ;
//while (checkNode != NULL)
SizedArray < BfToken , 8 > tokenStack ;
while ( true )
{
auto checkNode = mVisitorPos . Get ( checkIdx ) ;
if ( checkNode = = NULL )
break ;
auto checkTokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) ;
if ( checkTokenNode ! = NULL )
{
if ( hadEndBracket )
return false ;
BfToken checkToken = checkTokenNode - > GetToken ( ) ;
if ( bracketDepth > 0 )
{
if ( ( checkToken = = BfToken_LBracket ) | | ( checkToken = = BfToken_QuestionLBracket ) )
{
bracketDepth + + ;
}
else if ( checkToken = = BfToken_RBracket )
{
bracketDepth - - ;
}
}
else
{
if ( ( checkToken = = successToken ) & & ( checkTokenNode ! = firstNode ) )
{
bool doEnding = true ;
bool success = false ;
if ( ( lastToken ! = NULL ) & & ( ( lastToken - > GetToken ( ) = = BfToken_RChevron ) | | ( lastToken - > GetToken ( ) = = BfToken_RDblChevron ) ) )
{
if ( couldBeExpr ! = NULL )
* couldBeExpr = false ;
}
if ( successToken = = BfToken_RParen )
{
success = ( chevronDepth = = 0 ) & & ( bracketDepth = = 0 ) & & ( parenDepth = = 1 ) ;
if ( success )
{
// Check identifierExpected - this catches (.) casts
if ( ( identifierExpected ) & & ( couldBeExpr ! = NULL ) )
* couldBeExpr = false ;
}
}
else if ( ( successToken = = BfToken_Comma ) | |
( successToken = = BfToken_LBracket ) )
{
success = ( chevronDepth = = 0 ) & & ( bracketDepth = = 0 ) & & ( parenDepth = = 0 ) ;
}
if ( success )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return true ;
}
if ( doEnding )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return ( chevronDepth = = 0 ) & & ( bracketDepth = = 0 ) & & ( parenDepth = = 0 ) ;
}
}
bool isDone = false ;
if ( checkToken = = BfToken_LParen )
{
if ( ( hadIdentifier ) & & ( chevronDepth = = 0 ) & & ( bracketDepth = = 0 ) & & ( parenDepth = = 0 ) )
isDone = true ;
else
{
tokenStack . Add ( BfToken_LParen ) ;
parenDepth + + ;
}
}
else if ( checkToken = = BfToken_RParen )
{
if ( ( parenDepth = = 0 ) | | ( tokenStack . back ( ) ! = BfToken_LParen ) )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
tokenStack . pop_back ( ) ;
parenDepth - - ;
if ( parenDepth > 0 )
{
// if we are embedded in a multi-tuple like (A, (B, C), D) then we expect a , or ) after
// closing an inner tuple. Otherwise this is an expression like ((Type)a)
auto nextNode = mVisitorPos . GetNext ( ) ;
bool isOkay = false ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
isOkay = ( nextToken - > GetToken ( ) = = BfToken_Comma ) | | ( nextToken - > GetToken ( ) = = BfToken_RParen ) ;
}
if ( ! isOkay )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
}
if ( ( parenDepth < 0 ) | |
// Probably a cast
( ( successToken = = BfToken_None ) & & ( parenDepth = = 0 ) & & ( ! hadTupleComma ) ) )
{
if ( successToken = = BfToken_RParen )
{
foundSuccessToken = true ;
break ;
}
else
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
}
}
else if ( ( checkToken = = BfToken_Const ) & & ( chevronDepth > 0 ) )
{
if ( mCompatMode )
{
identifierExpected = true ;
}
else
{
int prevReadPos = mVisitorPos . mReadPos ;
auto nextNode = mVisitorPos . Get ( checkIdx + 1 ) ;
if ( nextNode ! = NULL )
{
mVisitorPos . mReadPos = checkIdx + 1 ;
auto expr = CreateExpression ( nextNode , BfReducer : : CreateExprFlags_BreakOnRChevron ) ;
int endExprReadPos = mVisitorPos . mReadPos ;
mVisitorPos . mReadPos = prevReadPos ;
if ( expr = = NULL )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
checkIdx = endExprReadPos ;
}
}
}
else if ( ( checkToken = = BfToken_Minus ) & & ( mCompatMode ) & & ( chevronDepth > 0 ) & & ( parenDepth = = 0 ) & & ( bracketDepth = = 0 ) )
{
// Allow
}
else if ( checkToken = = BfToken_Unsigned )
{
identifierExpected = true ;
}
else if ( ( checkToken = = BfToken_Ref ) | | ( checkToken = = BfToken_Mut ) )
{
identifierExpected = true ;
}
else if ( checkToken = = BfToken_LChevron )
{
identifierExpected = true ;
chevronDepth + + ;
tokenStack . Add ( BfToken_LChevron ) ;
}
else if ( ( checkToken = = BfToken_RChevron ) | | ( checkToken = = BfToken_RDblChevron ) )
{
for ( int i = 0 ; i < ( ( checkToken = = BfToken_RDblChevron ) ? 2 : 1 ) ; i + + )
{
if ( ( tokenStack . IsEmpty ( ) ) | | ( tokenStack . back ( ) ! = BfToken_LChevron ) )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
tokenStack . pop_back ( ) ;
chevronDepth - - ;
}
identifierExpected = false ;
if ( chevronDepth < 0 )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
if ( chevronDepth = = 0 )
{
if ( isGenericType ! = NULL )
* isGenericType = true ;
}
}
else if ( checkToken = = BfToken_RDblChevron )
chevronDepth - = 2 ;
else if ( checkToken = = BfToken_Comma )
{
if ( ( bracketDepth = = 0 ) & & ( tokenStack . IsEmpty ( ) ) )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
if ( ( ! tokenStack . IsEmpty ( ) ) & & ( tokenStack . back ( ) = = BfToken_LParen ) )
{
hadTupleComma = true ;
if ( isTuple ! = NULL )
{
* isTuple = true ;
}
}
identifierExpected = true ;
}
else if ( checkToken = = BfToken_Dot )
{
auto prevNode = mVisitorPos . Get ( checkIdx - 1 ) ;
if ( auto prevToken = BfNodeDynCast < BfTokenNode > ( prevNode ) )
{
if ( couldBeExpr ! = NULL )
{
// UH- NO, it could be referencing a static member
// a ">." can only be a reference to an inner type of a generic type
//if ((prevToken->GetToken() == BfToken_RChevron) || (prevToken->GetToken() == BfToken_RDblChevron))
//*couldBeExpr = false;
}
// a ".[" can only be a member reference after an indexer expression
if ( prevToken - > GetToken ( ) = = BfToken_RBracket )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
}
identifierExpected = true ;
}
else if ( checkToken = = BfToken_RBracket )
{
hadEndBracket = true ;
}
else if ( ( checkToken = = BfToken_Star ) | | ( checkToken = = BfToken_Question ) )
{
if ( checkToken = = BfToken_Star )
{
auto prevNode = mVisitorPos . Get ( checkIdx - 1 ) ;
if ( auto prevToken = BfNodeDynCast < BfTokenNode > ( prevNode ) )
{
switch ( prevToken - > GetToken ( ) )
{
case BfToken_RParen :
case BfToken_RBracket :
case BfToken_RChevron :
case BfToken_RDblChevron :
break ;
default :
// These are definitely dereferences
return false ;
}
}
while ( true )
{
auto nextNode = mVisitorPos . Get ( checkIdx + 1 ) ;
auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( nextToken = = NULL ) | | ( nextToken - > GetToken ( ) ! = BfToken_Star ) )
break ;
checkTokenNode = nextToken ;
checkToken = checkTokenNode - > GetToken ( ) ;
checkIdx + + ;
}
}
else
{
auto prevNode = mVisitorPos . Get ( checkIdx - 1 ) ;
if ( auto prevToken = BfNodeDynCast < BfTokenNode > ( prevNode ) )
{
// If this is just a 'loose' comma then it can't be part of a nullable
if ( ( prevToken - > GetToken ( ) = = BfToken_Comma ) | |
( prevToken - > GetToken ( ) = = BfToken_LParen ) )
{
return false ;
}
}
}
// Star or Question always end a TypeRef
if ( ( chevronDepth = = 0 ) & & ( parenDepth = = 0 ) & & ( bracketDepth = = 0 ) )
{
if ( hadTupleComma )
return false ;
if ( couldBeExpr ! = NULL )
* couldBeExpr = false ;
if ( outEndNode ! = NULL )
* outEndNode = checkIdx + 1 ;
if ( successToken = = BfToken_None )
return true ;
auto nextNode = mVisitorPos . Get ( checkIdx + 1 ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( nextToken - > GetToken ( ) = = successToken )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx + 1 ;
return true ;
}
if ( nextToken - > GetToken ( ) = = BfToken_LBracket )
{
// A rare case of something like "char*[...]", let the bracket information through
}
else
break ;
}
else
return false ;
}
}
else if ( ( checkToken = = BfToken_LBracket ) | | ( checkToken = = BfToken_QuestionLBracket ) )
{
auto prevNode = mVisitorPos . Get ( checkIdx - 1 ) ;
if ( auto prevToken = BfNodeDynCast < BfTokenNode > ( prevNode ) )
{
// .[ - that's not a valid type, but could be an attributed member reference
if ( ( prevToken - > GetToken ( ) = = BfToken_Dot ) | | ( prevToken - > GetToken ( ) = = BfToken_DotDot ) )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx - 1 ;
return false ;
}
}
bracketDepth + + ;
}
else if ( checkToken = = BfToken_This )
{
if ( ( parenDepth = = 1 ) & & ( hadIdentifier ) )
{
// If this looks like it's from a '(<type> this ...)' then it could be part of a function declaration, so allow it
}
else
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
}
else if ( ( checkToken = = BfToken_Delegate ) | | ( checkToken = = BfToken_Function ) )
{
int funcEndNode = - 1 ;
int prevReadPos = mVisitorPos . mReadPos ;
mVisitorPos . mReadPos = checkIdx ;
bool isTypeRef = IsTypeReference ( checkNode , BfToken_None , & funcEndNode ) ;
mVisitorPos . mReadPos = prevReadPos ;
if ( ! isTypeRef )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
checkIdx = funcEndNode ;
continue ;
}
else if ( checkToken = = BfToken_Decltype )
{
int endNodeIdx = checkIdx + 1 ;
auto nextNode = mVisitorPos . Get ( checkIdx + 1 ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
int openCount = 1 ;
while ( true )
{
endNodeIdx + + ;
auto checkNextNode = mVisitorPos . Get ( endNodeIdx ) ;
if ( checkNextNode = = NULL )
break ;
if ( auto checkNextToken = BfNodeDynCast < BfTokenNode > ( checkNextNode ) )
{
if ( checkNextToken - > GetToken ( ) = = BfToken_LParen )
openCount + + ;
else if ( checkNextToken - > GetToken ( ) = = BfToken_RParen )
{
openCount - - ;
if ( openCount = = 0 )
break ;
}
}
}
}
checkIdx = endNodeIdx ;
/*if (outEndNode != NULL)
* outEndNode = endNodeIdx + 1 ;
return true ; */
}
else if ( checkToken ! = BfToken_LBracket )
isDone = true ;
if ( isDone )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
if ( isGenericType ! = NULL )
* isGenericType = false ;
return false ;
}
}
}
else if ( bracketDepth > 0 )
{
// Ignore
}
else if ( ( checkNode - > IsA < BfIdentifierNode > ( ) ) | | ( checkNode - > IsA < BfMemberReferenceExpression > ( ) ) )
{
// Identifier is always allowed in tuple (parenDepth == 0), because it's potentially the field name
// (successToken == BfToken_RParen) infers we are already checking inside parentheses, such as
// when we see a potential cast expression
if ( ( ! identifierExpected ) & & ( parenDepth = = 0 ) & & ( successToken ! = BfToken_RParen ) )
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
if ( successToken = = BfToken_None )
return chevronDepth = = 0 ;
return false ;
}
hadIdentifier = true ;
identifierExpected = false ;
}
else if ( checkNode - > IsA < BfBlock > ( ) )
{
if ( successToken = = BfToken_LBrace )
{
foundSuccessToken = true ;
}
break ;
}
else if ( ( mCompatMode ) & & ( checkNode - > IsExact < BfLiteralExpression > ( ) ) & & ( chevronDepth > 0 ) & & ( identifierExpected ) )
{
// Allow
identifierExpected = false ;
}
else
{
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return false ;
}
lastToken = checkTokenNode ;
checkIdx + + ;
}
if ( outEndNode ! = NULL )
* outEndNode = checkIdx ;
return ( hadIdentifier ) & & ( chevronDepth = = 0 ) & & ( bracketDepth = = 0 ) & & ( parenDepth = = 0 ) & & ( ( successToken = = BfToken_None ) | | ( foundSuccessToken ) ) ;
}
bool BfReducer : : IsLocalMethod ( BfAstNode * nameNode )
{
AssertCurrentNode ( nameNode ) ;
int parenDepth = 0 ;
bool hadParens = false ;
int chevronDepth = 0 ;
bool hadGenericParams = false ;
int checkIdx = mVisitorPos . mReadPos + 1 ;
while ( true )
{
auto checkNode = mVisitorPos . Get ( checkIdx ) ;
if ( checkNode = = NULL )
return false ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) )
{
BfToken token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_LParen )
{
parenDepth + + ;
hadParens = true ;
}
else if ( token = = BfToken_RParen )
{
parenDepth - - ;
if ( parenDepth = = 0 )
return true ;
}
else
{
switch ( token )
{
case BfToken_Semicolon : // Never can be a local method
return false ;
case BfToken_Where : // Always denotes a local method
return true ;
2019-10-14 14:08:29 -07:00
default : break ;
2019-08-23 11:56:54 -07:00
}
}
}
else if ( auto tokenNode = BfNodeDynCast < BfBlock > ( checkNode ) )
{
//return (hadParens) && (parenDepth == 0);
return false ;
}
else
{
}
checkIdx + + ;
}
return false ;
}
int BfReducer : : QualifiedBacktrack ( BfAstNode * endNode , int checkIdx , bool * outHadChevrons )
{
auto checkNode = endNode ;
BF_ASSERT ( checkNode = = mVisitorPos . Get ( checkIdx ) ) ;
int chevronDepth = 0 ;
bool identifierExpected = true ;
bool hadEndBracket = false ;
bool lastWasIdentifier = false ;
while ( checkNode ! = NULL )
{
auto checkTokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) ;
if ( checkTokenNode ! = NULL )
{
BfToken checkToken = checkTokenNode - > GetToken ( ) ;
if ( ( checkToken = = BfToken_Dot ) | | ( checkToken = = BfToken_DotDot ) )
{
if ( chevronDepth = = 0 )
return checkIdx ;
}
else if ( checkToken = = BfToken_LChevron )
{
if ( outHadChevrons ! = NULL )
* outHadChevrons = true ;
chevronDepth + + ;
}
else if ( checkToken = = BfToken_RChevron )
{
// Was this a case like "Test<T> MethodName"? Those are split.
if ( lastWasIdentifier )
return - 1 ;
chevronDepth - - ;
}
else if ( checkToken = = BfToken_RDblChevron )
{
if ( lastWasIdentifier )
return - 1 ;
chevronDepth - = 2 ;
}
else if ( ( checkToken ! = BfToken_Comma ) & &
( checkToken ! = BfToken_Dot ) & &
( checkToken ! = BfToken_DotDot ) & &
( checkToken ! = BfToken_RBracket ) & &
( checkToken ! = BfToken_Star ) & &
( checkToken ! = BfToken_Question ) & &
( checkToken ! = BfToken_LBracket ) )
{
return - 1 ;
}
if ( chevronDepth = = 0 )
return - 1 ;
lastWasIdentifier = false ;
}
else if ( checkNode - > IsA < BfIdentifierNode > ( ) )
{
// Two identifiers in a row denotes a break
if ( lastWasIdentifier )
return - 1 ;
lastWasIdentifier = true ;
}
else
{
return - 1 ;
}
checkIdx - - ;
checkNode = mVisitorPos . Get ( checkIdx ) ;
}
return - 1 ;
}
BfExpression * BfReducer : : ApplyToFirstExpression ( BfUnaryOperatorExpression * unaryOp , BfExpression * target )
{
auto condExpression = BfNodeDynCast < BfConditionalExpression > ( target ) ;
if ( condExpression ! = NULL )
{
auto result = ApplyToFirstExpression ( unaryOp , condExpression - > mConditionExpression ) ;
if ( result = = condExpression - > mConditionExpression )
{
//TODO: Make sure this one works, check children and next's and such
//ReplaceNode(unaryOp, binOpExpression);
unaryOp - > mExpression = condExpression - > mConditionExpression ;
ReplaceNode ( unaryOp , condExpression ) ;
unaryOp - > SetSrcEnd ( condExpression - > mConditionExpression - > GetSrcEnd ( ) ) ;
condExpression - > mConditionExpression = unaryOp ;
}
condExpression - > SetSrcStart ( unaryOp - > GetSrcStart ( ) ) ;
return result ;
}
auto binOpExpression = BfNodeDynCast < BfBinaryOperatorExpression > ( target ) ;
if ( binOpExpression ! = NULL )
{
auto result = ApplyToFirstExpression ( unaryOp , binOpExpression - > mLeft ) ;
if ( result = = binOpExpression - > mLeft )
{
unaryOp - > mExpression = binOpExpression - > mLeft ;
unaryOp - > SetSrcEnd ( binOpExpression - > mLeft - > GetSrcEnd ( ) ) ;
binOpExpression - > mLeft = unaryOp ;
}
binOpExpression - > SetSrcStart ( unaryOp - > GetSrcStart ( ) ) ;
return result ;
}
return target ;
}
static String DbgNodeToString ( BfAstNode * astNode )
{
if ( auto binOpExpr = BfNodeDynCast < BfBinaryOperatorExpression > ( astNode ) )
{
String str ;
str + = " ( " ;
str + = DbgNodeToString ( binOpExpr - > mLeft ) ;
str + = " " ;
str + = DbgNodeToString ( binOpExpr - > mOpToken ) ;
str + = " " ;
str + = DbgNodeToString ( binOpExpr - > mRight ) ;
str + = " ) " ;
return str ;
}
else if ( auto condExpr = BfNodeDynCast < BfConditionalExpression > ( astNode ) )
{
String str ;
str + = " ( " ;
str + = DbgNodeToString ( condExpr - > mConditionExpression ) ;
str + = " ) ? ( " ;
str + = DbgNodeToString ( condExpr - > mTrueExpression ) ;
str + = " ) : ( " ;
str + = DbgNodeToString ( condExpr - > mFalseExpression ) ;
str + = " ) " ;
return str ;
}
return astNode - > ToString ( ) ;
}
BfExpression * BfReducer : : CheckBinaryOperatorPrecedence ( BfBinaryOperatorExpression * binOpExpression )
{
BfExpression * resultExpr = binOpExpression ;
bool dbg = false ;
# ifdef BF_AST_HAS_PARENT_MEMBER
BF_ASSERT ( BfNodeDynCast < BfBinaryOperatorExpression > ( binOpExpression - > mParent ) = = NULL ) ;
# endif
SizedArray < BfBinaryOperatorExpression * , 8 > binOpParents ;
SizedArray < BfBinaryOperatorExpression * , 8 > deferredChecks ;
BfBinaryOperatorExpression * checkBinOpExpression = binOpExpression ;
while ( true )
{
if ( checkBinOpExpression = = NULL )
{
if ( deferredChecks . size ( ) = = 0 )
break ;
checkBinOpExpression = deferredChecks . back ( ) ;
deferredChecks . pop_back ( ) ;
}
if ( dbg )
OutputDebugStrF ( " Checking: %s \n " , DbgNodeToString ( checkBinOpExpression ) . c_str ( ) ) ;
# ifdef BF_AST_HAS_PARENT_MEMBER
BfBinaryOperatorExpression * prevBinOpExpression = BfNodeDynCast < BfBinaryOperatorExpression > ( checkBinOpExpression - > mParent ) ;
if ( prevBinOpExpression ! = NULL )
{
BF_ASSERT ( binOpParents . back ( ) = = prevBinOpExpression ) ;
}
# else
BfBinaryOperatorExpression * prevBinOpExpression = NULL ;
# endif
if ( ! binOpParents . IsEmpty ( ) )
{
prevBinOpExpression = binOpParents . back ( ) ;
}
BfBinaryOperatorExpression * nextBinaryOperatorExpression = NULL ;
bool didCondSwap = false ;
while ( auto rightCondExpression = BfNodeDynCast < BfConditionalExpression > ( checkBinOpExpression - > mRight ) )
{
// Turn (A || (B ? C : D)) into ((A || B) ? C : D)
BfExpression * exprA = checkBinOpExpression - > mLeft ;
BfExpression * exprB = rightCondExpression - > mConditionExpression ;
BfExpression * exprC = rightCondExpression - > mTrueExpression ;
checkBinOpExpression - > SetSrcEnd ( exprB - > GetSrcEnd ( ) ) ;
MEMBER_SET ( rightCondExpression , mConditionExpression , checkBinOpExpression ) ;
MEMBER_SET ( checkBinOpExpression , mLeft , exprA ) ;
MEMBER_SET ( checkBinOpExpression , mRight , exprB ) ;
didCondSwap = true ;
if ( dbg )
{
OutputDebugStrF ( " NewCond: %s \n " , DbgNodeToString ( rightCondExpression ) . c_str ( ) ) ;
OutputDebugStrF ( " CheckAfterCond: %s \n " , DbgNodeToString ( checkBinOpExpression ) . c_str ( ) ) ;
}
if ( prevBinOpExpression ! = NULL )
{
BF_ASSERT ( checkBinOpExpression = = prevBinOpExpression - > mRight ) ;
MEMBER_SET ( prevBinOpExpression , mRight , rightCondExpression ) ;
nextBinaryOperatorExpression = prevBinOpExpression ;
binOpParents . pop_back ( ) ;
}
else
{
BF_ASSERT ( resultExpr = = checkBinOpExpression ) ;
resultExpr = rightCondExpression ;
}
}
if ( nextBinaryOperatorExpression ! = NULL )
{
checkBinOpExpression = nextBinaryOperatorExpression ;
continue ;
}
/*auto _CheckLeftBinaryOpearator = [&](BfBinaryOperatorExpression* checkBinOpExpression)
{
while ( auto leftBinOpExpression = BfNodeDynCast < BfBinaryOperatorExpression > ( checkBinOpExpression - > mLeft ) )
{
if ( dbg )
{
OutputDebugStrF ( " CheckCur : %s \n " , DbgNodeToString ( checkBinOpExpression ) . c_str ( ) ) ;
OutputDebugStrF ( " Left : %s \n " , DbgNodeToString ( leftBinOpExpression ) . c_str ( ) ) ;
}
if ( leftBinOpExpression - > mRight = = NULL )
{
BF_ASSERT ( mPassInstance - > HasFailed ( ) ) ;
return ;
}
int leftPrecedence = BfGetBinaryOpPrecendence ( leftBinOpExpression - > mOp ) ;
int rightPrecedence = BfGetBinaryOpPrecendence ( checkBinOpExpression - > mOp ) ;
// Turn ((A + B) * C) into (A + (B * C))
if ( leftPrecedence > = rightPrecedence )
{
break ;
}
BfTokenNode * tokenNode = checkBinOpExpression - > mOpToken ;
BfExpression * exprA = leftBinOpExpression - > mLeft ;
BfExpression * exprB = leftBinOpExpression - > mRight ;
BfExpression * exprC = checkBinOpExpression - > mRight ;
auto rightBinOpExpression = leftBinOpExpression ; // We reuse this memory for the right side now
auto binOp = checkBinOpExpression - > mOp ;
checkBinOpExpression - > mLeft = exprA ;
checkBinOpExpression - > mOp = leftBinOpExpression - > mOp ;
checkBinOpExpression - > mOpToken = leftBinOpExpression - > mOpToken ;
checkBinOpExpression - > mRight = rightBinOpExpression ;
rightBinOpExpression - > mLeft = exprB ;
rightBinOpExpression - > mOp = binOp ;
rightBinOpExpression - > mOpToken = tokenNode ;
rightBinOpExpression - > mRight = exprC ;
rightBinOpExpression - > SetSrcStart ( rightBinOpExpression - > mLeft - > GetSrcStart ( ) ) ;
rightBinOpExpression - > SetSrcEnd ( rightBinOpExpression - > mRight - > GetSrcEnd ( ) ) ;
if ( dbg )
{
OutputDebugStrF ( " CheckAfter : %s \n " , DbgNodeToString ( checkBinOpExpression ) . c_str ( ) ) ;
}
}
} ; */
while ( auto rightBinOpExpression = BfNodeDynCast < BfBinaryOperatorExpression > ( checkBinOpExpression - > mRight ) )
{
if ( dbg )
{
OutputDebugStrF ( " CheckCur : %s \n " , DbgNodeToString ( checkBinOpExpression ) . c_str ( ) ) ;
OutputDebugStrF ( " Right : %s \n " , DbgNodeToString ( rightBinOpExpression ) . c_str ( ) ) ;
}
if ( rightBinOpExpression - > mRight = = NULL )
{
BF_ASSERT ( mPassInstance - > HasFailed ( ) ) ;
return binOpExpression ;
}
int leftPrecedence = BfGetBinaryOpPrecendence ( checkBinOpExpression - > mOp ) ;
int rightPrecedence = BfGetBinaryOpPrecendence ( rightBinOpExpression - > mOp ) ;
// Turn (A * (B + C)) into ((A * B) + C)
// Note: this DOES need to be '<' in order to preserve left-to-right evaluation when precedence is equal
if ( leftPrecedence < rightPrecedence )
{
binOpParents . Add ( checkBinOpExpression ) ;
nextBinaryOperatorExpression = rightBinOpExpression ;
break ;
}
BfTokenNode * tokenNode = checkBinOpExpression - > mOpToken ;
BfExpression * exprA = checkBinOpExpression - > mLeft ;
BfExpression * exprB = rightBinOpExpression - > mLeft ;
BfExpression * exprC = rightBinOpExpression - > mRight ;
auto leftBinOpExpression = rightBinOpExpression ; // We reuse this memory for the left side now
auto binOp = checkBinOpExpression - > mOp ;
checkBinOpExpression - > mLeft = leftBinOpExpression ;
checkBinOpExpression - > mOp = rightBinOpExpression - > mOp ;
checkBinOpExpression - > mOpToken = rightBinOpExpression - > mOpToken ;
checkBinOpExpression - > mRight = exprC ;
leftBinOpExpression - > mLeft = exprA ;
leftBinOpExpression - > mOp = binOp ;
leftBinOpExpression - > mOpToken = tokenNode ;
leftBinOpExpression - > mRight = exprB ;
leftBinOpExpression - > SetSrcStart ( leftBinOpExpression - > mLeft - > GetSrcStart ( ) ) ;
leftBinOpExpression - > SetSrcEnd ( leftBinOpExpression - > mRight - > GetSrcEnd ( ) ) ;
if ( dbg )
{
OutputDebugStrF ( " CheckAfter: %s \n " , DbgNodeToString ( checkBinOpExpression ) . c_str ( ) ) ;
}
if ( ( leftPrecedence > rightPrecedence ) & & ( prevBinOpExpression ! = NULL ) )
{
// Backtrack
nextBinaryOperatorExpression = prevBinOpExpression ;
binOpParents . pop_back ( ) ;
break ;
}
if ( auto leftBinaryExpr = BfNodeDynCast < BfBinaryOperatorExpression > ( checkBinOpExpression - > mLeft ) )
{
deferredChecks . push_back ( leftBinaryExpr ) ;
}
}
checkBinOpExpression = nextBinaryOperatorExpression ;
}
if ( dbg )
OutputDebugStrF ( " NodeOut: %s \n " , DbgNodeToString ( resultExpr ) . c_str ( ) ) ;
return resultExpr ;
}
BfAstNode * BfReducer : : ReplaceTokenStarter ( BfAstNode * astNode , int idx )
{
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( astNode ) )
{
if ( ( tokenNode - > GetToken ( ) = = BfToken_As ) | |
( tokenNode - > GetToken ( ) = = BfToken_In ) )
{
if ( idx = = - 1 )
idx = mVisitorPos . mReadPos ;
BF_ASSERT ( mVisitorPos . Get ( idx ) = = astNode ) ;
auto identifierNode = mAlloc - > Alloc < BfIdentifierNode > ( ) ;
ReplaceNode ( tokenNode , identifierNode ) ;
mVisitorPos . Set ( idx , identifierNode ) ;
return identifierNode ;
}
}
return astNode ;
}
BfEnumCaseBindExpression * BfReducer : : CreateEnumCaseBindExpression ( BfTokenNode * bindToken )
{
auto bindExpr = mAlloc - > Alloc < BfEnumCaseBindExpression > ( ) ;
MEMBER_SET ( bindExpr , mBindToken , bindToken ) ;
mVisitorPos . MoveNext ( ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( nextToken - > GetToken ( ) = = BfToken_Dot )
{
auto memberReferenceExpr = mAlloc - > Alloc < BfMemberReferenceExpression > ( ) ;
MEMBER_SET ( memberReferenceExpr , mDotToken , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
auto memberName = ExpectIdentifierAfter ( memberReferenceExpr ) ;
if ( memberName ! = NULL )
{
MEMBER_SET ( memberReferenceExpr , mMemberName , memberName ) ;
}
MEMBER_SET ( bindExpr , mEnumMemberExpr , memberReferenceExpr ) ;
}
}
if ( bindExpr - > mEnumMemberExpr = = NULL )
{
auto typeRef = CreateTypeRefAfter ( bindExpr ) ;
if ( typeRef ! = NULL )
{
if ( auto namedTypeRef = BfNodeDynCast < BfNamedTypeReference > ( typeRef ) )
{
MEMBER_SET ( bindExpr , mEnumMemberExpr , namedTypeRef - > mNameNode ) ;
}
else
{
auto memberRefExpr = mAlloc - > Alloc < BfMemberReferenceExpression > ( ) ;
if ( auto qualifiedTypeRef = BfNodeDynCast < BfQualifiedTypeReference > ( typeRef ) )
{
if ( auto namedTypeRef = BfNodeDynCast < BfNamedTypeReference > ( qualifiedTypeRef - > mRight ) )
{
MEMBER_SET ( memberRefExpr , mTarget , qualifiedTypeRef - > mLeft ) ;
MEMBER_SET ( memberRefExpr , mDotToken , qualifiedTypeRef - > mDot ) ;
MEMBER_SET ( memberRefExpr , mMemberName , namedTypeRef - > mNameNode ) ;
}
}
else
{
MEMBER_SET ( memberRefExpr , mTarget , typeRef ) ;
}
MEMBER_SET ( bindExpr , mEnumMemberExpr , memberRefExpr ) ;
}
}
if ( bindExpr - > mEnumMemberExpr = = NULL )
{
Fail ( " Expected enum case name " , typeRef ) ;
}
}
if ( bindExpr - > mEnumMemberExpr ! = NULL )
{
auto openToken = ExpectTokenAfter ( bindExpr - > mEnumMemberExpr , BfToken_LParen ) ;
if ( openToken ! = NULL )
{
auto tupleExpr = CreateTupleExpression ( openToken , NULL ) ;
MEMBER_SET ( bindExpr , mBindNames , tupleExpr ) ;
}
}
return bindExpr ;
}
BfExpression * BfReducer : : CreateExpression ( BfAstNode * node , CreateExprFlags createExprFlags )
{
if ( node = = NULL )
return NULL ;
BP_ZONE ( " CreateExpression " ) ;
//
{
BP_ZONE ( " CreateExpression.CheckStack " ) ;
StackHelper stackHelper ;
if ( ! stackHelper . CanStackExpand ( 64 * 1024 ) )
{
BfExpression * result = NULL ;
if ( ! stackHelper . Execute ( [ & ] ( )
{
result = CreateExpression ( node , createExprFlags ) ;
} ) )
{
Fail ( " Expression too complex to parse " , node ) ;
}
return result ;
}
}
AssertCurrentNode ( node ) ;
/*if (auto block = BfNodeDynCast<BfBlock>(node))
{
HandleBlock ( block , true ) ;
return block ;
} */
auto rhsCreateExprFlags = ( CreateExprFlags ) ( createExprFlags & CreateExprFlags_BreakOnRChevron ) ;
node = ReplaceTokenStarter ( node ) ;
auto exprLeft = BfNodeDynCast < BfExpression > ( node ) ;
AssertCurrentNode ( node ) ;
if ( ( createExprFlags & ( CreateExprFlags_AllowVariableDecl | CreateExprFlags_PermissiveVariableDecl ) ) ! = 0 )
{
bool isLocalVariable = false ;
auto nextNode = mVisitorPos . GetNext ( ) ;
BfVariableDeclaration * continuingVariable = NULL ;
int outEndNode = - 1 ;
bool couldBeExpr = false ;
bool isTuple = false ;
if ( IsTypeReference ( node , BfToken_None , & outEndNode , & couldBeExpr , NULL , & isTuple ) )
{
if ( ( createExprFlags & CreateExprFlags_PermissiveVariableDecl ) ! = 0 )
isLocalVariable = true ;
else if ( auto identifierNode = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . Get ( outEndNode ) ) )
{
if ( auto equalsToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( outEndNode + 1 ) ) )
{
if ( equalsToken - > GetToken ( ) = = BfToken_AssignEquals )
isLocalVariable = true ;
}
//if (!couldBeExpr)
{
auto endingTokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( outEndNode - 1 ) ) ;
// If the type ends with a * or a ? then it could be an expression
if ( endingTokenNode = = NULL )
{
isLocalVariable = true ;
}
else
{
BfToken endingToken = endingTokenNode - > GetToken ( ) ;
if ( endingToken = = BfToken_RParen )
{
if ( isTuple )
isLocalVariable = true ;
}
else if ( endingToken = = BfToken_Star )
{
// Check spacing for "a* b" to determine if it's a pointer definition or a multiply
auto beforeStarNode = mVisitorPos . Get ( outEndNode - 2 ) ;
if ( ( endingTokenNode - > GetSrcStart ( ) = = beforeStarNode - > GetSrcEnd ( ) ) & &
( identifierNode - > GetSrcStart ( ) > endingTokenNode - > GetSrcEnd ( ) ) )
isLocalVariable = true ;
}
else if ( ( endingToken ! = BfToken_Star ) & & ( endingToken ! = BfToken_Question ) )
isLocalVariable = true ;
}
}
}
if ( auto typeNameToken = BfNodeDynCast < BfTokenNode > ( node ) )
{
if ( ( typeNameToken - > GetToken ( ) = = BfToken_Var ) | | ( typeNameToken - > GetToken ( ) = = BfToken_Let ) )
isLocalVariable = true ;
}
}
if ( nextNode = = NULL )
{
// Treat ending identifier as just an identifier (could be block result)
isLocalVariable = false ;
}
if ( ( isLocalVariable ) | | ( continuingVariable ! = NULL ) )
{
auto variableDeclaration = mAlloc - > Alloc < BfVariableDeclaration > ( ) ;
BfTypeReference * typeRef = NULL ;
if ( continuingVariable ! = NULL )
{
typeRef = continuingVariable - > mTypeRef ;
variableDeclaration - > mModSpecifier = continuingVariable - > mModSpecifier ;
ReplaceNode ( node , variableDeclaration ) ;
variableDeclaration - > mPrecedingComma = ( BfTokenNode * ) node ;
}
else
{
typeRef = CreateTypeRef ( node ) ;
if ( typeRef = = NULL )
return NULL ;
ReplaceNode ( typeRef , variableDeclaration ) ;
}
variableDeclaration - > mTypeRef = typeRef ;
BfAstNode * variableNameNode = NULL ;
nextNode = mVisitorPos . GetNext ( ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_LParen )
{
mVisitorPos . mReadPos + + ;
variableNameNode = CreateTupleExpression ( tokenNode ) ;
}
}
if ( variableNameNode = = NULL )
variableNameNode = ExpectIdentifierAfter ( variableDeclaration , " variable name " ) ;
if ( variableNameNode = = NULL )
return variableDeclaration ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) ;
variableDeclaration - > mNameNode = variableNameNode ;
MoveNode ( variableNameNode , variableDeclaration ) ;
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_AssignEquals ) )
{
MEMBER_SET ( variableDeclaration , mEqualsNode , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
if ( variableDeclaration - > mInitializer = = NULL )
variableDeclaration - > mInitializer = CreateExpressionAfter ( variableDeclaration ) ;
if ( variableDeclaration - > mInitializer = = NULL )
return variableDeclaration ;
MoveNode ( variableDeclaration - > mInitializer , variableDeclaration ) ;
}
exprLeft = variableDeclaration ;
}
}
if ( auto block = BfNodeDynCast < BfBlock > ( node ) )
{
HandleBlock ( block , true ) ;
exprLeft = block ;
}
if ( auto identifierNode = BfNodeDynCast < BfIdentifierNode > ( exprLeft ) )
{
identifierNode = CompactQualifiedName ( identifierNode ) ;
exprLeft = identifierNode ;
if ( ( mCompatMode ) & & ( exprLeft - > ToString ( ) = = " defined " ) )
{
auto definedNodeExpr = mAlloc - > Alloc < BfPreprocessorDefinedExpression > ( ) ;
ReplaceNode ( identifierNode , definedNodeExpr ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
bool hadParenToken = false ;
if ( auto parenToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( parenToken - > GetToken ( ) = = BfToken_LParen )
{
MoveNode ( parenToken , definedNodeExpr ) ;
hadParenToken = true ;
}
}
auto definedIdentifier = ExpectIdentifierAfter ( definedNodeExpr ) ;
MEMBER_SET_CHECKED ( definedNodeExpr , mIdentifier , definedIdentifier ) ;
if ( hadParenToken )
{
auto parenToken = ExpectTokenAfter ( definedNodeExpr , BfToken_RParen ) ;
if ( parenToken ! = NULL )
MoveNode ( parenToken , definedNodeExpr ) ;
}
exprLeft = definedNodeExpr ;
}
int endNodeIdx = - 1 ;
if ( ( IsTypeReference ( exprLeft , BfToken_LBracket , & endNodeIdx , NULL ) ) )
{
if ( IsTypeReference ( exprLeft , BfToken_LBrace , NULL , NULL ) )
{
BfSizedArrayCreateExpression * arrayCreateExpr = mAlloc - > Alloc < BfSizedArrayCreateExpression > ( ) ;
auto typeRef = CreateTypeRef ( exprLeft ) ;
if ( typeRef ! = NULL )
{
ReplaceNode ( typeRef , arrayCreateExpr ) ;
auto arrayType = BfNodeDynCast < BfArrayTypeRef > ( typeRef ) ;
if ( arrayType ! = NULL )
{
arrayCreateExpr - > mTypeRef = arrayType ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto block = BfNodeDynCast < BfBlock > ( nextNode ) ;
if ( block ! = NULL )
{
Fail ( " Brace initialization is not supported. Enclose initializer with parentheses. " , block ) ;
auto initializerExpr = CreateCollectionInitializerExpression ( block ) ;
MEMBER_SET ( arrayCreateExpr , mInitializer , initializerExpr ) ;
mVisitorPos . MoveNext ( ) ;
}
exprLeft = arrayCreateExpr ;
}
else
{
Fail ( " Sized array type expected " , typeRef ) ;
}
}
}
else if ( IsTypeReference ( exprLeft , BfToken_LParen , NULL , NULL ) )
{
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( endNodeIdx - 1 ) ) )
{
if ( ( tokenNode - > mToken = = BfToken_Star ) | | ( tokenNode - > mToken = = BfToken_Question ) ) // Is it something that can ONLY be a sized type reference?
{
BfSizedArrayCreateExpression * arrayCreateExpr = mAlloc - > Alloc < BfSizedArrayCreateExpression > ( ) ;
auto typeRef = CreateTypeRef ( exprLeft ) ;
if ( typeRef ! = NULL )
{
ReplaceNode ( typeRef , arrayCreateExpr ) ;
auto arrayType = BfNodeDynCast < BfArrayTypeRef > ( typeRef ) ;
if ( arrayType ! = NULL )
{
arrayCreateExpr - > mTypeRef = arrayType ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
mVisitorPos . MoveNext ( ) ;
auto initializerExpr = CreateCollectionInitializerExpression ( nextToken ) ;
MEMBER_SET ( arrayCreateExpr , mInitializer , initializerExpr ) ;
}
exprLeft = arrayCreateExpr ;
}
else
{
Fail ( " Sized array type expected " , typeRef ) ;
}
}
}
}
}
/*else if (IsTypeReference(exprLeft, BfToken_LParen, NULL, NULL))
{
BfSizedArrayCreateExpression * arrayCreateExpr = mAlloc - > Alloc < BfSizedArrayCreateExpression > ( ) ;
auto typeRef = CreateTypeRef ( exprLeft ) ;
if ( typeRef ! = NULL )
{
ReplaceNode ( typeRef , arrayCreateExpr ) ;
auto arrayType = BfNodeDynCast < BfArrayTypeRef > ( typeRef ) ;
if ( arrayType ! = NULL )
{
mVisitorPos . MoveNext ( ) ;
arrayCreateExpr - > mTypeRef = arrayType ;
auto nextNode = mVisitorPos . GetCurrent ( ) ;
auto openParen = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
BF_ASSERT ( openParen - > GetToken ( ) = = BfToken_LParen ) ;
auto initializerExpr = CreateCollectionInitializerExpression ( openParen ) ;
MEMBER_SET ( arrayCreateExpr , mInitializer , initializerExpr ) ;
exprLeft = arrayCreateExpr ;
}
else
{
Fail ( " Sized array type expected " , typeRef ) ;
}
}
} */
}
}
if ( exprLeft = = NULL )
{
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) )
{
BfToken token = tokenNode - > GetToken ( ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( ( nextNode ! = NULL ) & &
( ( token = = BfToken_Checked ) | |
( token = = BfToken_Unchecked ) ) )
{
mVisitorPos . MoveNext ( ) ;
auto nextExpr = CreateExpression ( nextNode ) ;
if ( nextExpr = = NULL )
return NULL ;
return nextExpr ;
}
else if ( ( token = = BfToken_New ) | |
( token = = BfToken_Scope ) | |
( token = = BfToken_Stack ) | |
( token = = BfToken_Append ) )
{
if ( token = = BfToken_Stack )
Fail ( " 'Stack' not supported. Use 'scope::' instead. " , tokenNode ) ;
auto allocNode = CreateAllocNode ( tokenNode ) ;
bool isDelegateBind = false ;
bool isLambdaBind = false ;
bool isBoxing = false ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto nextTokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
int nextToken = nextTokenNode - > GetToken ( ) ;
isBoxing = nextToken = = BfToken_Box ;
isDelegateBind = nextToken = = BfToken_FatArrow ;
isLambdaBind = ( nextToken = = BfToken_LBracket ) ;
// Either this is a lambda bind or a dynamic tuple allocation.
// We assume it's a lambda bind unless theres a "()" afterward
if ( nextToken = = BfToken_LParen )
{
int endNode = - 1 ;
mVisitorPos . mReadPos + + ;
if ( ! IsTypeReference ( nextTokenNode , BfToken_LParen , & endNode ) )
{
isLambdaBind = true ;
}
// if (IsTypeReference(nextToken, BfToken_FatArrow, &endNode))
// isLambdaBind = true;
mVisitorPos . mReadPos - - ;
}
}
if ( isBoxing )
{
auto boxExpr = mAlloc - > Alloc < BfBoxExpression > ( ) ;
ReplaceNode ( allocNode , boxExpr ) ;
boxExpr - > mAllocNode = allocNode ;
tokenNode = ExpectTokenAfter ( boxExpr , BfToken_Box ) ;
MEMBER_SET ( boxExpr , mBoxToken , tokenNode ) ;
auto exprNode = CreateExpressionAfter ( boxExpr ) ;
if ( exprNode ! = NULL )
{
MEMBER_SET ( boxExpr , mExpression , exprNode ) ;
}
return boxExpr ;
}
else if ( isLambdaBind )
exprLeft = CreateLambdaBindExpression ( allocNode ) ;
else if ( isDelegateBind )
exprLeft = CreateDelegateBindExpression ( allocNode ) ;
else
exprLeft = CreateObjectCreateExpression ( allocNode ) ;
if ( token = = BfToken_Append )
{
# ifdef BF_AST_HAS_PARENT_MEMBER
auto ctorDeclP = exprLeft - > FindParentOfType < BfConstructorDeclaration > ( ) ;
if ( ctorDeclP ! = NULL )
ctorDeclP - > mHasAppend = true ;
# endif
# ifdef BF_AST_HAS_PARENT_MEMBER
BF_ASSERT ( ctorDecl = = ctorDeclP ) ;
# endif
}
}
else if ( token = = BfToken_This )
{
auto thisExpr = mAlloc - > Alloc < BfThisExpression > ( ) ;
ReplaceNode ( tokenNode , thisExpr ) ;
thisExpr - > SetTriviaStart ( tokenNode - > GetTriviaStart ( ) ) ;
exprLeft = thisExpr ;
}
else if ( token = = BfToken_Base )
{
auto baseExpr = mAlloc - > Alloc < BfBaseExpression > ( ) ;
ReplaceNode ( tokenNode , baseExpr ) ;
baseExpr - > SetTriviaStart ( tokenNode - > GetTriviaStart ( ) ) ;
exprLeft = baseExpr ;
}
else if ( token = = BfToken_Null )
{
BfVariant nullVariant ;
nullVariant . mTypeCode = BfTypeCode_NullPtr ;
auto bfLiteralExpression = mAlloc - > Alloc < BfLiteralExpression > ( ) ;
bfLiteralExpression - > mValue = nullVariant ;
ReplaceNode ( tokenNode , bfLiteralExpression ) ;
bfLiteralExpression - > SetTriviaStart ( tokenNode - > GetTriviaStart ( ) ) ;
exprLeft = bfLiteralExpression ;
}
else if ( ( token = = BfToken_TypeOf ) | | ( token = = BfToken_SizeOf ) | |
( token = = BfToken_AlignOf ) | | ( token = = BfToken_StrideOf ) )
{
BfTypeAttrExpression * typeAttrExpr = NULL ;
switch ( tokenNode - > GetToken ( ) )
{
case BfToken_TypeOf :
typeAttrExpr = mAlloc - > Alloc < BfTypeOfExpression > ( ) ;
break ;
case BfToken_SizeOf :
typeAttrExpr = mAlloc - > Alloc < BfSizeOfExpression > ( ) ;
break ;
case BfToken_AlignOf :
typeAttrExpr = mAlloc - > Alloc < BfAlignOfExpression > ( ) ;
break ;
case BfToken_StrideOf :
typeAttrExpr = mAlloc - > Alloc < BfStrideOfExpression > ( ) ;
break ;
2019-10-14 14:08:29 -07:00
default : break ;
2019-08-23 11:56:54 -07:00
}
ReplaceNode ( tokenNode , typeAttrExpr ) ;
typeAttrExpr - > mToken = tokenNode ;
tokenNode = ExpectTokenAfter ( typeAttrExpr , BfToken_LParen ) ;
MEMBER_SET_CHECKED ( typeAttrExpr , mOpenParen , tokenNode ) ;
auto typeRef = CreateTypeRefAfter ( typeAttrExpr ) ;
MEMBER_SET_CHECKED ( typeAttrExpr , mTypeRef , typeRef ) ;
tokenNode = ExpectTokenAfter ( typeAttrExpr , BfToken_RParen ) ;
MEMBER_SET_CHECKED ( typeAttrExpr , mCloseParen , tokenNode ) ;
exprLeft = typeAttrExpr ;
}
else if ( token = = BfToken_Default )
{
auto defaultExpr = mAlloc - > Alloc < BfDefaultExpression > ( ) ;
ReplaceNode ( tokenNode , defaultExpr ) ;
defaultExpr - > mDefaultToken = tokenNode ;
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) ) & & ( tokenNode - > GetToken ( ) = = BfToken_LParen ) )
{
mVisitorPos . MoveNext ( ) ;
//tokenNode = ExpectTokenAfter(defaultExpr, BfToken_LParen);
MEMBER_SET_CHECKED ( defaultExpr , mOpenParen , tokenNode ) ;
auto sizeRef = CreateTypeRefAfter ( defaultExpr ) ;
MEMBER_SET_CHECKED ( defaultExpr , mTypeRef , sizeRef ) ;
tokenNode = ExpectTokenAfter ( defaultExpr , BfToken_RParen ) ;
MEMBER_SET_CHECKED ( defaultExpr , mCloseParen , tokenNode ) ;
}
exprLeft = defaultExpr ;
}
else if ( token = = BfToken_Question )
{
auto uninitExpr = mAlloc - > Alloc < BfUninitializedExpression > ( ) ;
ReplaceNode ( tokenNode , uninitExpr ) ;
uninitExpr - > mQuestionToken = tokenNode ;
return uninitExpr ;
//MEMBER_SET(variableDeclaration, mInitializer, uninitExpr);
}
else if ( token = = BfToken_Case )
{
auto caseExpr = mAlloc - > Alloc < BfCaseExpression > ( ) ;
ReplaceNode ( tokenNode , caseExpr ) ;
caseExpr - > mCaseToken = tokenNode ;
if ( auto bindToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( ( bindToken - > GetToken ( ) = = BfToken_Var ) | | ( bindToken - > GetToken ( ) = = BfToken_Let ) )
{
auto expr = CreateEnumCaseBindExpression ( bindToken ) ;
if ( expr = = NULL )
return caseExpr ;
MEMBER_SET ( caseExpr , mCaseExpression , expr ) ;
}
}
if ( caseExpr - > mCaseExpression = = NULL )
{
auto expr = CreateExpressionAfter ( caseExpr , ( CreateExprFlags ) ( CreateExprFlags_NoAssignment | CreateExprFlags_PermissiveVariableDecl ) ) ;
if ( expr = = NULL )
return caseExpr ;
MEMBER_SET ( caseExpr , mCaseExpression , expr ) ;
}
auto equalsNode = ExpectTokenAfter ( caseExpr , BfToken_AssignEquals ) ;
if ( equalsNode = = NULL )
return caseExpr ;
MEMBER_SET ( caseExpr , mEqualsNode , equalsNode ) ;
auto expr = CreateExpressionAfter ( caseExpr ) ;
if ( expr = = NULL )
return caseExpr ;
MEMBER_SET ( caseExpr , mValueExpression , expr ) ;
return caseExpr ;
}
else if ( token = = BfToken_Dot ) // Abbreviated dot syntax ".EnumVal"
{
auto memberReferenceExpr = mAlloc - > Alloc < BfMemberReferenceExpression > ( ) ;
ReplaceNode ( tokenNode , memberReferenceExpr ) ;
MEMBER_SET ( memberReferenceExpr , mDotToken , tokenNode ) ;
bool handled = false ;
if ( auto nextToken = BfNodeDynCastExact < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( nextToken - > GetToken ( ) = = BfToken_LParen )
{
// It's an unnamed dot ctor
handled = true ;
}
}
if ( ! handled )
{
auto memberName = ExpectIdentifierAfter ( memberReferenceExpr ) ;
if ( memberName ! = NULL )
{
MEMBER_SET ( memberReferenceExpr , mMemberName , memberName ) ;
}
}
// We don't set exprLeft here because it's illegal to do ".EnumVal.SomethingElse". That wouldn't make
// sense because the abbreviated syntax relies on type inference and the ".SomethingElse" wouldn't be
// the right type (whatever it is), AND mostly importantly, it breaks autocomplete when we are typing
// "KEnum val = ." above a line that starts with a something like a method call "OtherThing.MethodCall()"
// The exception is if we're creating an enum val with a payload
//auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
//if ((nextToken != NULL) && (nextToken->GetToken() == BfToken_LParen))
{
exprLeft = memberReferenceExpr ;
}
/*else
{
return memberReferenceExpr ;
} */
}
else if ( token = = BfToken_LBracket )
{
exprLeft = CreateAttributedExpression ( tokenNode , false ) ;
}
else if ( token = = BfToken_FatArrow )
{
auto delegateBindExpr = mAlloc - > Alloc < BfDelegateBindExpression > ( ) ;
ReplaceNode ( tokenNode , delegateBindExpr ) ;
MEMBER_SET_CHECKED ( delegateBindExpr , mFatArrowToken , tokenNode ) ;
auto expr = CreateExpressionAfter ( delegateBindExpr ) ;
MEMBER_SET_CHECKED ( delegateBindExpr , mTarget , expr ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_LChevron )
{
auto genericParamsDecl = CreateGenericArguments ( tokenNode ) ;
MEMBER_SET_CHECKED ( delegateBindExpr , mGenericArgs , genericParamsDecl ) ;
}
}
return delegateBindExpr ;
}
}
}
if ( exprLeft = = NULL )
{
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) )
{
BfUnaryOperatorExpression * unaryOpExpr = NULL ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( ( tokenNode - > GetToken ( ) = = BfToken_LParen ) & & ( nextNode ! = NULL ) )
{
bool couldBeExpr = true ;
// Peek ahead
int endNodeIdx = - 1 ;
BfAstNode * endNode = NULL ;
bool isTuple = false ;
bool outerIsTypeRef = IsTypeReference ( tokenNode , BfToken_FatArrow , & endNodeIdx , & couldBeExpr , NULL , & isTuple ) ;
if ( outerIsTypeRef )
{
if ( endNodeIdx ! = - 1 )
{
endNode = mVisitorPos . Get ( endNodeIdx ) ;
if ( auto endToken = BfNodeDynCast < BfTokenNode > ( endNode ) )
{
if ( endToken - > GetToken ( ) = = BfToken_FatArrow )
{
return CreateLambdaBindExpression ( NULL , tokenNode ) ;
}
}
}
}
//mVisitorPos.mReadPos++;
bool isCastExpr = false ;
couldBeExpr = false ;
isTuple = false ;
if ( ( createExprFlags & CreateExprFlags_NoCast ) = = 0 )
isCastExpr = IsTypeReference ( node , BfToken_RParen , & endNodeIdx , & couldBeExpr , NULL , & isTuple ) ;
//mVisitorPos.mReadPos--;
if ( endNodeIdx ! = - 1 )
endNode = mVisitorPos . Get ( endNodeIdx ) ;
//TODO: Remove this for compat
/*if (couldBeExpr)
isCastExpr = false ; */
if ( isCastExpr )
{
bool isValidTupleCast = false ;
auto tokenNextNode = mVisitorPos . Get ( mVisitorPos . mReadPos + 1 ) ;
if ( auto startToken = BfNodeDynCast < BfTokenNode > ( tokenNextNode ) )
{
if ( startToken - > GetToken ( ) = = BfToken_LParen )
{
if ( endNode ! = NULL )
{
auto afterEndNode = mVisitorPos . Get ( endNodeIdx + 1 ) ;
if ( auto afterEndToken = BfNodeDynCast < BfTokenNode > ( afterEndNode ) )
{
if ( afterEndToken - > GetToken ( ) = = BfToken_RParen )
{
isValidTupleCast = true ;
endNode = afterEndToken ; // Check this one now, instead...
}
}
}
if ( ! isValidTupleCast )
isCastExpr = false ;
}
}
BfAstNode * beforeEndNode = mVisitorPos . Get ( endNodeIdx - 1 ) ;
if ( auto prevTokenNode = BfNodeDynCast < BfTokenNode > ( beforeEndNode ) )
{
int prevToken = prevTokenNode - > GetToken ( ) ;
// Ending in a "*" or a ">" means it's definitely a type reference
if ( ( prevToken = = BfToken_Star ) | | ( prevToken = = BfToken_RChevron ) | | ( prevToken = = BfToken_RDblChevron ) )
couldBeExpr = false ;
}
// It's not a cast expression if a binary operator (like +) immediately follows
if ( couldBeExpr )
{
auto endNextNode = mVisitorPos . Get ( endNodeIdx + 1 ) ;
if ( endNextNode = = NULL )
{
isCastExpr = false ;
}
else if ( auto nextTokenNode = BfNodeDynCast < BfTokenNode > ( endNextNode ) )
{
BfToken nextToken = nextTokenNode - > GetToken ( ) ;
//TODO: Hm. What other tokens make it into a cast expr?
2019-11-17 09:28:39 -08:00
auto binaryOp = BfTokenToBinaryOp ( nextToken ) ;
2019-08-23 11:56:54 -07:00
// When we have a binary operator token following, it COULD either be a "(double)-val" or it COULD be a "(val2)-val"
// But we can't tell until we determine whether the thing inside the paren is a type name or a value name, so we
// have special code in BfExprEvaluator that can fix those cases at evaluation time
if ( ( ( binaryOp ! = BfBinaryOp_None ) /*&& (nextToken != BfToken_Star) && (nextToken != BfToken_Ampersand)*/ ) | | // Star could be dereference, not multiply
( nextToken = = BfToken_RParen ) | |
( nextToken = = BfToken_LBracket ) | |
( nextToken = = BfToken_Dot ) | |
( nextToken = = BfToken_DotDot ) | |
( nextToken = = BfToken_Comma ) | |
( nextToken = = BfToken_Colon ) | |
( nextToken = = BfToken_Question ) | |
( nextToken = = BfToken_Semicolon ) | |
( nextToken = = BfToken_AssignEquals ) | |
( nextToken = = BfToken_Case ) )
isCastExpr = false ;
}
}
}
if ( isCastExpr )
{
auto bfCastExpr = mAlloc - > Alloc < BfCastExpression > ( ) ;
if ( isTuple )
{
// Create typeRef including the parens (tuple type)
auto castTypeRef = CreateTypeRef ( tokenNode ) ;
ReplaceNode ( castTypeRef , bfCastExpr ) ;
bfCastExpr - > mTypeRef = castTypeRef ;
}
else
{
ReplaceNode ( tokenNode , bfCastExpr ) ;
bfCastExpr - > mOpenParen = tokenNode ;
auto castTypeRef = CreateTypeRefAfter ( bfCastExpr ) ;
MEMBER_SET_CHECKED ( bfCastExpr , mTypeRef , castTypeRef ) ;
tokenNode = ExpectTokenAfter ( bfCastExpr , BfToken_RParen ) ;
MEMBER_SET_CHECKED ( bfCastExpr , mCloseParen , tokenNode ) ;
}
auto expression = CreateExpressionAfter ( bfCastExpr ) ;
if ( expression = = NULL )
return bfCastExpr ;
MEMBER_SET ( bfCastExpr , mExpression , expression ) ;
unaryOpExpr = bfCastExpr ;
}
else
{
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
// Empty tuple?
if ( nextToken - > GetToken ( ) = = BfToken_RParen )
{
auto tupleExpr = mAlloc - > Alloc < BfTupleExpression > ( ) ;
ReplaceNode ( tokenNode , tupleExpr ) ;
tupleExpr - > mOpenParen = tokenNode ;
MEMBER_SET ( tupleExpr , mCloseParen , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
return tupleExpr ;
}
}
// static int sItrIdx = 0;
// sItrIdx++;
// int itrIdx = sItrIdx;
// if (itrIdx == 197)
// {
// NOP;
// }
// BfParenthesizedExpression or BfTupleExpression
SetAndRestoreValue < bool > prevInParenExpr ( mInParenExpr , true ) ;
auto innerExpr = CreateExpressionAfter ( tokenNode , CreateExprFlags_AllowVariableDecl ) ;
if ( innerExpr = = NULL )
return NULL ;
BfTokenNode * closeParenToken ;
if ( innerExpr - > IsA < BfIdentifierNode > ( ) )
closeParenToken = ExpectTokenAfter ( innerExpr , BfToken_RParen , BfToken_Comma , BfToken_Colon ) ;
else
closeParenToken = ExpectTokenAfter ( innerExpr , BfToken_RParen , BfToken_Comma ) ;
if ( ( closeParenToken = = NULL ) | | ( closeParenToken - > GetToken ( ) = = BfToken_RParen ) )
{
auto parenExpr = mAlloc - > Alloc < BfParenthesizedExpression > ( ) ;
parenExpr - > mExpression = innerExpr ;
ReplaceNode ( node , parenExpr ) ;
parenExpr - > mOpenParen = tokenNode ;
MoveNode ( innerExpr , parenExpr ) ;
if ( closeParenToken = = NULL )
return parenExpr ;
MEMBER_SET ( parenExpr , mCloseParen , closeParenToken ) ;
exprLeft = parenExpr ;
if ( ( createExprFlags & CreateExprFlags_ExitOnParenExpr ) ! = 0 )
return exprLeft ;
}
else
{
mVisitorPos . mReadPos - - ; // Backtrack to before token
exprLeft = CreateTupleExpression ( tokenNode , innerExpr ) ;
}
}
}
if ( exprLeft = = NULL )
{
2019-11-17 09:28:39 -08:00
BfUnaryOp unaryOp = BfTokenToUnaryOp ( tokenNode - > GetToken ( ) ) ;
2019-08-23 11:56:54 -07:00
if ( unaryOp ! = BfUnaryOp_None )
{
if ( unaryOp = = BfUnaryOp_Positive )
Fail ( " Unary operator '+' not allowed " , tokenNode ) ;
unaryOpExpr = mAlloc - > Alloc < BfUnaryOperatorExpression > ( ) ;
unaryOpExpr - > mOp = unaryOp ;
unaryOpExpr - > mOpToken = tokenNode ;
ReplaceNode ( tokenNode , unaryOpExpr ) ;
unaryOpExpr - > mExpression = CreateExpressionAfter ( unaryOpExpr , rhsCreateExprFlags ) ;
if ( unaryOpExpr - > mExpression = = NULL )
return NULL ;
MoveNode ( unaryOpExpr - > mExpression , unaryOpExpr ) ;
}
if ( unaryOpExpr ! = NULL )
{
exprLeft = unaryOpExpr ;
if ( auto binaryOpExpr = BfNodeDynCast < BfBinaryOperatorExpression > ( unaryOpExpr - > mExpression ) )
{
exprLeft = binaryOpExpr ;
ApplyToFirstExpression ( unaryOpExpr , binaryOpExpr ) ;
}
if ( auto condExpr = BfNodeDynCast < BfConditionalExpression > ( unaryOpExpr - > mExpression ) )
{
exprLeft = condExpr ;
ApplyToFirstExpression ( unaryOpExpr , condExpr ) ;
}
if ( auto assignmentExpr = BfNodeDynCast < BfAssignmentExpression > ( unaryOpExpr - > mExpression ) )
{
// Apply unary operator (likely a dereference) to LHS
assignmentExpr - > RemoveSelf ( ) ;
ReplaceNode ( unaryOpExpr , assignmentExpr ) ;
if ( assignmentExpr - > mLeft ! = NULL )
{
MEMBER_SET ( unaryOpExpr , mExpression , assignmentExpr - > mLeft ) ;
unaryOpExpr - > SetSrcEnd ( assignmentExpr - > mLeft - > GetSrcEnd ( ) ) ;
MEMBER_SET ( assignmentExpr , mLeft , unaryOpExpr ) ;
exprLeft = assignmentExpr ;
}
}
if ( auto dynCastExpr = BfNodeDynCast < BfDynamicCastExpression > ( unaryOpExpr - > mExpression ) )
{
// Apply unary operator (likely a dereference) to Expr
dynCastExpr - > RemoveSelf ( ) ;
ReplaceNode ( unaryOpExpr , dynCastExpr ) ;
if ( dynCastExpr - > mTarget ! = NULL )
{
MEMBER_SET ( unaryOpExpr , mExpression , dynCastExpr - > mTarget ) ;
unaryOpExpr - > SetSrcEnd ( dynCastExpr - > mTarget - > GetSrcEnd ( ) ) ;
MEMBER_SET ( dynCastExpr , mTarget , unaryOpExpr ) ;
exprLeft = dynCastExpr ;
}
}
if ( auto caseExpr = BfNodeDynCast < BfCaseExpression > ( unaryOpExpr - > mExpression ) )
{
// Apply unary operator (likely a dereference) to Expr
caseExpr - > RemoveSelf ( ) ;
ReplaceNode ( unaryOpExpr , caseExpr ) ;
if ( caseExpr - > mValueExpression ! = NULL )
{
MEMBER_SET ( unaryOpExpr , mExpression , caseExpr - > mValueExpression ) ;
unaryOpExpr - > SetSrcEnd ( caseExpr - > mValueExpression - > GetSrcEnd ( ) ) ;
MEMBER_SET ( caseExpr , mValueExpression , unaryOpExpr ) ;
exprLeft = caseExpr ;
}
}
}
}
}
}
if ( exprLeft = = NULL )
{
Fail ( " Expected expression " , node ) ;
return NULL ;
}
while ( true )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode = = NULL )
break ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
BfToken token = tokenNode - > GetToken ( ) ;
if ( ( ( createExprFlags & CreateExprFlags_BreakOnRChevron ) ! = 0 ) & & ( token = = BfToken_RChevron ) )
return exprLeft ;
if ( ( token = = BfToken_DblPlus ) | | ( token = = BfToken_DblMinus ) )
{
// Post-increment, post-decrement
auto unaryOpExpr = mAlloc - > Alloc < BfUnaryOperatorExpression > ( ) ;
ReplaceNode ( exprLeft , unaryOpExpr ) ;
unaryOpExpr - > mOp = ( token = = BfToken_DblPlus ) ? BfUnaryOp_PostIncrement : BfUnaryOp_PostDecrement ;
MEMBER_SET ( unaryOpExpr , mOpToken , tokenNode ) ;
MEMBER_SET ( unaryOpExpr , mExpression , exprLeft ) ;
exprLeft = unaryOpExpr ;
mVisitorPos . MoveNext ( ) ;
continue ;
}
if ( token = = BfToken_As )
{
auto dynCastExpr = mAlloc - > Alloc < BfDynamicCastExpression > ( ) ;
ReplaceNode ( exprLeft , dynCastExpr ) ;
dynCastExpr - > mTarget = exprLeft ;
MEMBER_SET ( dynCastExpr , mAsToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
auto typeRef = CreateTypeRefAfter ( dynCastExpr ) ;
if ( typeRef = = NULL )
return dynCastExpr ;
MEMBER_SET ( dynCastExpr , mTypeRef , typeRef ) ;
return dynCastExpr ;
}
if ( token = = BfToken_Is )
{
auto checkTypeExpr = mAlloc - > Alloc < BfCheckTypeExpression > ( ) ;
ReplaceNode ( exprLeft , checkTypeExpr ) ;
checkTypeExpr - > mTarget = exprLeft ;
MEMBER_SET ( checkTypeExpr , mIsToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
auto typeRef = CreateTypeRefAfter ( checkTypeExpr ) ;
if ( typeRef = = NULL )
return checkTypeExpr ;
MEMBER_SET ( checkTypeExpr , mTypeRef , typeRef ) ;
exprLeft = checkTypeExpr ;
continue ;
}
if ( token = = BfToken_Question )
{
auto conditionExpr = mAlloc - > Alloc < BfConditionalExpression > ( ) ;
ReplaceNode ( exprLeft , conditionExpr ) ;
conditionExpr - > mConditionExpression = exprLeft ;
MEMBER_SET ( conditionExpr , mQuestionToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
auto expr = CreateExpressionAfter ( conditionExpr ) ;
if ( expr ! = NULL )
{
MEMBER_SET ( conditionExpr , mTrueExpression , expr ) ;
tokenNode = ExpectTokenAfter ( conditionExpr , BfToken_Colon ) ;
if ( tokenNode ! = NULL )
{
MEMBER_SET ( conditionExpr , mColonToken , tokenNode ) ;
expr = CreateExpressionAfter ( conditionExpr ) ;
if ( expr ! = NULL )
{
MEMBER_SET ( conditionExpr , mFalseExpression , expr ) ;
}
}
}
exprLeft = conditionExpr ;
continue ;
}
if ( ( token = = BfToken_Case ) & & ( ( createExprFlags & CreateStmtFlags_NoCaseExpr ) = = 0 ) )
{
// If we have a ".Member case <XXX>" expression, that is an invalid construct. We bail out here
// because it allows the ".Member" to autocomplete because we will treat it as a full expression instead
// of making it the target of an illegal expression
if ( auto memberRefLeft = BfNodeDynCast < BfMemberReferenceExpression > ( exprLeft ) )
{
if ( memberRefLeft - > mTarget = = NULL )
return exprLeft ;
}
auto caseExpr = mAlloc - > Alloc < BfCaseExpression > ( ) ;
ReplaceNode ( exprLeft , caseExpr ) ;
caseExpr - > mValueExpression = exprLeft ;
MEMBER_SET ( caseExpr , mCaseToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
exprLeft = caseExpr ;
if ( auto bindTokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
BfToken bindToken = bindTokenNode - > GetToken ( ) ;
if ( ( bindToken = = BfToken_Var ) | | ( bindToken = = BfToken_Let ) )
{
auto expr = CreateEnumCaseBindExpression ( bindTokenNode ) ;
if ( expr = = NULL )
continue ;
MEMBER_SET ( caseExpr , mCaseExpression , expr ) ;
}
}
if ( caseExpr - > mCaseExpression = = NULL )
{
auto expr = CreateExpressionAfter ( caseExpr , ( CreateExprFlags ) ( CreateExprFlags_NoAssignment | CreateExprFlags_PermissiveVariableDecl ) ) ;
if ( expr = = NULL )
continue ;
MEMBER_SET ( caseExpr , mCaseExpression , expr ) ;
}
continue ;
}
if ( token = = BfToken_LChevron )
{
bool hadEndingToken = false ;
// If this is a complex member reference (IE: GType<int>.sVal) then condense in into a BfMemberReference.
// We need to be conservative about typeRef names, so GType<int>.A<T>.B.C.D, we can only assume "GType<int>.A<T>" is a typeref
// and the ".B.C.D" part is exposed as a MemberReference that may or may not include inner types
int outNodeIdx = - 1 ;
bool isGenericType = false ;
bool isTypeRef = ( ( IsTypeReference ( exprLeft , BfToken_None , & outNodeIdx , NULL , & isGenericType ) ) & &
( outNodeIdx ! = - 1 ) ) ;
BfAstNode * outNode = mVisitorPos . Get ( outNodeIdx ) ;
if ( ( ! isTypeRef ) & & ( outNodeIdx ! = - 1 ) )
{
if ( ( isGenericType ) & & ( outNode = = NULL ) )
{
for ( int checkOutNodeIdx = outNodeIdx + 1 ; true ; checkOutNodeIdx + + )
{
BfAstNode * checkNode = mVisitorPos . Get ( checkOutNodeIdx ) ;
if ( checkNode = = NULL )
break ;
outNode = checkNode ;
}
isTypeRef = true ;
}
else if ( auto outTokenNode = BfNodeDynCast < BfTokenNode > ( outNode ) )
{
BfToken outToken = outTokenNode - > GetToken ( ) ;
if ( ( outToken = = BfToken_Semicolon ) | | ( outToken = = BfToken_RParen ) | | ( outToken = = BfToken_Comma ) | |
( outToken = = BfToken_Let ) | | ( outToken = = BfToken_Var ) | | ( outToken = = BfToken_Const ) )
{
auto prevNode = mVisitorPos . Get ( outNodeIdx - 1 ) ;
if ( auto prevToken = BfNodeDynCast < BfTokenNode > ( prevNode ) )
{
// This handles such as "dlg = stack => obj.method<int>;"
if ( prevToken - > GetToken ( ) = = BfToken_RChevron )
hadEndingToken = true ;
}
}
//TODO: We had BfToken_Semicolon here, but it broke legitimate cases of "a.b.c < d.e.f;" expressions
//if ((outToken == BfToken_Semicolon) || (isGenericType) || (outToken == BfToken_LParen) || (outToken == BfToken_Var) || (outToken == BfToken_Const))
{
// Was just 'true'
int newOutNodeIdx = - 1 ;
bool newIsTypeRef = IsTypeReference ( exprLeft , outToken , & newOutNodeIdx , NULL , & isGenericType ) ;
BfAstNode * newOutNode = mVisitorPos . Get ( newOutNodeIdx ) ;
if ( ( newIsTypeRef ) & & ( newOutNode = = outNode ) & & ( isGenericType ) )
isTypeRef = true ;
}
}
}
if ( isTypeRef )
{
auto startIdentifier = exprLeft ;
int curNodeEndIdx = outNodeIdx - 1 ;
BfAstNode * curNodeEnd = mVisitorPos . Get ( curNodeEndIdx ) ;
bool isDotName = false ;
if ( auto qualifiedIdentifierNode = BfNodeDynCast < BfMemberReferenceExpression > ( startIdentifier ) )
{
// Don't try to convert dot-name to a qualified type
isDotName = qualifiedIdentifierNode - > mTarget = = NULL ;
}
bool didSplit = false ;
for ( int checkIdx = curNodeEndIdx ; checkIdx > = mVisitorPos . mReadPos ; checkIdx - - )
{
if ( isDotName )
break ;
auto checkNode = mVisitorPos . Get ( checkIdx ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) )
{
BfToken token = tokenNode - > GetToken ( ) ;
if ( ( token = = BfToken_RChevron ) | | ( token = = BfToken_RDblChevron ) )
{
auto nextCheckNode = mVisitorPos . Get ( checkIdx + 1 ) ;
if ( auto nextTokenNode = BfNodeDynCast < BfTokenNode > ( nextCheckNode ) )
{
if ( nextTokenNode - > GetToken ( ) = = BfToken_Dot )
{
auto nextNextCheckNode = mVisitorPos . Get ( checkIdx + 2 ) ;
if ( auto identifierNode = BfNodeDynCast < BfIdentifierNode > ( nextNextCheckNode ) )
{
// Remove dot temporarily so we create a typedef up to that dot
nextTokenNode - > SetToken ( BfToken_None ) ;
auto typeRef = CreateTypeRef ( startIdentifier ) ;
if ( typeRef = = NULL )
return NULL ;
nextTokenNode - > SetToken ( BfToken_Dot ) ;
auto memberRefExpr = mAlloc - > Alloc < BfMemberReferenceExpression > ( ) ;
ReplaceNode ( identifierNode , memberRefExpr ) ;
MEMBER_SET ( memberRefExpr , mDotToken , nextTokenNode ) ;
MEMBER_SET ( memberRefExpr , mTarget , typeRef ) ;
MEMBER_SET ( memberRefExpr , mMemberName , identifierNode ) ;
exprLeft = memberRefExpr ;
mVisitorPos . mReadPos = checkIdx + 2 ;
didSplit = true ;
break ;
}
else if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNextCheckNode ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_LBracket )
{
// Remove dot temporarily so we create a typedef up to that dot
nextTokenNode - > SetToken ( BfToken_None ) ;
auto typeRef = CreateTypeRef ( startIdentifier ) ;
if ( typeRef = = NULL )
return NULL ;
nextTokenNode - > SetToken ( BfToken_Dot ) ;
mVisitorPos . mReadPos = checkIdx + 0 ;
exprLeft = CreateMemberReferenceExpression ( typeRef ) ;
didSplit = true ;
}
}
}
else if ( nextTokenNode - > GetToken ( ) = = BfToken_LBracket )
{
int endNodeIdx = - 1 ;
if ( IsTypeReference ( startIdentifier , BfToken_LParen , & endNodeIdx ) )
{
if ( endNodeIdx > checkIdx + 1 )
{
auto typeRef = CreateTypeRef ( startIdentifier ) ;
auto arrayType = BfNodeDynCast < BfArrayTypeRef > ( typeRef ) ;
if ( arrayType = = NULL )
return NULL ;
mVisitorPos . mReadPos = checkIdx + 0 ;
auto arrayCreateExpr = mAlloc - > Alloc < BfSizedArrayCreateExpression > ( ) ;
ReplaceNode ( typeRef , arrayCreateExpr ) ;
arrayCreateExpr - > mTypeRef = arrayType ;
mVisitorPos . mReadPos = endNodeIdx ;
auto initializerExpr = CreateCollectionInitializerExpression ( BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetCurrent ( ) ) ) ;
MEMBER_SET ( arrayCreateExpr , mInitializer , initializerExpr ) ;
exprLeft = arrayCreateExpr ;
return arrayCreateExpr ;
}
}
}
}
}
}
}
if ( didSplit )
continue ;
}
// Could be a struct generic initializer, or a generic method invocation
if ( auto outToken = BfNodeDynCast < BfTokenNode > ( outNode ) )
{
int endNodeIdx = - 1 ;
if ( ( outToken - > GetToken ( ) = = BfToken_LParen ) & & ( IsTypeReference ( exprLeft , BfToken_LParen , & endNodeIdx ) ) )
{
exprLeft = CreateInvocationExpression ( exprLeft ) ;
if ( exprLeft = = NULL )
return NULL ;
continue ;
}
}
if ( hadEndingToken )
return exprLeft ;
}
if ( token = = BfToken_Star )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( ( nextToken - > mToken = = BfToken_Star ) | | ( nextToken - > mToken = = BfToken_LBracket ) )
{
//if (IsTypeReference(tokenNode, BfToken_LBracket))
{
/*auto typeRef = CreateTypeRef(tokenNode, true);
exprLeft = CreateObjectCreateExpression ( typeRef ) ;
return exprLeft ; */
}
}
}
}
2019-11-17 09:28:39 -08:00
BfBinaryOp binOp = BfTokenToBinaryOp ( tokenNode - > GetToken ( ) ) ;
2019-08-23 11:56:54 -07:00
if ( binOp ! = BfBinaryOp_None )
{
auto binOpExpression = mAlloc - > Alloc < BfBinaryOperatorExpression > ( ) ;
ReplaceNode ( exprLeft , binOpExpression ) ;
binOpExpression - > mLeft = exprLeft ;
binOpExpression - > mOp = binOp ;
MEMBER_SET ( binOpExpression , mOpToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
// We only need to check binary operator precedence at the "top level" binary operator
rhsCreateExprFlags = ( CreateExprFlags ) ( rhsCreateExprFlags | CreateExprFlags_NoCheckBinOpPrecedence ) ;
auto exprRight = CreateExpressionAfter ( binOpExpression , rhsCreateExprFlags ) ;
if ( exprRight = = NULL )
return binOpExpression ;
MEMBER_SET ( binOpExpression , mRight , exprRight ) ;
if ( ( createExprFlags & CreateExprFlags_NoCheckBinOpPrecedence ) ! = 0 )
return binOpExpression ;
return CheckBinaryOperatorPrecedence ( binOpExpression ) ;
}
2019-11-17 09:28:39 -08:00
auto assignmentOp = BfTokenToAssignmentOp ( tokenNode - > GetToken ( ) ) ;
2019-08-23 11:56:54 -07:00
if ( assignmentOp ! = BfAssignmentOp_None )
{
if ( ( createExprFlags & CreateExprFlags_NoAssignment ) ! = 0 )
return exprLeft ;
auto assignmentExpression = mAlloc - > Alloc < BfAssignmentExpression > ( ) ;
ReplaceNode ( exprLeft , assignmentExpression ) ;
mVisitorPos . MoveNext ( ) ;
assignmentExpression - > mOp = assignmentOp ;
assignmentExpression - > mLeft = exprLeft ;
assignmentExpression - > mOpToken = tokenNode ;
MoveNode ( assignmentExpression - > mOpToken , assignmentExpression ) ;
bool continueCascade = false ;
if ( auto memberExpr = BfNodeDynCast < BfMemberReferenceExpression > ( exprLeft ) )
{
if ( memberExpr - > mDotToken - > GetToken ( ) = = BfToken_DotDot )
continueCascade = true ;
}
CreateExprFlags flags = rhsCreateExprFlags ;
if ( continueCascade )
flags = ( CreateExprFlags ) ( rhsCreateExprFlags | CreateExprFlags_BreakOnCascade ) ;
auto exprRight = CreateExpressionAfter ( assignmentExpression , flags ) ;
if ( exprRight = = NULL )
{
FailAfter ( " Invalid expression " , assignmentExpression ) ;
return assignmentExpression ;
}
assignmentExpression - > mRight = exprRight ;
MoveNode ( assignmentExpression - > mRight , assignmentExpression ) ;
if ( continueCascade )
{
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( nextToken - > GetToken ( ) = = BfToken_DotDot )
{
exprLeft = assignmentExpression ;
continue ;
}
}
}
return assignmentExpression ;
}
BF_ASSERT ( tokenNode - > GetToken ( ) = = token ) ;
// Not a binary op, it's a 'close'
if ( token = = BfToken_Bang )
{
if ( ( createExprFlags & CreateExprFlags_ExitOnBang ) ! = 0 )
return exprLeft ;
exprLeft = CreateInvocationExpression ( exprLeft ) ;
}
else if ( token = = BfToken_LParen )
{
exprLeft = CreateInvocationExpression ( exprLeft , ( CreateExprFlags ) ( createExprFlags & ~ ( CreateExprFlags_NoCast ) ) ) ;
}
else if ( ( token = = BfToken_LBracket ) | | ( token = = BfToken_QuestionLBracket ) )
{
exprLeft = CreateIndexerExpression ( exprLeft ) ;
}
else if ( ( token = = BfToken_Dot ) | | ( token = = BfToken_DotDot ) | | ( token = = BfToken_QuestionDot ) )
{
if ( ( token = = BfToken_DotDot ) & & ( ( createExprFlags & CreateExprFlags_BreakOnCascade ) ! = 0 ) )
return exprLeft ;
if ( auto memberExpr = BfNodeDynCastExact < BfMemberReferenceExpression > ( exprLeft ) )
{
if ( memberExpr - > mTarget = = NULL )
{
// A dot syntax like ".A.B" is never valid - to help with autocomplete we stop the expr parsing here
Fail ( " Unexpected '.' token " , tokenNode ) ;
return exprLeft ;
}
}
exprLeft = CreateMemberReferenceExpression ( exprLeft ) ;
}
else
{
return exprLeft ;
}
if ( exprLeft = = NULL )
return NULL ;
}
else
break ;
}
return exprLeft ;
}
BfExpression * BfReducer : : CreateExpressionAfter ( BfAstNode * node , CreateExprFlags createExprFlags )
{
AssertCurrentNode ( node ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
bool isEmpty = false ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_RParen )
isEmpty = true ;
}
if ( ( nextNode = = NULL ) | | ( isEmpty ) )
{
FailAfter ( " Expression expected " , node ) ;
return NULL ;
}
int startReadPos = mVisitorPos . mReadPos ;
mVisitorPos . MoveNext ( ) ;
auto result = CreateExpression ( nextNode , createExprFlags ) ;
if ( result = = NULL )
{
// Nope, didn't handle it
mVisitorPos . mReadPos = startReadPos ;
}
return result ;
}
BfForEachStatement * BfReducer : : CreateForEachStatement ( BfAstNode * node , bool hasTypeDecl )
{
auto forToken = BfNodeDynCast < BfTokenNode > ( node ) ;
auto parenToken = ExpectTokenAfter ( forToken , BfToken_LParen ) ;
if ( parenToken = = NULL )
return NULL ;
auto forEachStatement = mAlloc - > Alloc < BfForEachStatement > ( ) ;
ReplaceNode ( forToken , forEachStatement ) ;
MEMBER_SET ( forEachStatement , mForToken , forToken ) ;
MEMBER_SET ( forEachStatement , mOpenParen , parenToken ) ;
if ( hasTypeDecl )
{
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( tokenNode - > mToken = = BfToken_ReadOnly )
{
MEMBER_SET_CHECKED ( forEachStatement , mReadOnlyToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
}
}
auto typeRef = CreateTypeRefAfter ( forEachStatement ) ;
if ( typeRef = = NULL )
return forEachStatement ;
MEMBER_SET_CHECKED ( forEachStatement , mVariableTypeRef , typeRef ) ;
}
if ( auto nextNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
2019-10-05 11:27:30 -07:00
if ( ( nextNode - > mToken = = BfToken_LParen ) | | ( nextNode - > mToken = = BfToken_LessEquals ) )
2019-08-23 11:56:54 -07:00
{
mVisitorPos . MoveNext ( ) ;
auto tupleNode = CreateTupleExpression ( nextNode ) ;
MEMBER_SET_CHECKED ( forEachStatement , mVariableName , tupleNode ) ;
}
}
if ( forEachStatement - > mVariableName = = NULL )
{
auto name = ExpectIdentifierAfter ( forEachStatement , " variable name " ) ;
MEMBER_SET_CHECKED ( forEachStatement , mVariableName , name ) ;
}
2019-10-05 11:27:30 -07:00
auto inToken = ExpectTokenAfter ( forEachStatement , BfToken_In , BfToken_LChevron , BfToken_LessEquals ) ;
2019-08-23 11:56:54 -07:00
MEMBER_SET_CHECKED ( forEachStatement , mInToken , inToken ) ;
auto expr = CreateExpressionAfter ( forEachStatement ) ;
MEMBER_SET_CHECKED ( forEachStatement , mCollectionExpression , expr ) ;
parenToken = ExpectTokenAfter ( forEachStatement , BfToken_RParen ) ;
MEMBER_SET_CHECKED ( forEachStatement , mCloseParen , parenToken ) ;
auto stmt = CreateStatementAfter ( forEachStatement , CreateStmtFlags_FindTrailingSemicolon ) ;
if ( stmt = = NULL )
return forEachStatement ;
MEMBER_SET ( forEachStatement , mEmbeddedStatement , stmt ) ;
return forEachStatement ;
}
BfStatement * BfReducer : : CreateForStatement ( BfAstNode * node )
{
int startReadIdx = mVisitorPos . mReadPos ;
auto forToken = BfNodeDynCast < BfTokenNode > ( node ) ;
auto parenToken = ExpectTokenAfter ( forToken , BfToken_LParen ) ;
if ( parenToken = = NULL )
return NULL ;
int outNodeIdx = - 1 ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
// Handle 'for (let (key, value) in dict)'
if ( ( tokenNode - > mToken = = BfToken_Let ) | | ( tokenNode - > mToken = = BfToken_Var ) )
{
if ( auto afterLet = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( mVisitorPos . mReadPos + 2 ) ) )
{
if ( afterLet - > mToken = = BfToken_LParen )
{
bool isTupleIn = true ;
int parenDepth = 1 ;
for ( int readPos = mVisitorPos . mReadPos + 3 ; true ; readPos + + )
{
auto checkNode = mVisitorPos . Get ( readPos ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) )
{
if ( tokenNode - > mToken = = BfToken_RParen )
{
if ( parenDepth ! = 1 )
{
isTupleIn = false ;
break ;
}
parenDepth - - ;
}
else if ( tokenNode - > mToken = = BfToken_In )
{
if ( parenDepth ! = 0 )
isTupleIn = false ;
break ;
}
else if ( tokenNode - > mToken = = BfToken_Comma )
{
//
}
else
{
isTupleIn = false ;
break ;
}
}
else if ( auto identifierNode = BfNodeDynCast < BfIdentifierNode > ( checkNode ) )
{
//
}
else
{
isTupleIn = false ;
break ;
}
}
if ( isTupleIn )
{
mVisitorPos . mReadPos = startReadIdx ;
return CreateForEachStatement ( node , true ) ;
}
}
}
}
}
bool isTypeRef = false ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( nextNode - > mToken = = BfToken_ReadOnly )
{
mVisitorPos . mReadPos + = 2 ;
isTypeRef = IsTypeReference ( mVisitorPos . Get ( mVisitorPos . mReadPos ) , BfToken_None , & outNodeIdx ) ;
mVisitorPos . mReadPos - = 2 ;
}
}
if ( ! isTypeRef )
{
mVisitorPos . mReadPos + + ;
isTypeRef = IsTypeReference ( nextNode , BfToken_None , & outNodeIdx ) ;
mVisitorPos . mReadPos - - ;
}
BfAstNode * outNode = mVisitorPos . Get ( outNodeIdx ) ;
if ( isTypeRef )
{
auto nextNode = mVisitorPos . Get ( outNodeIdx + 1 ) ;
if ( ( outNode ! = NULL ) & & ( nextNode ! = NULL ) )
{
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode ! = NULL )
{
int token = tokenNode - > GetToken ( ) ;
2019-10-05 11:27:30 -07:00
if ( ( token = = BfToken_In ) | | ( token = = BfToken_LChevron ) | | ( token = = BfToken_LessEquals ) )
2019-08-23 11:56:54 -07:00
{
mVisitorPos . mReadPos = startReadIdx ;
return CreateForEachStatement ( node , true ) ;
}
}
}
}
else
{
int checkNodeIdx = ( outNodeIdx ! = - 1 ) ? outNodeIdx : mVisitorPos . mReadPos + 1 ;
auto checkNode = mVisitorPos . Get ( checkNodeIdx ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) )
{
BfToken token = tokenNode - > GetToken ( ) ;
// Is this an 'anonymous' foreach?
if ( ( token ! = BfToken_Semicolon ) & & ( token ! = BfToken_LChevron ) & &
( token ! = BfToken_In ) & & ( token ! = BfToken_AssignEquals ) )
{
mVisitorPos . mReadPos = startReadIdx ;
auto forToken = BfNodeDynCast < BfTokenNode > ( node ) ;
auto parenToken = ExpectTokenAfter ( forToken , BfToken_LParen ) ;
if ( parenToken = = NULL )
return NULL ;
auto forEachStatement = mAlloc - > Alloc < BfForEachStatement > ( ) ;
ReplaceNode ( forToken , forEachStatement ) ;
MEMBER_SET ( forEachStatement , mForToken , forToken ) ;
MEMBER_SET ( forEachStatement , mOpenParen , parenToken ) ;
auto expr = CreateExpressionAfter ( forEachStatement ) ;
MEMBER_SET_CHECKED ( forEachStatement , mCollectionExpression , expr ) ;
parenToken = ExpectTokenAfter ( forEachStatement , BfToken_RParen ) ;
MEMBER_SET_CHECKED ( forEachStatement , mCloseParen , parenToken ) ;
auto stmt = CreateStatementAfter ( forEachStatement , CreateStmtFlags_FindTrailingSemicolon ) ;
if ( stmt = = NULL )
return forEachStatement ;
MEMBER_SET ( forEachStatement , mEmbeddedStatement , stmt ) ;
return forEachStatement ;
}
}
}
auto nextNextNode = mVisitorPos . Get ( mVisitorPos . mReadPos + 2 ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNextNode ) )
{
if ( ( tokenNode ! = NULL ) & & ( ( tokenNode - > GetToken ( ) = = BfToken_LChevron ) | | ( tokenNode - > GetToken ( ) = = BfToken_In ) ) )
{
Fail ( " Ranged for statement must declare new value variable, consider adding a type name, 'var', or 'let' " , tokenNode ) ;
mVisitorPos . mReadPos = startReadIdx ;
return CreateForEachStatement ( node , false ) ;
}
}
BfAstNode * stmt ;
auto forStatement = mAlloc - > Alloc < BfForStatement > ( ) ;
BfDeferredAstSizedArray < BfAstNode * > initializers ( forStatement - > mInitializers , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > initializerCommas ( forStatement - > mInitializerCommas , mAlloc ) ;
BfDeferredAstSizedArray < BfAstNode * > iterators ( forStatement - > mIterators , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > iteratorCommas ( forStatement - > mIteratorCommas , mAlloc ) ;
ReplaceNode ( forToken , forStatement ) ;
MEMBER_SET ( forStatement , mForToken , forToken ) ;
MEMBER_SET ( forStatement , mOpenParen , parenToken ) ;
// Initializers
for ( int listIdx = 0 ; true ; listIdx + + )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( ( listIdx > 0 ) | | ( ! IsSemicolon ( nextNode ) ) )
{
auto stmt = CreateStatementAfter ( forStatement ) ;
if ( stmt = = NULL )
return forStatement ;
initializers . push_back ( stmt ) ;
MoveNode ( stmt , forStatement ) ;
}
nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode = = NULL )
return forStatement ;
if ( tokenNode - > GetToken ( ) = = BfToken_Semicolon )
{
MEMBER_SET ( forStatement , mInitializerSemicolon , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
break ;
}
else if ( tokenNode - > GetToken ( ) = = BfToken_Comma )
{
MoveNode ( tokenNode , forStatement ) ;
initializerCommas . push_back ( tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
}
else
{
Fail ( " Expected ',' or ';' " , tokenNode ) ;
return forStatement ;
}
}
// Condition
nextNode = mVisitorPos . GetNext ( ) ;
if ( ! IsSemicolon ( nextNode ) )
{
bool doExpr = true ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_RParen )
{
Fail ( " Expected expression or ';' " , tokenNode ) ;
doExpr = false ;
}
}
if ( doExpr )
{
auto expr = CreateExpressionAfter ( forStatement ) ;
if ( expr = = NULL )
return forStatement ;
MEMBER_SET ( forStatement , mCondition , expr ) ;
}
}
auto tokenNode = ExpectTokenAfter ( forStatement , BfToken_Semicolon ) ;
if ( tokenNode = = NULL )
return forStatement ;
MEMBER_SET ( forStatement , mConditionSemicolon , tokenNode ) ;
// Iterators
for ( int listIdx = 0 ; true ; listIdx + + )
{
if ( listIdx = = 0 )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_RParen )
{
MEMBER_SET ( forStatement , mCloseParen , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
break ;
}
}
}
auto stmt = CreateStatementAfter ( forStatement ) ;
if ( stmt = = NULL )
return forStatement ;
iterators . push_back ( stmt ) ;
MoveNode ( stmt , forStatement ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode = = NULL )
return forStatement ;
if ( tokenNode - > GetToken ( ) = = BfToken_RParen )
{
MEMBER_SET ( forStatement , mCloseParen , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
break ;
}
else if ( tokenNode - > GetToken ( ) = = BfToken_Comma )
{
MoveNode ( tokenNode , forStatement ) ;
iteratorCommas . push_back ( tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
}
else
{
Fail ( " Expected ',' or ')' " , tokenNode ) ;
return forStatement ;
}
}
stmt = CreateStatementAfter ( forStatement , CreateStmtFlags_FindTrailingSemicolon ) ;
if ( stmt = = NULL )
return forStatement ;
MEMBER_SET ( forStatement , mEmbeddedStatement , stmt ) ;
return forStatement ;
}
BfUsingStatement * BfReducer : : CreateUsingStatement ( BfAstNode * node )
{
auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) ;
auto usingStatement = mAlloc - > Alloc < BfUsingStatement > ( ) ;
ReplaceNode ( tokenNode , usingStatement ) ;
MEMBER_SET ( usingStatement , mUsingToken , tokenNode ) ;
tokenNode = ExpectTokenAfter ( usingStatement , BfToken_LParen ) ;
if ( tokenNode = = NULL )
return NULL ;
MEMBER_SET ( usingStatement , mOpenParen , tokenNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode ! = NULL )
{
BfVariableDeclaration * varDecl = mAlloc - > Alloc < BfVariableDeclaration > ( ) ;
int outNodeIdx = - 1 ;
auto nextNode = mVisitorPos . GetNext ( ) ;
mVisitorPos . mReadPos + + ;
bool isTypeReference = IsTypeReference ( nextNode , BfToken_None , & outNodeIdx ) ;
mVisitorPos . mReadPos - - ;
if ( isTypeReference )
{
BfAstNode * outNode = mVisitorPos . Get ( outNodeIdx ) ;
BfAstNode * outNodeNext = mVisitorPos . Get ( outNodeIdx + 1 ) ;
BfTokenNode * equalsNode = NULL ;
if ( ( outNode ! = NULL ) & & ( BfNodeIsA < BfIdentifierNode > ( outNode ) ) & & ( BfNodeIsA < BfTokenNode > ( outNodeNext ) ) )
{
auto typeRef = CreateTypeRefAfter ( usingStatement ) ;
if ( typeRef = = NULL )
return usingStatement ;
MEMBER_SET ( varDecl , mTypeRef , typeRef ) ;
usingStatement - > SetSrcEnd ( typeRef - > GetSrcEnd ( ) ) ;
auto nameNode = ExpectIdentifierAfter ( usingStatement , " variable name " ) ;
if ( nameNode = = NULL )
return usingStatement ;
MEMBER_SET ( varDecl , mNameNode , nameNode ) ;
usingStatement - > SetSrcEnd ( varDecl - > GetSrcEnd ( ) ) ;
auto equalsNode = ExpectTokenAfter ( usingStatement , BfToken_AssignEquals ) ;
if ( equalsNode = = NULL )
return usingStatement ;
MEMBER_SET ( varDecl , mEqualsNode , equalsNode ) ;
usingStatement - > SetSrcEnd ( equalsNode - > GetSrcEnd ( ) ) ;
}
}
auto expr = CreateExpressionAfter ( usingStatement ) ;
if ( expr = = NULL )
return usingStatement ;
MEMBER_SET ( varDecl , mInitializer , expr ) ;
MEMBER_SET ( usingStatement , mVariableDeclaration , varDecl ) ;
}
tokenNode = ExpectTokenAfter ( usingStatement , BfToken_RParen ) ;
if ( tokenNode = = NULL )
return usingStatement ;
MEMBER_SET ( usingStatement , mCloseParen , tokenNode ) ;
auto stmt = CreateStatementAfter ( usingStatement , CreateStmtFlags_FindTrailingSemicolon ) ;
if ( stmt = = NULL )
return usingStatement ;
MEMBER_SET ( usingStatement , mEmbeddedStatement , stmt ) ;
return usingStatement ;
}
BfWhileStatement * BfReducer : : CreateWhileStatement ( BfAstNode * node )
{
auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) ;
auto whileStatement = mAlloc - > Alloc < BfWhileStatement > ( ) ;
ReplaceNode ( tokenNode , whileStatement ) ;
MEMBER_SET ( whileStatement , mWhileToken , tokenNode ) ;
tokenNode = ExpectTokenAfter ( whileStatement , BfToken_LParen ) ;
if ( tokenNode = = NULL )
return NULL ;
MEMBER_SET ( whileStatement , mOpenParen , tokenNode ) ;
// Condition
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( ! IsSemicolon ( nextNode ) )
{
auto expr = CreateExpressionAfter ( whileStatement ) ;
if ( expr = = NULL )
return whileStatement ;
MEMBER_SET ( whileStatement , mCondition , expr ) ;
}
tokenNode = ExpectTokenAfter ( whileStatement , BfToken_RParen ) ;
if ( tokenNode = = NULL )
return whileStatement ;
MEMBER_SET ( whileStatement , mCloseParen , tokenNode ) ;
auto stmt = CreateStatementAfter ( whileStatement , CreateStmtFlags_FindTrailingSemicolon ) ;
if ( stmt = = NULL )
return whileStatement ;
MEMBER_SET ( whileStatement , mEmbeddedStatement , stmt ) ;
return whileStatement ;
}
BfDoStatement * BfReducer : : CreateDoStatement ( BfAstNode * node )
{
auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) ;
auto doStatement = mAlloc - > Alloc < BfDoStatement > ( ) ;
ReplaceNode ( tokenNode , doStatement ) ;
MEMBER_SET ( doStatement , mDoToken , tokenNode ) ;
auto stmt = CreateStatementAfter ( doStatement , CreateStmtFlags_FindTrailingSemicolon ) ;
if ( stmt ! = NULL )
{
MEMBER_SET ( doStatement , mEmbeddedStatement , stmt ) ;
}
return doStatement ;
}
BfRepeatStatement * BfReducer : : CreateRepeatStatement ( BfAstNode * node )
{
auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) ;
auto repeatStatement = mAlloc - > Alloc < BfRepeatStatement > ( ) ;
ReplaceNode ( tokenNode , repeatStatement ) ;
MEMBER_SET ( repeatStatement , mRepeatToken , tokenNode ) ;
auto stmt = CreateStatementAfter ( repeatStatement , CreateStmtFlags_FindTrailingSemicolon ) ;
if ( stmt ! = NULL )
{
MEMBER_SET ( repeatStatement , mEmbeddedStatement , stmt ) ;
}
tokenNode = ExpectTokenAfter ( repeatStatement , BfToken_While ) ;
if ( tokenNode ! = NULL )
{
MEMBER_SET ( repeatStatement , mWhileToken , tokenNode ) ;
}
tokenNode = ExpectTokenAfter ( repeatStatement , BfToken_LParen ) ;
if ( tokenNode ! = NULL )
{
MEMBER_SET ( repeatStatement , mOpenParen , tokenNode ) ;
}
// Condition
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( ! IsSemicolon ( nextNode ) )
{
auto expr = CreateExpressionAfter ( repeatStatement ) ;
if ( expr = = NULL )
return repeatStatement ;
MEMBER_SET ( repeatStatement , mCondition , expr ) ;
}
tokenNode = ExpectTokenAfter ( repeatStatement , BfToken_RParen ) ;
if ( tokenNode ! = NULL )
{
MEMBER_SET ( repeatStatement , mCloseParen , tokenNode ) ;
}
return repeatStatement ;
}
BfSwitchStatement * BfReducer : : CreateSwitchStatement ( BfTokenNode * tokenNode )
{
auto switchStatement = mAlloc - > Alloc < BfSwitchStatement > ( ) ;
BfDeferredAstSizedArray < BfSwitchCase * > switchCases ( switchStatement - > mSwitchCases , mAlloc ) ;
ReplaceNode ( tokenNode , switchStatement ) ;
switchStatement - > mSwitchToken = tokenNode ;
tokenNode = ExpectTokenAfter ( switchStatement , BfToken_LParen ) ;
if ( tokenNode ! = NULL )
{
MEMBER_SET ( switchStatement , mOpenParen , tokenNode ) ;
}
auto switchValue = CreateExpressionAfter ( switchStatement ) ;
if ( switchValue ! = NULL )
{
MEMBER_SET ( switchStatement , mSwitchValue , switchValue ) ;
}
tokenNode = ExpectTokenAfter ( switchStatement , BfToken_RParen ) ;
if ( tokenNode ! = NULL )
{
MEMBER_SET ( switchStatement , mCloseParen , tokenNode ) ;
}
auto block = ExpectBlockAfter ( switchStatement ) ;
if ( block = = NULL )
return switchStatement ;
MoveNode ( block , switchStatement ) ;
switchStatement - > mOpenBrace = block - > mOpenBrace ;
switchStatement - > mCloseBrace = block - > mCloseBrace ;
bool hadEmptyCaseStatement = false ;
BfSwitchCase * switchCase = NULL ;
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( block ) ) ;
bool isDone = ! mVisitorPos . MoveNext ( ) ;
while ( ! isDone )
{
auto child = mVisitorPos . GetCurrent ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( child ) ;
BfToken token = BfToken_None ;
if ( tokenNode ! = NULL )
token = tokenNode - > GetToken ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = = NULL ) | |
( ( token ! = BfToken_Case ) & & ( token ! = BfToken_When ) & & ( token ! = BfToken_Default ) ) )
2019-08-23 11:56:54 -07:00
{
Fail ( " Expected 'case' " , child ) ;
return switchStatement ;
}
//TODO: This error was getting annoying... Put back?
// This check is here at the top, being processed for the previous switchCase because
// we don't throw an error on the last case in the switch
/*if (hadEmptyCaseStatement)
FailAfter ( " Expected case statement, 'fallthrough', or 'break' " , switchCase ) ; */
bool isDefault = token = = BfToken_Default ;
switchCase = mAlloc - > Alloc < BfSwitchCase > ( ) ;
BfDeferredAstSizedArray < BfExpression * > caseExpressions ( switchCase - > mCaseExpressions , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > caseCommas ( switchCase - > mCaseCommas , mAlloc ) ;
ReplaceNode ( tokenNode , switchCase ) ;
BfTokenNode * whenToken = NULL ;
if ( token = = BfToken_When )
whenToken = tokenNode ;
else
switchCase - > mCaseToken = tokenNode ;
for ( int caseIdx = 0 ; true ; caseIdx + + )
{
if ( ! isDefault )
{
BfExpression * expr = NULL ;
bool wasWhenSet = whenToken ! = NULL ;
if ( ! wasWhenSet )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
whenToken = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( whenToken ! = NULL ) & & ( whenToken - > GetToken ( ) ! = BfToken_When ) )
whenToken = NULL ;
}
if ( whenToken ! = NULL )
{
auto whenExpr = mAlloc - > Alloc < BfWhenExpression > ( ) ;
whenExpr - > mWhenToken = whenToken ;
ReplaceNode ( whenToken , whenExpr ) ;
//mVisitorPos.MoveNext();
//auto exprAfter = wasWhenSet ? (BfAstNode*)switchCase : (BfAstNode*)whenExpr;
if ( expr = = NULL )
{
auto innerExpr = CreateExpressionAfter ( whenToken ) ;
if ( innerExpr ! = NULL )
{
MEMBER_SET ( whenExpr , mExpression , innerExpr ) ;
}
expr = whenExpr ;
}
}
if ( expr = = NULL )
{
if ( auto bindToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( ( bindToken - > GetToken ( ) = = BfToken_Var ) | | ( bindToken - > GetToken ( ) = = BfToken_Let ) )
{
expr = CreateEnumCaseBindExpression ( bindToken ) ;
}
}
}
if ( expr = = NULL )
expr = CreateExpressionAfter ( switchCase ) ;
if ( expr = = NULL )
{
///
}
else
{
caseExpressions . push_back ( expr ) ;
MoveNode ( expr , switchCase ) ;
}
}
if ( ( whenToken = = NULL ) & & ( ! isDefault ) )
tokenNode = ExpectTokenAfter ( switchCase , BfToken_When , BfToken_Colon , BfToken_Comma ) ;
else
tokenNode = ExpectTokenAfter ( switchCase , BfToken_Colon ) ;
if ( tokenNode = = NULL )
break ;
if ( tokenNode - > GetToken ( ) = = BfToken_When )
{
whenToken = tokenNode ;
continue ;
}
if ( tokenNode - > GetToken ( ) = = BfToken_Colon )
{
MEMBER_SET ( switchCase , mColonToken , tokenNode ) ;
break ;
}
if ( isDefault )
{
Fail ( " Expected ':' " , tokenNode ) ;
break ;
}
MoveNode ( tokenNode , switchCase ) ;
caseCommas . push_back ( tokenNode ) ;
BF_ASSERT ( whenToken = = NULL ) ;
}
if ( isDefault )
{
if ( switchStatement - > mDefaultCase ! = NULL )
{
Fail ( " Only one default case is allowed " , switchCase ) ;
// Add to normal switch cases just so we process it
switchCases . push_back ( switchCase ) ;
}
else
switchStatement - > mDefaultCase = switchCase ;
}
else
{
if ( switchStatement - > mDefaultCase ! = NULL )
{
Fail ( " Default case must be last case " , switchStatement - > mDefaultCase ) ;
}
switchCases . push_back ( switchCase ) ;
}
hadEmptyCaseStatement = true ;
auto codeBlock = mAlloc - > Alloc < BfBlock > ( ) ;
//codeBlock->mSource = switchCase->mSource;
MEMBER_SET ( switchCase , mCodeBlock , codeBlock ) ;
//switchCase->Add(codeBlock);
BfDeferredAstSizedArray < BfAstNode * > codeBlockChildArr ( codeBlock - > mChildArr , mAlloc ) ;
while ( true )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode ! = NULL )
{
int token = tokenNode - > GetToken ( ) ;
if ( ( token = = BfToken_Case ) | | ( token = = BfToken_Default ) | | ( token = = BfToken_When ) )
break ; // Done! No fallthrough
}
nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode = = NULL )
break ;
hadEmptyCaseStatement = false ;
mVisitorPos . MoveNext ( ) ;
// We need to use CreateStmtFlags_NoCaseExpr because otherwise during typing a new statement at the end of one case, it
// could interpret the 'case' token for the next case as being part of a case expression in the first case
auto stmt = CreateStatement ( nextNode , ( CreateStmtFlags ) ( CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_NoCaseExpr | CreateStmtFlags_AllowLocalFunction ) ) ;
if ( stmt = = NULL )
{
AddErrorNode ( nextNode ) ;
}
else
{
MoveNode ( stmt , codeBlock ) ;
codeBlockChildArr . push_back ( stmt ) ;
}
}
MoveNode ( switchCase , switchStatement ) ;
if ( ! codeBlock - > IsInitialized ( ) )
{
int srcPos = switchCase - > GetSrcEnd ( ) ;
codeBlock - > Init ( srcPos , srcPos , srcPos ) ;
}
isDone = ! mVisitorPos . MoveNext ( ) ;
}
return switchStatement ;
}
// Does everything but pull the trailing semicolon
BfAstNode * BfReducer : : DoCreateStatement ( BfAstNode * node , CreateStmtFlags createStmtFlags )
{
auto subCreateStmtFlags = ( CreateStmtFlags ) ( createStmtFlags & ( CreateStmtFlags_NoCaseExpr | CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_AllowUnterminatedExpression ) ) ;
if ( node - > IsA < BfBlock > ( ) )
{
auto block = ( BfBlock * ) node ;
HandleBlock ( block , ( createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression ) ! = 0 ) ;
return block ;
}
BfVariableDeclaration * continuingVariable = NULL ;
BfTokenNode * refToken = NULL ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) )
{
int token = tokenNode - > GetToken ( ) ;
if ( ( token = = BfToken_Ref ) | | ( token = = BfToken_Mut ) )
{
refToken = tokenNode ;
}
else if ( token = = BfToken_Semicolon )
{
Fail ( " Empty statement not allowed " , tokenNode ) ;
auto emptyStatement = mAlloc - > Alloc < BfEmptyStatement > ( ) ;
ReplaceNode ( tokenNode , emptyStatement ) ;
emptyStatement - > mTrailingSemicolon = tokenNode ;
return emptyStatement ;
}
else if ( token = = BfToken_Break )
{
auto breakStmt = mAlloc - > Alloc < BfBreakStatement > ( ) ;
ReplaceNode ( tokenNode , breakStmt ) ;
breakStmt - > mBreakNode = tokenNode ;
if ( auto label = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . GetNext ( ) ) )
{
MEMBER_SET ( breakStmt , mLabel , label ) ;
mVisitorPos . MoveNext ( ) ;
}
else if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_Mixin )
{
MEMBER_SET ( breakStmt , mLabel , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
}
}
return breakStmt ;
}
else if ( token = = BfToken_Continue )
{
auto continueStmt = mAlloc - > Alloc < BfContinueStatement > ( ) ;
ReplaceNode ( tokenNode , continueStmt ) ;
continueStmt - > mContinueNode = tokenNode ;
if ( auto label = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . GetNext ( ) ) )
{
MEMBER_SET ( continueStmt , mLabel , label ) ;
mVisitorPos . MoveNext ( ) ;
}
else if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_Mixin )
{
MEMBER_SET ( continueStmt , mLabel , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
}
}
return continueStmt ;
}
else if ( token = = BfToken_Fallthrough )
{
auto fallthroughStmt = mAlloc - > Alloc < BfFallthroughStatement > ( ) ;
ReplaceNode ( tokenNode , fallthroughStmt ) ;
fallthroughStmt - > mFallthroughToken = tokenNode ;
return fallthroughStmt ;
}
else if ( token = = BfToken_For )
{
return CreateForStatement ( node ) ;
}
else if ( token = = BfToken_Using )
{
return CreateUsingStatement ( node ) ;
}
else if ( token = = BfToken_While )
{
return CreateWhileStatement ( node ) ;
}
else if ( token = = BfToken_Do )
{
auto checkNode = mVisitorPos . Get ( mVisitorPos . mReadPos + 2 ) ;
auto checkToken = BfNodeDynCast < BfTokenNode > ( checkNode ) ;
if ( ( checkToken ! = NULL ) & & ( checkToken - > GetToken ( ) = = BfToken_While ) )
return CreateRepeatStatement ( node ) ;
else
return CreateDoStatement ( node ) ;
}
else if ( token = = BfToken_Repeat )
{
return CreateRepeatStatement ( node ) ;
}
else if ( token = = BfToken_Return )
{
auto returnStmt = mAlloc - > Alloc < BfReturnStatement > ( ) ;
ReplaceNode ( node , returnStmt ) ;
MEMBER_SET ( returnStmt , mReturnToken , tokenNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( ! IsSemicolon ( nextNode ) )
{
auto expr = CreateExpressionAfter ( returnStmt ) ;
MEMBER_SET_CHECKED ( returnStmt , mExpression , expr ) ;
}
return returnStmt ;
}
else if ( token = = BfToken_Delete )
{
auto deleteStmt = mAlloc - > Alloc < BfDeleteStatement > ( ) ;
ReplaceNode ( node , deleteStmt ) ;
MEMBER_SET ( deleteStmt , mDeleteToken , tokenNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_Append )
{
MEMBER_SET ( deleteStmt , mTargetTypeToken , tokenNode ) ;
}
else if ( tokenNode - > GetToken ( ) = = BfToken_Colon )
{
MEMBER_SET ( deleteStmt , mTargetTypeToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( tokenNode - > mToken = = BfToken_Append )
{
MEMBER_SET ( deleteStmt , mAllocExpr , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
}
}
if ( deleteStmt - > mAllocExpr = = NULL )
{
auto allocExpr = CreateExpressionAfter ( deleteStmt ) ;
if ( allocExpr ! = NULL )
{
MEMBER_SET ( deleteStmt , mAllocExpr , allocExpr ) ;
}
}
}
}
auto expr = CreateExpressionAfter ( deleteStmt ) ;
MEMBER_SET_CHECKED ( deleteStmt , mExpression , expr ) ;
return deleteStmt ;
}
else if ( token = = BfToken_Throw )
{
auto throwStmt = mAlloc - > Alloc < BfThrowStatement > ( ) ;
ReplaceNode ( node , throwStmt ) ;
MEMBER_SET ( throwStmt , mThrowToken , tokenNode ) ;
auto expr = CreateExpressionAfter ( throwStmt ) ;
MEMBER_SET_CHECKED ( throwStmt , mExpression , expr ) ;
return throwStmt ;
}
else if ( token = = BfToken_If )
{
subCreateStmtFlags = ( CreateStmtFlags ) ( createStmtFlags & ( CreateStmtFlags_FindTrailingSemicolon ) ) ;
auto ifStmt = mAlloc - > Alloc < BfIfStatement > ( ) ;
ReplaceNode ( node , ifStmt ) ;
MEMBER_SET ( ifStmt , mIfToken , tokenNode ) ;
tokenNode = ExpectTokenAfter ( ifStmt , BfToken_LParen ) ;
MEMBER_SET_CHECKED ( ifStmt , mOpenParen , tokenNode ) ;
auto condExpr = CreateExpressionAfter ( ifStmt , CreateExprFlags_AllowVariableDecl ) ;
MEMBER_SET_CHECKED ( ifStmt , mCondition , condExpr ) ;
tokenNode = ExpectTokenAfter ( ifStmt , BfToken_RParen ) ;
MEMBER_SET_CHECKED ( ifStmt , mCloseParen , tokenNode ) ;
auto trueStmt = CreateStatementAfter ( ifStmt , subCreateStmtFlags ) ;
MEMBER_SET_CHECKED ( ifStmt , mTrueStatement , trueStmt ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_Else ) )
{
MEMBER_SET ( ifStmt , mElseToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
auto falseStmt = CreateStatementAfter ( ifStmt , subCreateStmtFlags ) ;
MEMBER_SET_CHECKED ( ifStmt , mFalseStatement , falseStmt ) ;
}
return ifStmt ;
}
else if ( token = = BfToken_Switch )
{
return CreateSwitchStatement ( tokenNode ) ;
}
else if ( token = = BfToken_Defer )
{
auto deferStmt = mAlloc - > Alloc < BfDeferStatement > ( ) ;
ReplaceNode ( tokenNode , deferStmt ) ;
deferStmt - > mDeferToken = tokenNode ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto nextTokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( nextTokenNode - > GetToken ( ) = = BfToken_Colon )
{
MEMBER_SET ( deferStmt , mColonToken , nextTokenNode ) ;
mVisitorPos . MoveNext ( ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( ( nextToken - > GetToken ( ) = = BfToken_Colon ) | | ( nextToken - > GetToken ( ) = = BfToken_Mixin ) )
{
MEMBER_SET ( deferStmt , mScopeName , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
}
}
else if ( auto identifier = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . GetNext ( ) ) )
{
MEMBER_SET ( deferStmt , mScopeName , identifier ) ;
mVisitorPos . MoveNext ( ) ;
}
if ( deferStmt - > mScopeName = = NULL )
{
FailAfter ( " Expected scope name " , deferStmt ) ;
}
}
else if ( nextTokenNode - > GetToken ( ) = = BfToken_LParen )
{
MEMBER_SET ( deferStmt , mOpenParen , nextTokenNode ) ;
mVisitorPos . MoveNext ( ) ;
nextTokenNode = ExpectTokenAfter ( deferStmt , BfToken_Scope , BfToken_Stack ) ;
MEMBER_SET_CHECKED ( deferStmt , mScopeToken , nextTokenNode ) ;
nextTokenNode = ExpectTokenAfter ( deferStmt , BfToken_RParen ) ;
MEMBER_SET_CHECKED ( deferStmt , mCloseParen , nextTokenNode ) ;
}
}
if ( auto nextTokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( nextTokenNode - > GetToken ( ) = = BfToken_LBracket )
{
auto bindNode = mAlloc - > Alloc < BfDeferBindNode > ( ) ;
ReplaceNode ( nextTokenNode , bindNode ) ;
MEMBER_SET ( bindNode , mOpenBracket , nextTokenNode ) ;
mVisitorPos . MoveNext ( ) ;
BfDeferredAstSizedArray < BfIdentifierNode * > params ( bindNode - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( bindNode - > mCommas , mAlloc ) ;
for ( int paramIdx = 0 ; true ; paramIdx + + )
{
bool isRBracket = false ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
isRBracket = tokenNode - > GetToken ( ) = = BfToken_RBracket ;
if ( ! isRBracket )
{
auto nameIdentifier = ExpectIdentifierAfter ( bindNode , " parameter name " ) ;
if ( nameIdentifier = = NULL )
break ;
MoveNode ( nameIdentifier , bindNode ) ;
params . push_back ( nameIdentifier ) ;
}
tokenNode = ExpectTokenAfter ( bindNode , BfToken_Comma , BfToken_RBracket ) ;
if ( tokenNode = = NULL )
return deferStmt ;
if ( tokenNode - > GetToken ( ) = = BfToken_RBracket )
{
MEMBER_SET ( bindNode , mCloseBracket , tokenNode ) ;
break ;
}
MoveNode ( tokenNode , bindNode ) ;
commas . push_back ( tokenNode ) ;
}
MEMBER_SET ( deferStmt , mBind , bindNode ) ;
}
}
BfAstNode * targetNode = CreateStatementAfter ( deferStmt ) ;
if ( targetNode ! = NULL )
{
BfAstNode * innerTarget = targetNode ;
if ( auto exprStmt = BfNodeDynCast < BfExpressionStatement > ( innerTarget ) )
innerTarget = exprStmt - > mExpression ;
if ( deferStmt - > mBind ! = NULL )
{
if ( ! innerTarget - > IsA < BfBlock > ( ) )
{
Fail ( " Only blocks are allowed when defer binding is used " , targetNode ) ;
}
}
else
{
if ( ( ! innerTarget - > IsA < BfInvocationExpression > ( ) ) & &
( ! innerTarget - > IsA < BfBlock > ( ) ) & &
( ! innerTarget - > IsA < BfDeleteStatement > ( ) ) )
{
Fail ( " Only invocation expressions, statement blocks, or deletes are allowed " , targetNode ) ;
}
}
MEMBER_SET ( deferStmt , mTargetNode , targetNode ) ;
}
return deferStmt ;
}
else if ( token = = BfToken_Comma )
{
auto prevVarDecl = mVisitorPos . Get ( mVisitorPos . mWritePos - 1 ) ;
if ( auto exprStmt = BfNodeDynCast < BfExpressionStatement > ( prevVarDecl ) )
{
continuingVariable = BfNodeDynCast < BfVariableDeclaration > ( exprStmt - > mExpression ) ;
}
}
else if ( ( token = = BfToken_Const ) | | ( token = = BfToken_ReadOnly ) )
{
auto stmt = CreateStatementAfter ( tokenNode , ( CreateStmtFlags ) ( CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_ForceVariableDecl ) ) ;
if ( auto exprStmt = BfNodeDynCast < BfExpressionStatement > ( stmt ) )
{
if ( auto variableDecl = BfNodeDynCast < BfVariableDeclaration > ( exprStmt - > mExpression ) )
{
if ( variableDecl - > mModSpecifier ! = NULL )
{
Fail ( StrFormat ( " '%s' already specified " , BfTokenToString ( variableDecl - > mModSpecifier - > GetToken ( ) ) ) , variableDecl - > mModSpecifier ) ;
}
MEMBER_SET ( variableDecl , mModSpecifier , tokenNode ) ;
exprStmt - > SetSrcStart ( variableDecl - > mSrcStart ) ;
return stmt ;
}
}
Fail ( StrFormat ( " Unexpected '%s' specifier " , BfTokenToString ( tokenNode - > GetToken ( ) ) ) , tokenNode ) ;
return stmt ;
}
else if ( token = = BfToken_Volatile )
{
Fail ( " Cannot create volatile local variables " , tokenNode ) ;
return NULL ;
}
else if ( token = = BfToken_Asm )
{
return CreateInlineAsmStatement ( node ) ;
}
else if ( token = = BfToken_Mixin )
{
auto methodDecl = mAlloc - > Alloc < BfMethodDeclaration > ( ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( methodDecl - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( methodDecl - > mCommas , mAlloc ) ;
ReplaceNode ( tokenNode , methodDecl ) ;
methodDecl - > mDocumentation = FindDocumentation ( methodDecl ) ;
methodDecl - > mMixinSpecifier = tokenNode ;
auto nameNode = ExpectIdentifierAfter ( methodDecl ) ;
if ( nameNode ! = NULL )
{
2019-11-17 09:28:39 -08:00
MEMBER_SET ( methodDecl , mNameNode , nameNode ) ;
2019-08-23 11:56:54 -07:00
ParseMethod ( methodDecl , & params , & commas , true ) ;
}
auto localMethodDecl = mAlloc - > Alloc < BfLocalMethodDeclaration > ( ) ;
ReplaceNode ( methodDecl , localMethodDecl ) ;
localMethodDecl - > mMethodDeclaration = methodDecl ;
return localMethodDecl ;
}
}
if ( auto identifier = BfNodeDynCast < BfIdentifierNode > ( node ) )
{
node = CompactQualifiedName ( identifier ) ;
}
bool isLocalVariable = false ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( nextToken - > GetToken ( ) = = BfToken_Colon )
{
auto nameIdentifier = BfNodeDynCast < BfIdentifierNode > ( node ) ;
if ( nameIdentifier ! = NULL )
{
BfLabelNode * labelNode = mAlloc - > Alloc < BfLabelNode > ( ) ;
ReplaceNode ( nameIdentifier , labelNode ) ;
labelNode - > mLabel = nameIdentifier ;
mVisitorPos . MoveNext ( ) ;
MEMBER_SET ( labelNode , mColonToken , nextToken ) ;
BfAstNode * stmt = NULL ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode ! = NULL )
{
mVisitorPos . MoveNext ( ) ;
stmt = DoCreateStatement ( nextNode ) ;
if ( auto labelableStmt = BfNodeDynCast < BfLabelableStatement > ( stmt ) )
{
MEMBER_SET ( labelableStmt , mLabelNode , labelNode ) ;
return labelableStmt ;
}
if ( auto block = BfNodeDynCast < BfBlock > ( stmt ) )
{
auto labeledBlock = mAlloc - > Alloc < BfLabeledBlock > ( ) ;
ReplaceNode ( block , labeledBlock ) ;
labeledBlock - > mBlock = block ;
MEMBER_SET ( labeledBlock , mLabelNode , labelNode ) ;
return labeledBlock ;
}
}
Fail ( " Label must appear before a labelable statement (if, for, do, while, switch, block) " , labelNode ) ;
AddErrorNode ( labelNode ) ;
return stmt ;
}
}
}
int typeRefEndNode = - 1 ;
bool isTuple = false ;
if ( IsTypeReference ( node , BfToken_None , & typeRefEndNode , NULL , NULL , & isTuple ) )
isLocalVariable = true ;
if ( ( isLocalVariable ) & & ( isTuple ) )
{
if ( typeRefEndNode ! = - 1 )
{
// When we're typing something like "(a, )" ... don't make that a type ref yet because it could be "(a, b) = " where
// we're typing a tuple value rather than a tuple tpye ref
auto checkNode = mVisitorPos . Get ( typeRefEndNode ) ;
if ( checkNode = = NULL )
isLocalVariable = false ;
}
}
if ( nextNode = = NULL )
{
// Treat ending identifier as just an identifier (could be block result)
isLocalVariable = false ;
}
if ( ( isLocalVariable ) & & ( typeRefEndNode ! = - 1 ) & & ( continuingVariable = = NULL ) & & ( ( createStmtFlags & CreateStmtFlags_AllowLocalFunction ) ! = 0 ) )
{
BfTokenNode * nextToken = BfNodeDynCast < BfTokenNode > ( node ) ;
if ( ( nextToken = = NULL ) | |
( ( nextToken - > GetToken ( ) ! = BfToken_Delegate ) & & ( nextToken - > GetToken ( ) ! = BfToken_Function ) ) )
{
auto afterTypeRefNode = mVisitorPos . Get ( typeRefEndNode ) ;
if ( auto nameIdentifier = BfNodeDynCast < BfIdentifierNode > ( afterTypeRefNode ) )
{
auto nextNextNode = mVisitorPos . Get ( typeRefEndNode + 1 ) ;
if ( auto afterNameToken = BfNodeDynCast < BfTokenNode > ( nextNextNode ) )
{
bool isLocalMethod = ( afterNameToken - > GetToken ( ) = = BfToken_LParen ) | | ( afterNameToken - > GetToken ( ) = = BfToken_LChevron ) ;
if ( isLocalMethod )
{
int prevReadPos = mVisitorPos . mReadPos ;
mVisitorPos . mReadPos = typeRefEndNode ;
isLocalMethod = IsLocalMethod ( nameIdentifier ) ;
mVisitorPos . mReadPos = prevReadPos ;
}
if ( isLocalMethod )
{
auto typeRef = CreateTypeRef ( node ) ;
if ( mVisitorPos . GetNext ( ) ! = nameIdentifier )
isLocalMethod = false ;
else
{
int prevReadPos = mVisitorPos . mReadPos ;
mVisitorPos . MoveNext ( ) ;
isLocalMethod = IsLocalMethod ( nameIdentifier ) ;
if ( ! isLocalMethod )
mVisitorPos . mReadPos = prevReadPos ;
}
if ( ! isLocalMethod )
{
// TypeRef didn't match what we expected, just set it up as a variable declaration
auto variableDeclaration = mAlloc - > Alloc < BfVariableDeclaration > ( ) ;
ReplaceNode ( typeRef , variableDeclaration ) ;
variableDeclaration - > mTypeRef = typeRef ;
return variableDeclaration ;
}
auto methodDecl = mAlloc - > Alloc < BfMethodDeclaration > ( ) ;
ReplaceNode ( typeRef , methodDecl ) ;
methodDecl - > mDocumentation = FindDocumentation ( methodDecl ) ;
methodDecl - > mReturnType = typeRef ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( methodDecl - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( methodDecl - > mCommas , mAlloc ) ;
MEMBER_SET ( methodDecl , mNameNode , nameIdentifier ) ;
if ( afterNameToken - > GetToken ( ) = = BfToken_LChevron )
{
auto genericParams = CreateGenericParamsDeclaration ( afterNameToken ) ;
if ( genericParams ! = NULL )
{
MEMBER_SET ( methodDecl , mGenericParams , genericParams ) ;
}
}
ParseMethod ( methodDecl , & params , & commas , true ) ;
auto localMethodDecl = mAlloc - > Alloc < BfLocalMethodDeclaration > ( ) ;
ReplaceNode ( methodDecl , localMethodDecl ) ;
localMethodDecl - > mMethodDeclaration = methodDecl ;
return localMethodDecl ;
}
}
}
}
}
if ( ( isLocalVariable ) | | ( continuingVariable ! = NULL ) )
{
auto variableDeclaration = mAlloc - > Alloc < BfVariableDeclaration > ( ) ;
BfTypeReference * typeRef = NULL ;
if ( continuingVariable ! = NULL )
{
typeRef = continuingVariable - > mTypeRef ;
variableDeclaration - > mModSpecifier = continuingVariable - > mModSpecifier ;
ReplaceNode ( node , variableDeclaration ) ;
variableDeclaration - > mPrecedingComma = ( BfTokenNode * ) node ;
}
else
{
typeRef = CreateTypeRef ( node ) ;
if ( typeRef = = NULL )
return NULL ;
ReplaceNode ( typeRef , variableDeclaration ) ;
}
variableDeclaration - > mTypeRef = typeRef ;
BfAstNode * variableNameNode = NULL ;
nextNode = mVisitorPos . GetNext ( ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_LParen )
{
mVisitorPos . mReadPos + + ;
variableNameNode = CreateTupleExpression ( tokenNode ) ;
}
}
if ( variableNameNode = = NULL )
{
auto checkToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( mVisitorPos . mReadPos + 2 ) ) ;
if ( ( checkToken ! = NULL ) & & ( checkToken - > mToken = = BfToken_Dot ) )
{
FailAfter ( " Expected variable name " , variableDeclaration ) ;
}
else
variableNameNode = ExpectIdentifierAfter ( variableDeclaration , " variable name " ) ;
}
if ( variableNameNode = = NULL )
return variableDeclaration ;
bool isValidFinish = false ;
BfTokenNode * tokenNode ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) ) )
2019-08-23 11:56:54 -07:00
{
int token = tokenNode - > GetToken ( ) ;
if ( ( token = = BfToken_AssignEquals ) | | ( token = = BfToken_Semicolon ) | | ( token = = BfToken_Comma ) )
isValidFinish = true ;
}
/*if (!isValidFinish)
{
if ( auto nextIdentifier = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( auto nextNextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( mVisitorPos . mReadPos + 2 ) ) )
{
if ( ( nextNextToken - > GetToken ( ) = = BfToken_LParen ) | | ( nextNextToken - > GetToken ( ) = = BfToken_LChevron ) )
{
// It's less destructive to not consume the identifier we see as the name, because it may not be. This handles the case
// where we're typing some stuff before a local method declaration. Kindof a corner case...
Fail ( " Unexpected type " , typeRef ) ;
mVisitorPos . mReadPos - - ;
return variableDeclaration ;
}
}
}
} */
// Is a local variable?
tokenNode = ExpectTokenAfter ( variableNameNode , BfToken_AssignEquals , BfToken_Semicolon , BfToken_Comma ) ;
variableDeclaration - > mNameNode = variableNameNode ;
MoveNode ( variableNameNode , variableDeclaration ) ;
if ( tokenNode = = NULL )
return variableDeclaration ;
if ( tokenNode - > GetToken ( ) = = BfToken_AssignEquals )
{
MEMBER_SET ( variableDeclaration , mEqualsNode , tokenNode ) ;
if ( variableDeclaration - > mInitializer = = NULL )
variableDeclaration - > mInitializer = CreateExpressionAfter ( variableDeclaration , ( CreateExprFlags ) ( createStmtFlags & CreateStmtFlags_To_CreateExprFlags_Mask ) ) ;
if ( variableDeclaration - > mInitializer = = NULL )
return variableDeclaration ;
MoveNode ( variableDeclaration - > mInitializer , variableDeclaration ) ;
}
else
mVisitorPos . mReadPos - - ; // Backtrack to the semicolon or comma
return variableDeclaration ;
}
if ( ( createStmtFlags & CreateStmtFlags_ForceVariableDecl ) ! = 0 )
{
Fail ( " Expected local variable declaration " , node ) ;
return NULL ;
}
// Must be an expression. Always set CreateExprFlags_NoCaseExpr, to keep ending statements in a switch case to look like case expressions
CreateExprFlags exprFlags = ( CreateExprFlags ) ( createStmtFlags & CreateStmtFlags_To_CreateExprFlags_Mask ) ;
if ( ( createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression ) = = 0 )
exprFlags = ( CreateExprFlags ) ( exprFlags | CreateExprFlags_NoCaseExpr ) ;
auto expr = CreateExpression ( node , exprFlags ) ;
if ( expr = = NULL )
return NULL ;
bool isOkUnary = false ;
if ( auto unaryOperatorExpr = BfNodeDynCast < BfUnaryOperatorExpression > ( expr ) )
{
isOkUnary =
( unaryOperatorExpr - > mOp = = BfUnaryOp_Increment ) | |
( unaryOperatorExpr - > mOp = = BfUnaryOp_PostIncrement ) | |
( unaryOperatorExpr - > mOp = = BfUnaryOp_Decrement ) | |
( unaryOperatorExpr - > mOp = = BfUnaryOp_PostDecrement ) ;
if ( ( unaryOperatorExpr - > mOp = = BfUnaryOp_Ref ) | | ( unaryOperatorExpr - > mOp = = BfUnaryOp_Mut ) | | ( unaryOperatorExpr - > mOp = = BfUnaryOp_Out ) )
{
if ( unaryOperatorExpr - > mOp = = BfUnaryOp_Ref )
mPassInstance - > Fail ( " Cannot use 'ref' in this context " , unaryOperatorExpr ) ;
else if ( unaryOperatorExpr - > mOp = = BfUnaryOp_Mut )
mPassInstance - > Fail ( " Cannot use 'mut' in this context " , unaryOperatorExpr ) ;
else
mPassInstance - > Fail ( " Cannot use 'out' in this context " , unaryOperatorExpr ) ;
return NULL ;
}
}
if ( ( ! mPrevStmtHadError ) & & ( ! mStmtHasError ) )
{
nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode ! = NULL )
{
if ( ! isOkUnary )
expr - > VerifyIsStatement ( mPassInstance ) ;
}
}
return expr ;
}
// This is conservative - it doesn't HAVE to return true, but in some cases may cause a parsing error if the nodes
// can be consumed as a statement rather than an expression. We must be more careful about not returning 'true'
// for something that can only be interpreted as a statement, however.
bool BfReducer : : IsTerminatingExpression ( BfAstNode * node )
{
int parenDepth = 0 ;
int chevronDepth = 0 ;
int readIdx = mVisitorPos . mReadPos ;
bool prevWasValue = false ;
BfTokenNode * prevTokenNode = NULL ;
while ( true )
{
auto node = mVisitorPos . Get ( readIdx ) ;
if ( node = = NULL )
break ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) ;
if ( tokenNode ! = NULL )
{
switch ( tokenNode - > GetToken ( ) )
{
case BfToken_AssignEquals :
if ( parenDepth = = 0 )
return false ;
break ;
case BfToken_LParen :
chevronDepth = 0 ;
parenDepth + + ;
break ;
case BfToken_RParen :
chevronDepth = 0 ;
parenDepth - - ;
break ;
case BfToken_LChevron :
chevronDepth + + ;
break ;
case BfToken_RChevron :
// If we find a < and > that are not seperated by parens, that's a generic, which must be a
// variable decl if it's not in parens
if ( ( parenDepth = = 0 ) & & ( chevronDepth > 0 ) )
return false ;
chevronDepth - - ;
break ;
case BfToken_RDblChevron :
chevronDepth - - ;
break ;
case BfToken_Comma :
if ( parenDepth = = 0 )
return false ;
break ;
case BfToken_As :
case BfToken_Append :
case BfToken_Default :
case BfToken_Is :
case BfToken_Stack :
case BfToken_Scope :
case BfToken_New :
case BfToken_RetType :
case BfToken_SizeOf :
case BfToken_This :
case BfToken_TypeOf :
case BfToken_LessEquals :
case BfToken_GreaterEquals :
case BfToken_LBracket :
case BfToken_RBracket :
case BfToken_Colon :
case BfToken_Dot :
case BfToken_DotDot :
case BfToken_QuestionDot :
case BfToken_QuestionLBracket :
case BfToken_Plus :
case BfToken_Minus :
case BfToken_DblPlus :
case BfToken_DblMinus :
case BfToken_Star :
case BfToken_ForwardSlash :
case BfToken_Modulus :
case BfToken_Ampersand :
case BfToken_At :
case BfToken_DblAmpersand :
case BfToken_Bar :
case BfToken_DblBar :
case BfToken_Bang :
case BfToken_Carat :
case BfToken_Tilde :
case BfToken_Question :
case BfToken_DblQuestion :
case BfToken_Arrow :
case BfToken_FatArrow :
// Allow these
break ;
case BfToken_Semicolon :
return false ;
default :
// Disallow everything else
return false ;
}
}
if ( ( node - > IsExact < BfIdentifierNode > ( ) ) | |
( node - > IsExact < BfQualifiedNameNode > ( ) ) | |
( node - > IsExact < BfMemberReferenceExpression > ( ) ) | |
( node - > IsExact < BfLiteralExpression > ( ) ) )
{
if ( prevWasValue )
{
// Two values in a row cannot be a valid expression
return false ;
}
prevWasValue = true ;
}
else
{
prevWasValue = false ;
}
if ( auto block = BfNodeDynCastExact < BfBlock > ( node ) )
{
// Local method decl
if ( ( parenDepth = = 0 ) & & ( prevTokenNode ! = NULL ) & & ( prevTokenNode - > GetToken ( ) = = BfToken_RParen ) )
return false ;
}
prevTokenNode = tokenNode ;
readIdx + + ;
}
int outEndNode = 0 ;
bool couldBeExpr = false ;
if ( IsTypeReference ( node , BfToken_None , & outEndNode , & couldBeExpr ) )
{
if ( outEndNode = = mVisitorPos . mTotalSize - 1 )
{
if ( auto name = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . Get ( outEndNode ) ) )
{
auto beforeNameToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( outEndNode - 1 ) ) ;
// We treat "a*b" as a multiply rather than a variable declaration
if ( ( beforeNameToken = = NULL ) | | ( beforeNameToken - > GetToken ( ) ! = BfToken_Star ) )
{
return false ;
}
}
}
}
return true ;
}
BfAstNode * BfReducer : : CreateStatement ( BfAstNode * node , CreateStmtFlags createStmtFlags )
{
AssertCurrentNode ( node ) ;
node = ReplaceTokenStarter ( node ) ;
if ( ( createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression ) ! = 0 )
{
if ( IsTerminatingExpression ( node ) )
{
mPrevStmtHadError = false ;
// Must be an expression. Always set CreateExprFlags_NoCaseExpr, to keep ending statements in a switch case to look like case expressions
2019-10-14 14:08:29 -07:00
auto expr = CreateExpression ( node , ( CreateExprFlags ) ( ( createStmtFlags & CreateStmtFlags_To_CreateExprFlags_Mask ) | CreateExprFlags_NoCaseExpr ) ) ;
2019-08-23 11:56:54 -07:00
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode ! = NULL )
{
mPassInstance - > FailAfter ( " Semicolon expected " , expr ) ;
}
return expr ;
}
}
mStmtHasError = false ;
auto stmtNode = DoCreateStatement ( node , createStmtFlags ) ;
mPrevStmtHadError = mStmtHasError ;
if ( stmtNode = = NULL )
return NULL ;
auto origStmtNode = stmtNode ;
if ( stmtNode - > IsA < BfBlock > ( ) )
return stmtNode ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto expr = BfNodeDynCast < BfExpression > ( stmtNode ) )
{
if ( ( ( createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression ) ! = 0 ) & & ( nextNode = = NULL ) )
return expr ;
auto stmt = mAlloc - > Alloc < BfExpressionStatement > ( ) ;
ReplaceNode ( expr , stmt ) ;
stmt - > mExpression = expr ;
stmtNode = stmt ;
}
if ( auto stmt = BfNodeDynCast < BfStatement > ( stmtNode ) )
{
if ( ( stmt - > IsMissingSemicolon ( ) ) & & ( ( createStmtFlags & CreateStmtFlags_FindTrailingSemicolon ) ! = 0 ) & & ( ! stmt - > IsA < BfEmptyStatement > ( ) ) )
{
if ( ! IsSemicolon ( nextNode ) )
{
// Why did we have this BfIdentifierNode check? It failed to throw an error on just things like "{ a }"
if ( /*(origStmtNode->IsA<BfIdentifierNode>()) || */ ( origStmtNode - > IsA < BfCompoundStatement > ( ) ) | | ( origStmtNode - > IsA < BfBlock > ( ) ) )
return stmt ;
if ( origStmtNode - > IsA < BfVariableDeclaration > ( ) )
{
// For compound variables
auto commaToken = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( commaToken ! = NULL ) & & ( commaToken - > GetToken ( ) = = BfToken_Comma ) )
return stmt ;
}
if ( ( ( createStmtFlags & CreateStmtFlags_AllowUnterminatedExpression ) ! = 0 ) & & ( origStmtNode - > IsA < BfExpression > ( ) ) & & ( nextNode = = NULL ) )
return stmt ;
mPassInstance - > FailAfterAt ( " Semicolon expected " , node - > GetSourceData ( ) , stmt - > GetSrcEnd ( ) - 1 ) ;
mPrevStmtHadError = true ;
return stmt ;
}
if ( ( ! stmt - > IsA < BfBlock > ( ) ) & & ( ! stmt - > IsA < BfIdentifierNode > ( ) ) )
{
mVisitorPos . MoveNext ( ) ;
MEMBER_SET ( stmt , mTrailingSemicolon , ( BfTokenNode * ) nextNode ) ;
}
}
}
return stmtNode ;
}
BfAstNode * BfReducer : : CreateStatementAfter ( BfAstNode * node , CreateStmtFlags createStmtFlags )
{
AssertCurrentNode ( node ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode = = NULL )
{
FailAfter ( " Expected statement " , node ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
BfAstNode * stmt = CreateStatement ( nextNode , createStmtFlags ) ;
if ( stmt = = NULL )
{
// Nope, didn't handle it
mVisitorPos . mReadPos - - ;
}
return stmt ;
}
bool BfReducer : : IsExtendedTypeName ( BfIdentifierNode * identifierNode )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode = = NULL )
return false ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode = = NULL )
return false ;
int token = tokenNode - > GetToken ( ) ;
return ( ( token = = BfToken_Star ) | |
( token = = BfToken_Question ) | |
( token = = BfToken_Dot ) | |
( token = = BfToken_LChevron ) | |
( token = = BfToken_LBracket ) ) ;
}
static String TypeToString ( BfTypeReference * typeRef )
{
if ( typeRef = = NULL )
return " null " ;
if ( auto qualifiedTypeRef = BfNodeDynCast < BfQualifiedTypeReference > ( typeRef ) )
return " ( " + TypeToString ( qualifiedTypeRef - > mLeft ) + " . " + TypeToString ( qualifiedTypeRef - > mRight ) + " ) " ;
if ( auto genericTypeInstanceRef = BfNodeDynCast < BfGenericInstanceTypeRef > ( typeRef ) )
return TypeToString ( genericTypeInstanceRef - > mElementType ) + " <...> " ;
return typeRef - > ToString ( ) ;
}
BfTypeReference * BfReducer : : DoCreateNamedTypeRef ( BfIdentifierNode * identifierNode )
{
if ( auto qualifiedNameNode = BfNodeDynCast < BfQualifiedNameNode > ( identifierNode ) )
{
auto qualifiedTypeRef = mAlloc - > Alloc < BfQualifiedTypeReference > ( ) ;
ReplaceNode ( identifierNode , qualifiedTypeRef ) ;
MoveNode ( qualifiedNameNode - > mLeft , qualifiedTypeRef ) ;
auto leftTypeRef = DoCreateNamedTypeRef ( qualifiedNameNode - > mLeft ) ;
MEMBER_SET ( qualifiedTypeRef , mLeft , leftTypeRef ) ;
MEMBER_SET ( qualifiedTypeRef , mDot , qualifiedNameNode - > mDot ) ;
MoveNode ( qualifiedNameNode - > mRight , qualifiedNameNode ) ;
auto rightTypeRef = DoCreateNamedTypeRef ( qualifiedNameNode - > mRight ) ;
MEMBER_SET ( qualifiedTypeRef , mRight , rightTypeRef ) ;
return qualifiedTypeRef ;
}
else
{
auto namedTypeRef = mAlloc - > Alloc < BfNamedTypeReference > ( ) ;
namedTypeRef - > mNameNode = identifierNode ;
ReplaceNode ( identifierNode , namedTypeRef ) ;
namedTypeRef - > SetTriviaStart ( identifierNode - > GetTriviaStart ( ) ) ;
return namedTypeRef ;
}
}
BfTypeReference * BfReducer : : DoCreateTypeRef ( BfAstNode * firstNode , bool parseArrayBracket )
{
AssertCurrentNode ( firstNode ) ;
auto identifierNode = BfNodeDynCast < BfIdentifierNode > ( firstNode ) ;
if ( identifierNode = = NULL )
{
if ( auto memberReferenceExpression = BfNodeDynCast < BfMemberReferenceExpression > ( firstNode ) )
{
auto qualifiedTypeRef = mAlloc - > Alloc < BfQualifiedTypeReference > ( ) ;
ReplaceNode ( firstNode , qualifiedTypeRef ) ;
BF_ASSERT ( memberReferenceExpression - > mTarget ! = NULL ) ;
if ( memberReferenceExpression - > mTarget ! = NULL )
{
MoveNode ( memberReferenceExpression - > mTarget , qualifiedTypeRef ) ;
auto leftTypeRef = DoCreateTypeRef ( memberReferenceExpression - > mTarget ) ;
MEMBER_SET ( qualifiedTypeRef , mLeft , leftTypeRef ) ;
}
MEMBER_SET ( qualifiedTypeRef , mDot , memberReferenceExpression - > mDotToken ) ;
if ( memberReferenceExpression - > mMemberName ! = NULL )
{
MoveNode ( memberReferenceExpression - > mMemberName , memberReferenceExpression ) ;
auto rightTypeRef = DoCreateTypeRef ( memberReferenceExpression - > mMemberName ) ;
MEMBER_SET ( qualifiedTypeRef , mRight , rightTypeRef ) ;
}
firstNode = qualifiedTypeRef ;
}
else
{
bool isHandled = false ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( firstNode ) ;
if ( tokenNode ! = NULL )
{
int token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_Dot )
{
auto dotTypeRef = mAlloc - > Alloc < BfDotTypeReference > ( ) ;
ReplaceNode ( firstNode , dotTypeRef ) ;
dotTypeRef - > mDotToken = tokenNode ;
firstNode = dotTypeRef ;
isHandled = true ;
//return dotTypeRef;
}
else if ( ( token = = BfToken_Star ) & & ( mAllowTypeWildcard ) )
{
auto wildcardTypeRef = mAlloc - > Alloc < BfWildcardTypeReference > ( ) ;
ReplaceNode ( firstNode , wildcardTypeRef ) ;
wildcardTypeRef - > mWildcardToken = tokenNode ;
return wildcardTypeRef ;
}
else if ( ( token = = BfToken_Var ) | | ( token = = BfToken_Let ) )
{
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( ( nextToken - > GetToken ( ) = = BfToken_Ref ) | | ( nextToken - > GetToken ( ) = = BfToken_Mut ) )
{
auto varTypeRef = mAlloc - > Alloc < BfVarRefTypeReference > ( ) ;
ReplaceNode ( firstNode , varTypeRef ) ;
varTypeRef - > mVarToken = tokenNode ;
MEMBER_SET ( varTypeRef , mRefToken , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
return varTypeRef ;
}
}
if ( token = = BfToken_Var )
{
auto varTypeRef = mAlloc - > Alloc < BfVarTypeReference > ( ) ;
ReplaceNode ( firstNode , varTypeRef ) ;
varTypeRef - > mVarToken = tokenNode ;
return varTypeRef ;
}
else
{
auto letTypeRef = mAlloc - > Alloc < BfLetTypeReference > ( ) ;
ReplaceNode ( firstNode , letTypeRef ) ;
letTypeRef - > mLetToken = tokenNode ;
return letTypeRef ;
}
}
else if ( ( mCompatMode ) & & ( token = = BfToken_Minus ) )
{
auto constExpr = CreateExpression ( tokenNode , CreateExprFlags_BreakOnRChevron ) ;
auto constTypeRef = mAlloc - > Alloc < BfConstExprTypeRef > ( ) ;
ReplaceNode ( firstNode , constTypeRef ) ;
MEMBER_SET_CHECKED ( constTypeRef , mConstExpr , constExpr ) ;
return constTypeRef ;
}
else if ( token = = BfToken_Const )
{
if ( ! mCompatMode )
{
//Fail("Invalid use of 'const', only fields and local variables can be declared as const", tokenNode);
//AddErrorNode(tokenNode);
auto constExpr = CreateExpressionAfter ( tokenNode , CreateExprFlags_BreakOnRChevron ) ;
auto constTypeRef = mAlloc - > Alloc < BfConstExprTypeRef > ( ) ;
ReplaceNode ( firstNode , constTypeRef ) ;
MEMBER_SET ( constTypeRef , mConstToken , tokenNode ) ;
MEMBER_SET_CHECKED ( constTypeRef , mConstExpr , constExpr ) ;
return constTypeRef ;
}
else
{
auto elementType = CreateTypeRefAfter ( tokenNode , parseArrayBracket ) ;
auto constTypeRef = mAlloc - > Alloc < BfConstTypeRef > ( ) ;
ReplaceNode ( firstNode , constTypeRef ) ;
MEMBER_SET ( constTypeRef , mConstToken , tokenNode ) ;
MEMBER_SET_CHECKED ( constTypeRef , mElementType , elementType ) ;
return constTypeRef ;
}
}
else if ( token = = BfToken_Unsigned )
{
BF_ASSERT ( mCompatMode ) ;
auto elementType = CreateTypeRefAfter ( tokenNode , parseArrayBracket ) ;
BfTypeReference * rootElementParent = NULL ;
auto rootElement = elementType ;
while ( auto elementedType = BfNodeDynCast < BfElementedTypeRef > ( rootElement ) )
{
rootElementParent = rootElement ;
rootElement = elementedType - > mElementType ;
}
auto unsignedTypeRef = mAlloc - > Alloc < BfUnsignedTypeRef > ( ) ;
ReplaceNode ( firstNode , unsignedTypeRef ) ;
MEMBER_SET ( unsignedTypeRef , mUnsignedToken , tokenNode ) ;
if ( rootElement = = elementType )
{
MEMBER_SET_CHECKED ( unsignedTypeRef , mElementType , elementType ) ;
return unsignedTypeRef ;
}
else
{
# ifdef BF_AST_HAS_PARENT_MEMBER
BF_ASSERT ( rootElementParent = = rootElement - > mParent ) ;
# endif
auto elementedType = BfNodeDynCast < BfElementedTypeRef > ( rootElementParent ) ;
MEMBER_SET_CHECKED ( unsignedTypeRef , mElementType , rootElement ) ;
MEMBER_SET_CHECKED ( elementedType , mElementType , unsignedTypeRef ) ;
elementType - > SetSrcStart ( unsignedTypeRef - > GetSrcStart ( ) ) ;
return elementType ;
}
}
else if ( token = = BfToken_RetType )
{
auto retTypeTypeRef = mAlloc - > Alloc < BfRetTypeTypeRef > ( ) ;
ReplaceNode ( firstNode , retTypeTypeRef ) ;
MEMBER_SET ( retTypeTypeRef , mRetTypeToken , tokenNode ) ;
tokenNode = ExpectTokenAfter ( retTypeTypeRef , BfToken_LParen ) ;
MEMBER_SET_CHECKED ( retTypeTypeRef , mOpenParen , tokenNode ) ;
auto elementType = CreateTypeRefAfter ( retTypeTypeRef , parseArrayBracket ) ;
MEMBER_SET_CHECKED ( retTypeTypeRef , mElementType , elementType ) ;
tokenNode = ExpectTokenAfter ( retTypeTypeRef , BfToken_RParen ) ;
MEMBER_SET_CHECKED ( retTypeTypeRef , mCloseParen , tokenNode ) ;
return retTypeTypeRef ;
}
else if ( ( token = = BfToken_Delegate ) | | ( token = = BfToken_Function ) )
{
auto delegateTypeRef = mAlloc - > Alloc < BfDelegateTypeRef > ( ) ;
ReplaceNode ( firstNode , delegateTypeRef ) ;
MEMBER_SET ( delegateTypeRef , mTypeToken , tokenNode ) ;
auto returnType = CreateTypeRefAfter ( delegateTypeRef ) ;
MEMBER_SET_CHECKED ( delegateTypeRef , mReturnType , returnType ) ;
tokenNode = ExpectTokenAfter ( delegateTypeRef , BfToken_LParen ) ;
MEMBER_SET_CHECKED ( delegateTypeRef , mOpenParen , tokenNode ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( delegateTypeRef - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( delegateTypeRef - > mCommas , mAlloc ) ;
auto closeNode = ParseMethodParams ( delegateTypeRef , & params , & commas , BfToken_RParen ) ;
if ( closeNode = = NULL )
{
if ( ! params . empty ( ) )
delegateTypeRef - > AdjustSrcEnd ( params . back ( ) ) ;
if ( ! commas . empty ( ) )
delegateTypeRef - > AdjustSrcEnd ( commas . back ( ) ) ;
}
MEMBER_SET_CHECKED ( delegateTypeRef , mCloseParen , closeNode ) ;
mVisitorPos . MoveNext ( ) ;
return delegateTypeRef ;
}
else if ( token = = BfToken_Decltype )
{
auto declTypeRef = mAlloc - > Alloc < BfDeclTypeRef > ( ) ;
ReplaceNode ( tokenNode , declTypeRef ) ;
declTypeRef - > mToken = tokenNode ;
tokenNode = ExpectTokenAfter ( declTypeRef , BfToken_LParen ) ;
MEMBER_SET_CHECKED ( declTypeRef , mOpenParen , tokenNode ) ;
auto targetExpr = CreateExpressionAfter ( declTypeRef ) ;
MEMBER_SET_CHECKED ( declTypeRef , mTarget , targetExpr ) ;
tokenNode = ExpectTokenAfter ( declTypeRef , BfToken_RParen ) ;
MEMBER_SET_CHECKED ( declTypeRef , mCloseParen , tokenNode ) ;
return declTypeRef ;
}
else if ( token = = BfToken_LParen )
{
auto tupleTypeRef = mAlloc - > Alloc < BfTupleTypeRef > ( ) ;
BfDeferredAstSizedArray < BfTypeReference * > fieldTypes ( tupleTypeRef - > mFieldTypes , mAlloc ) ;
BfDeferredAstSizedArray < BfIdentifierNode * > fieldNames ( tupleTypeRef - > mFieldNames , mAlloc ) ;
BfDeferredAstSizedArray < BfAstNode * > commas ( tupleTypeRef - > mCommas , mAlloc ) ;
ReplaceNode ( firstNode , tupleTypeRef ) ;
tupleTypeRef - > mOpenParen = tokenNode ;
while ( true )
{
auto tupleFieldType = CreateTypeRefAfter ( tupleTypeRef ) ;
if ( tupleFieldType = = NULL )
return tupleTypeRef ;
fieldTypes . push_back ( tupleFieldType ) ;
MoveNode ( tupleFieldType , tupleTypeRef ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto identifierNode = BfNodeDynCast < BfIdentifierNode > ( nextNode ) )
{
while ( fieldNames . size ( ) < fieldTypes . size ( ) - 1 )
fieldNames . push_back ( NULL ) ;
MoveNode ( identifierNode , tupleTypeRef ) ;
fieldNames . push_back ( identifierNode ) ;
mVisitorPos . MoveNext ( ) ;
}
auto tokenNode = ExpectTokenAfter ( tupleTypeRef , BfToken_Comma , BfToken_RParen ) ;
if ( tokenNode = = NULL )
return tupleTypeRef ;
if ( tokenNode - > GetToken ( ) = = BfToken_RParen )
{
MEMBER_SET ( tupleTypeRef , mCloseParen , tokenNode ) ;
//return tupleTypeRef;
firstNode = tupleTypeRef ;
isHandled = true ;
break ;
}
MoveNode ( tokenNode , tupleTypeRef ) ;
commas . push_back ( tokenNode ) ;
}
}
}
else if ( mCompatMode )
{
if ( auto literalExpr = BfNodeDynCast < BfLiteralExpression > ( firstNode ) )
{
auto constExpr = CreateExpression ( literalExpr , CreateExprFlags_BreakOnRChevron ) ;
auto constTypeRef = mAlloc - > Alloc < BfConstExprTypeRef > ( ) ;
ReplaceNode ( firstNode , constTypeRef ) ;
MEMBER_SET_CHECKED ( constTypeRef , mConstExpr , constExpr ) ;
return constTypeRef ;
}
}
if ( ! isHandled )
{
Fail ( " Expected type " , firstNode ) ;
return NULL ;
}
}
}
BfTypeReference * typeRef = BfNodeDynCast < BfTypeReference > ( firstNode ) ;
if ( typeRef = = NULL )
{
typeRef = DoCreateNamedTypeRef ( identifierNode ) ;
}
while ( true )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode ! = NULL )
{
BfToken token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_Dot )
{
BfQualifiedTypeReference * qualifiedTypeRef = mAlloc - > Alloc < BfQualifiedTypeReference > ( ) ;
ReplaceNode ( typeRef , qualifiedTypeRef ) ;
qualifiedTypeRef - > mLeft = typeRef ;
MEMBER_SET ( qualifiedTypeRef , mDot , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
while ( true )
{
bool handled = false ;
if ( mAllowTypeWildcard )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto nextTokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( nextTokenNode - > mToken = = BfToken_Star )
{
auto wildcardTypeRef = mAlloc - > Alloc < BfWildcardTypeReference > ( ) ;
ReplaceNode ( nextTokenNode , wildcardTypeRef ) ;
wildcardTypeRef - > mWildcardToken = nextTokenNode ;
typeRef = wildcardTypeRef ;
handled = true ;
mVisitorPos . MoveNext ( ) ;
}
}
}
if ( ! handled )
{
auto rightIdentifer = ExpectIdentifierAfter ( qualifiedTypeRef ) ;
if ( rightIdentifer = = NULL )
return qualifiedTypeRef ;
auto namedTypeRef = mAlloc - > Alloc < BfNamedTypeReference > ( ) ;
namedTypeRef - > mNameNode = rightIdentifer ;
ReplaceNode ( rightIdentifer , namedTypeRef ) ;
namedTypeRef - > SetTriviaStart ( rightIdentifer - > GetTriviaStart ( ) ) ;
typeRef = namedTypeRef ;
}
MEMBER_SET ( qualifiedTypeRef , mRight , typeRef ) ;
nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_Dot )
{
BfQualifiedTypeReference * outerQualifiedTypeRef = mAlloc - > Alloc < BfQualifiedTypeReference > ( ) ;
ReplaceNode ( qualifiedTypeRef , outerQualifiedTypeRef ) ;
outerQualifiedTypeRef - > mLeft = qualifiedTypeRef ;
MEMBER_SET ( outerQualifiedTypeRef , mDot , tokenNode ) ;
qualifiedTypeRef = outerQualifiedTypeRef ;
mVisitorPos . MoveNext ( ) ;
}
else
break ;
}
else
{
break ;
}
}
typeRef = qualifiedTypeRef ;
}
else if ( token = = BfToken_Star )
{
auto ptrType = mAlloc - > Alloc < BfPointerTypeRef > ( ) ;
ReplaceNode ( typeRef , ptrType ) ;
ptrType - > mElementType = typeRef ;
MEMBER_SET ( ptrType , mStarNode , tokenNode ) ;
typeRef = ptrType ;
mVisitorPos . MoveNext ( ) ;
}
else if ( ( token = = BfToken_Question ) | | ( token = = BfToken_QuestionLBracket ) )
{
if ( token = = BfToken_QuestionLBracket )
tokenNode = BreakQuestionLBracket ( tokenNode ) ;
else
mVisitorPos . MoveNext ( ) ;
auto nullableType = mAlloc - > Alloc < BfNullableTypeRef > ( ) ;
ReplaceNode ( typeRef , nullableType ) ;
nullableType - > mElementType = typeRef ;
MEMBER_SET ( nullableType , mQuestionToken , tokenNode ) ;
typeRef = nullableType ;
}
else if ( token = = BfToken_LBracket )
{
if ( ! parseArrayBracket )
return typeRef ;
auto arrayType = mAlloc - > Alloc < BfArrayTypeRef > ( ) ;
auto newArrayType = arrayType ;
ReplaceNode ( typeRef , arrayType ) ;
arrayType - > mOpenBracket = tokenNode ;
MoveNode ( tokenNode , arrayType ) ;
arrayType - > mDimensions = 1 ;
arrayType - > mElementType = typeRef ;
mVisitorPos . MoveNext ( ) ;
while ( true )
{
auto prevArrayType = BfNodeDynCast < BfArrayTypeRef > ( arrayType - > mElementType ) ;
if ( prevArrayType = = NULL )
break ;
std : : swap ( prevArrayType - > mOpenBracket , arrayType - > mOpenBracket ) ;
std : : swap ( prevArrayType - > mParams , arrayType - > mParams ) ;
std : : swap ( prevArrayType - > mCloseBracket , arrayType - > mCloseBracket ) ;
std : : swap ( prevArrayType - > mDimensions , arrayType - > mDimensions ) ;
prevArrayType - > SetSrcEnd ( arrayType - > GetSrcEnd ( ) ) ;
arrayType = prevArrayType ;
}
BF_ASSERT ( arrayType - > mParams . mVals = = NULL ) ;
arrayType - > mParams . mSize = 0 ;
BfDeferredAstSizedArray < BfAstNode * > params ( arrayType - > mParams , mAlloc ) ;
bool hasFailed = false ;
bool isSized = false ;
while ( true )
{
nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode ! = NULL )
{
if ( tokenNode - > GetToken ( ) = = BfToken_Comma )
{
MoveNode ( tokenNode , arrayType ) ;
mVisitorPos . MoveNext ( ) ;
arrayType - > mDimensions + + ;
params . push_back ( tokenNode ) ;
}
else if ( tokenNode - > GetToken ( ) = = BfToken_RBracket )
{
MoveNode ( tokenNode , arrayType ) ;
mVisitorPos . MoveNext ( ) ;
arrayType - > mCloseBracket = tokenNode ;
break ;
}
else
tokenNode = NULL ;
}
if ( tokenNode = = NULL )
{
BfExpression * sizeExpr = CreateExpressionAfter ( arrayType ) ;
if ( sizeExpr = = NULL )
{
hasFailed = true ;
break ;
}
MoveNode ( sizeExpr , arrayType ) ;
params . push_back ( sizeExpr ) ;
// if (params.size() == 0)
// {
// BfExpression* sizeExpr = CreateExpressionAfter(arrayType);
// if (sizeExpr == NULL)
// {
// hasFailed = true;
// break;
// }
// MoveNode(sizeExpr, arrayType);
// params.push_back(sizeExpr);
// tokenNode = ExpectTokenAfter(arrayType, BfToken_RBracket);
// if (tokenNode == NULL)
// {
// hasFailed = true;
// break;
// }
// MoveNode(tokenNode, arrayType);
// arrayType->mCloseBracket = tokenNode;
// break;
// }
// else
// {
// FailAfter("Either ',' or ']' expected", arrayType);
// return arrayType;
// }
}
}
newArrayType - > SetSrcEnd ( arrayType - > GetSrcEnd ( ) ) ;
if ( hasFailed )
return newArrayType ;
typeRef = newArrayType ;
}
else if ( token = = BfToken_LChevron )
{
auto genericInstance = mAlloc - > Alloc < BfGenericInstanceTypeRef > ( ) ;
BfDeferredSizedArray < BfTypeReference * > genericArguments ( genericInstance - > mGenericArguments , mAlloc ) ;
BfDeferredAstSizedArray < BfAstNode * > commas ( genericInstance - > mCommas , mAlloc ) ;
ReplaceNode ( typeRef , genericInstance ) ;
genericInstance - > mOpenChevron = tokenNode ;
MoveNode ( tokenNode , genericInstance ) ;
genericInstance - > mElementType = typeRef ;
mVisitorPos . MoveNext ( ) ;
bool isBoundName = false ;
bool isUnboundName = false ;
while ( true )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
auto genericIdentifier = BfNodeDynCast < BfIdentifierNode > ( nextNode ) ;
bool doAddType = genericIdentifier ! = NULL ;
if ( mCompatMode )
{
if ( BfNodeDynCast < BfLiteralExpression > ( nextNode ) ! = NULL )
doAddType = true ;
}
if ( genericIdentifier = = NULL )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
BfToken token = BfToken_None ;
if ( tokenNode ! = NULL )
token = tokenNode - > GetToken ( ) ;
if ( ( tokenNode ! = NULL ) & &
( ( token = = BfToken_Const ) | |
( token = = BfToken_Ref ) | |
( token = = BfToken_Mut ) | |
( token = = BfToken_LParen ) | |
( token = = BfToken_Delegate ) | |
( token = = BfToken_Function ) | |
( token = = BfToken_Decltype ) | |
( ( token = = BfToken_Star ) & & ( mAllowTypeWildcard ) ) ) )
doAddType = true ;
}
if ( ( ! doAddType ) & & ( isBoundName ) )
{
mPassInstance - > FailAfter ( " Expected type " , genericInstance ) ;
}
if ( ( doAddType ) & & ( ! isUnboundName ) )
{
auto genericArgumentTypeRef = CreateTypeRefAfter ( genericInstance ) ;
if ( genericArgumentTypeRef = = NULL )
return NULL ;
MoveNode ( genericArgumentTypeRef , genericInstance ) ;
genericArguments . push_back ( genericArgumentTypeRef ) ;
isBoundName = true ;
}
else
isUnboundName = true ;
nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode = = NULL )
{
FailAfter ( " Expected ',' or '>' " , genericInstance ) ;
return genericInstance ;
}
token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_RDblChevron )
{
tokenNode = BreakDoubleChevron ( tokenNode ) ;
token = tokenNode - > GetToken ( ) ;
}
else
{
mVisitorPos . MoveNext ( ) ;
}
if ( token = = BfToken_RChevron )
{
MoveNode ( tokenNode , genericInstance ) ;
genericInstance - > mCloseChevron = tokenNode ;
break ;
}
if ( token ! = BfToken_Comma )
{
Fail ( " Either ',' or '>' expected " , tokenNode ) ;
mVisitorPos . mReadPos - - ;
//AddErrorNode(tokenNode);
return genericInstance ;
}
MoveNode ( tokenNode , genericInstance ) ;
commas . push_back ( tokenNode ) ;
}
typeRef = genericInstance ;
}
else
break ;
}
else
break ;
}
return typeRef ;
}
BfTypeReference * BfReducer : : CreateTypeRef ( BfAstNode * firstNode , bool parseArrayBracket )
{
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( firstNode ) )
{
BfToken token = tokenNode - > GetToken ( ) ;
if ( ( token = = BfToken_Ref ) | | ( token = = BfToken_Mut ) )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
mVisitorPos . MoveNext ( ) ;
auto typeRef = DoCreateTypeRef ( nextNode , parseArrayBracket ) ;
if ( typeRef = = NULL )
{
mVisitorPos . mReadPos - - ;
AddErrorNode ( tokenNode ) ;
return NULL ;
}
return CreateRefTypeRef ( typeRef , tokenNode ) ;
}
else if ( ( token = = BfToken_In ) | | ( token = = BfToken_As ) )
{
// This is mostly to allow a partially typed 'int' to be parsed as 'in' to make autocomplete nicer
return CreateTypeRef ( ReplaceTokenStarter ( firstNode ) , parseArrayBracket ) ;
}
}
return DoCreateTypeRef ( firstNode , parseArrayBracket ) ;
}
BfTypeReference * BfReducer : : CreateTypeRefAfter ( BfAstNode * astNode , bool parseArrayBracket )
{
AssertCurrentNode ( astNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode = = NULL )
{
FailAfter ( " Expected type " , astNode ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
int startPos = mVisitorPos . mReadPos ;
BfTypeReference * typeRef = CreateTypeRef ( nextNode , parseArrayBracket ) ;
if ( typeRef = = NULL )
{
BF_ASSERT ( mVisitorPos . mReadPos = = startPos ) ;
mVisitorPos . mReadPos - - ;
}
return typeRef ;
}
BfTypeReference * BfReducer : : CreateRefTypeRef ( BfTypeReference * elementType , BfTokenNode * refTokenNode )
{
BfToken refToken = refTokenNode - > GetToken ( ) ;
BF_ASSERT ( ( refToken = = BfToken_Ref ) | | ( refToken = = BfToken_Mut ) | | ( refToken = = BfToken_Out ) ) ;
if ( elementType - > IsA < BfRefTypeRef > ( ) )
{
Fail ( " Multiple ref levels are not allowed " , refTokenNode ) ;
AddErrorNode ( refTokenNode ) ;
return elementType ;
}
if ( elementType - > IsA < BfConstTypeRef > ( ) )
{
Fail ( " Refs to const values are not allowed " , refTokenNode ) ;
AddErrorNode ( refTokenNode ) ;
return elementType ;
}
auto refTypeRef = mAlloc - > Alloc < BfRefTypeRef > ( ) ;
MEMBER_SET ( refTypeRef , mRefToken , refTokenNode ) ;
ReplaceNode ( elementType , refTypeRef ) ;
refTypeRef - > mElementType = elementType ;
return refTypeRef ;
}
BfIdentifierNode * BfReducer : : CompactQualifiedName ( BfAstNode * leftNode )
{
AssertCurrentNode ( leftNode ) ;
if ( ( leftNode = = NULL ) | | ( ! leftNode - > IsA < BfIdentifierNode > ( ) ) )
return NULL ;
auto prevNode = mVisitorPos . Get ( mVisitorPos . mWritePos - 1 ) ;
auto leftIdentifier = ( BfIdentifierNode * ) leftNode ;
while ( true )
{
auto nextToken = mVisitorPos . Get ( mVisitorPos . mReadPos + 1 ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextToken ) ;
if ( ( tokenNode = = NULL ) | | ( ( tokenNode - > GetToken ( ) ! = BfToken_Dot ) /*&& (tokenNode->GetToken() != BfToken_QuestionDot)*/ ) )
return leftIdentifier ;
auto nextNextToken = mVisitorPos . Get ( mVisitorPos . mReadPos + 2 ) ;
auto rightIdentifier = BfNodeDynCast < BfIdentifierNode > ( nextNextToken ) ;
if ( rightIdentifier = = NULL )
return leftIdentifier ;
// If the previous dotted span failed (IE: had chevrons) then don't insert qualified names in the middle of it
auto prevNodeToken = BfNodeDynCast < BfTokenNode > ( prevNode ) ;
if ( ( prevNodeToken ! = NULL ) & & ( ( prevNodeToken - > GetToken ( ) = = BfToken_Dot ) | | ( prevNodeToken - > GetToken ( ) = = BfToken_QuestionDot ) ) )
return leftIdentifier ;
mVisitorPos . MoveNext ( ) ; // past .
mVisitorPos . MoveNext ( ) ; // past right
auto qualifiedNameNode = mAlloc - > Alloc < BfQualifiedNameNode > ( ) ;
ReplaceNode ( leftIdentifier , qualifiedNameNode ) ;
qualifiedNameNode - > mLeft = leftIdentifier ;
MEMBER_SET ( qualifiedNameNode , mDot , tokenNode ) ;
MEMBER_SET ( qualifiedNameNode , mRight , rightIdentifier ) ;
leftIdentifier = qualifiedNameNode ;
prevNode = NULL ;
}
return leftIdentifier ;
}
void BfReducer : : CreateQualifiedNames ( BfAstNode * node )
{
auto block = BfNodeDynCast < BfBlock > ( node ) ;
if ( block = = NULL )
return ;
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( block ) ) ;
bool isDone = ! mVisitorPos . MoveNext ( ) ;
while ( ! isDone )
{
auto child = mVisitorPos . GetCurrent ( ) ;
BfAstNode * newNode = CompactQualifiedName ( child ) ;
if ( newNode = = NULL )
newNode = child ;
CreateQualifiedNames ( child ) ;
isDone = ! mVisitorPos . MoveNext ( ) ;
if ( newNode ! = NULL )
mVisitorPos . Write ( newNode ) ;
}
mVisitorPos . Trim ( ) ;
}
BfAttributeDirective * BfReducer : : CreateAttributeDirective ( BfTokenNode * startToken )
{
BfAttributeDirective * attributeDirective = mAlloc - > Alloc < BfAttributeDirective > ( ) ;
BfDeferredAstSizedArray < BfExpression * > arguments ( attributeDirective - > mArguments , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( attributeDirective - > mCommas , mAlloc ) ;
ReplaceNode ( startToken , attributeDirective ) ;
attributeDirective - > mAttrOpenToken = startToken ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode ! = NULL )
{
if ( tokenNode - > GetToken ( ) = = BfToken_Return )
{
auto attributeTargetSpecifier = mAlloc - > Alloc < BfAttributeTargetSpecifier > ( ) ;
ReplaceNode ( tokenNode , attributeTargetSpecifier ) ;
MEMBER_SET ( attributeDirective , mAttributeTargetSpecifier , attributeTargetSpecifier ) ;
attributeDirective - > mAttributeTargetSpecifier - > mTargetToken = tokenNode ;
mVisitorPos . MoveNext ( ) ;
tokenNode = ExpectTokenAfter ( attributeDirective , BfToken_Colon ) ;
if ( tokenNode ! = NULL )
MEMBER_SET ( attributeDirective - > mAttributeTargetSpecifier , mColonToken , tokenNode ) ;
attributeDirective - > SetSrcEnd ( attributeDirective - > mAttributeTargetSpecifier - > GetSrcEnd ( ) ) ;
}
}
auto typeRef = CreateTypeRefAfter ( attributeDirective ) ;
if ( typeRef = = NULL )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( BfTokenNode * endToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( endToken - > GetToken ( ) = = BfToken_RBracket )
{
mVisitorPos . MoveNext ( ) ;
MEMBER_SET ( attributeDirective , mCtorCloseParen , endToken ) ;
return attributeDirective ;
}
}
return attributeDirective ;
}
MEMBER_SET ( attributeDirective , mAttributeTypeRef , typeRef ) ;
tokenNode = ExpectTokenAfter ( attributeDirective , BfToken_LParen , BfToken_RBracket , BfToken_Comma ) ;
if ( tokenNode = = NULL )
return attributeDirective ;
if ( tokenNode - > GetToken ( ) = = BfToken_LParen )
{
MEMBER_SET ( attributeDirective , mCtorOpenParen , tokenNode ) ;
tokenNode = ReadArguments ( attributeDirective , attributeDirective , & arguments , & commas , BfToken_RParen , false ) ;
if ( tokenNode = = NULL )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_RBracket ) )
goto Do_RBracket ;
return attributeDirective ;
}
MEMBER_SET ( attributeDirective , mCtorCloseParen , tokenNode ) ;
tokenNode = ExpectTokenAfter ( attributeDirective , BfToken_RBracket , BfToken_Comma ) ;
if ( tokenNode = = NULL )
return attributeDirective ;
}
Do_RBracket :
if ( tokenNode - > GetToken ( ) = = BfToken_RBracket )
{
MEMBER_SET ( attributeDirective , mAttrCloseToken , tokenNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( tokenNode = = NULL ) | | ( tokenNode - > GetToken ( ) ! = BfToken_LBracket ) )
return attributeDirective ;
mVisitorPos . MoveNext ( ) ;
}
// Has another one- chain it
//mVisitorPos.MoveNext();
auto nextAttribute = CreateAttributeDirective ( tokenNode ) ;
if ( nextAttribute ! = NULL )
{
MEMBER_SET ( attributeDirective , mNextAttribute , nextAttribute ) ;
}
return attributeDirective ;
}
BfExpression * BfReducer : : CreateAttributedExpression ( BfTokenNode * tokenNode , bool onlyAllowIdentifier )
{
auto attrib = CreateAttributeDirective ( tokenNode ) ;
if ( attrib = = NULL )
return NULL ;
if ( ! onlyAllowIdentifier )
{
auto expr = CreateExpressionAfter ( attrib ) ;
if ( expr ! = NULL )
{
if ( auto identifier = BfNodeDynCast < BfIdentifierNode > ( expr ) )
{
auto attrIdentifier = mAlloc - > Alloc < BfAttributedIdentifierNode > ( ) ;
ReplaceNode ( attrib , attrIdentifier ) ;
attrIdentifier - > mAttributes = attrib ;
MEMBER_SET ( attrIdentifier , mIdentifier , identifier ) ;
return attrIdentifier ;
}
if ( ( expr - > IsA < BfObjectCreateExpression > ( ) ) | |
( expr - > IsA < BfInvocationExpression > ( ) ) | |
( expr - > IsA < BfVariableDeclaration > ( ) ) )
{
BfAttributedExpression * attribExpr = mAlloc - > Alloc < BfAttributedExpression > ( ) ;
ReplaceNode ( attrib , attribExpr ) ;
attribExpr - > mAttributes = attrib ;
MEMBER_SET ( attribExpr , mExpression , expr ) ;
return attribExpr ;
}
}
Fail ( " Prefixed attributes can only be used on constructor calls, invocations, or variable declarations " , attrib ) ;
BfAttributedExpression * attribExpr = mAlloc - > Alloc < BfAttributedExpression > ( ) ;
ReplaceNode ( attrib , attribExpr ) ;
attribExpr - > mAttributes = attrib ;
if ( expr ! = NULL )
MEMBER_SET ( attribExpr , mExpression , expr ) ;
return attribExpr ;
}
auto attrIdentifier = mAlloc - > Alloc < BfAttributedIdentifierNode > ( ) ;
ReplaceNode ( attrib , attrIdentifier ) ;
attrIdentifier - > mAttributes = attrib ;
auto identifier = ExpectIdentifierAfter ( attrib ) ;
if ( identifier ! = NULL )
{
MEMBER_SET ( attrIdentifier , mIdentifier , identifier ) ;
}
return attrIdentifier ;
}
BfTokenNode * BfReducer : : ReadArguments ( BfAstNode * parentNode , BfAstNode * afterNode , SizedArrayImpl < BfExpression * > * arguments , SizedArrayImpl < BfTokenNode * > * commas , BfToken endToken , bool allowSkippedArgs , CreateExprFlags createExprFlags )
{
for ( int paramIdx = 0 ; true ; paramIdx + + )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( ( nextNode = = NULL ) & & ( endToken = = BfToken_None ) )
return NULL ;
BfTokenNode * tokenNode = BfNodeDynCastExact < BfTokenNode > ( nextNode ) ;
if ( tokenNode ! = NULL )
{
if ( tokenNode - > GetToken ( ) = = endToken )
{
MoveNode ( tokenNode , parentNode ) ;
mVisitorPos . MoveNext ( ) ;
return tokenNode ;
}
if ( paramIdx > 0 )
{
if ( tokenNode - > GetToken ( ) ! = BfToken_Comma )
{
Fail ( " Expected comma " , tokenNode ) ;
return NULL ;
}
commas - > push_back ( tokenNode ) ;
MoveNode ( tokenNode , parentNode ) ;
mVisitorPos . MoveNext ( ) ;
}
}
else
{
if ( paramIdx > 0 )
{
FailAfter ( " Expected comma " , afterNode ) ;
return NULL ;
}
}
if ( allowSkippedArgs )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( ( nextNode = = NULL ) & & ( endToken = = BfToken_None ) )
return NULL ;
if ( auto nextToken = BfNodeDynCastExact < BfTokenNode > ( nextNode ) )
{
if ( nextToken - > GetToken ( ) = = endToken )
continue ;
if ( nextToken - > GetToken ( ) = = BfToken_Comma )
{
arguments - > push_back ( NULL ) ;
continue ;
}
}
}
auto argumentExpr = CreateExpressionAfter ( afterNode , CreateExprFlags_AllowVariableDecl ) ;
if ( ( argumentExpr ! = NULL ) | | ( endToken ! = BfToken_None ) )
arguments - > push_back ( argumentExpr ) ;
if ( argumentExpr = = NULL )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto tokenNode = BfNodeDynCastExact < BfTokenNode > ( nextNode ) )
{
// Try to continue with param list even after an error
if ( ( tokenNode - > GetToken ( ) = = BfToken_Comma ) | | ( tokenNode - > GetToken ( ) = = endToken ) )
continue ;
}
return NULL ;
}
MoveNode ( argumentExpr , parentNode ) ;
afterNode = parentNode ;
}
}
BfIdentifierNode * BfReducer : : ExtractExplicitInterfaceRef ( BfAstNode * memberDeclaration , BfIdentifierNode * nameIdentifier , BfTypeReference * * outExplicitInterface , BfTokenNode * * outExplicitInterfaceDotToken )
{
int dotTokenIdx = - 1 ;
if ( auto qualifiedName = BfNodeDynCast < BfQualifiedNameNode > ( nameIdentifier ) )
{
MoveNode ( qualifiedName , memberDeclaration ) ;
MoveNode ( qualifiedName - > mDot , memberDeclaration ) ;
* outExplicitInterfaceDotToken = qualifiedName - > mDot ;
auto explicitInterfaceRef = CreateTypeRef ( qualifiedName - > mLeft ) ;
BF_ASSERT ( explicitInterfaceRef ! = NULL ) ;
MoveNode ( explicitInterfaceRef , memberDeclaration ) ;
* outExplicitInterface = explicitInterfaceRef ;
return qualifiedName - > mRight ;
}
else if ( IsTypeReference ( nameIdentifier , BfToken_Dot , & dotTokenIdx ) )
{
BfAstNode * dotToken = mVisitorPos . Get ( dotTokenIdx ) ;
MoveNode ( dotToken , memberDeclaration ) ;
* outExplicitInterfaceDotToken = ( BfTokenNode * ) dotToken ;
auto explicitInterfaceRef = CreateTypeRef ( nameIdentifier ) ;
BF_ASSERT ( explicitInterfaceRef ! = NULL ) ;
MoveNode ( explicitInterfaceRef , memberDeclaration ) ;
* outExplicitInterface = explicitInterfaceRef ;
return ExpectIdentifierAfter ( memberDeclaration ) ;
}
return nameIdentifier ;
}
BfFieldDtorDeclaration * BfReducer : : CreateFieldDtorDeclaration ( BfAstNode * srcNode )
{
BfFieldDtorDeclaration * firstFieldDtor = NULL ;
BfFieldDtorDeclaration * prevFieldDtor = NULL ;
auto nextNode = mVisitorPos . GetNext ( ) ;
while ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( nextToken - > GetToken ( ) ! = BfToken_Tilde )
break ;
auto fieldDtor = mAlloc - > Alloc < BfFieldDtorDeclaration > ( ) ;
ReplaceNode ( nextToken , fieldDtor ) ;
fieldDtor - > mTildeToken = nextToken ;
//int prevReadPos = mVisitorPos.mReadPos;
mVisitorPos . MoveNext ( ) ;
if ( prevFieldDtor ! = NULL )
{
MEMBER_SET ( prevFieldDtor , mNextFieldDtor , fieldDtor ) ;
}
else
{
firstFieldDtor = fieldDtor ;
MoveNode ( fieldDtor , srcNode ) ;
}
auto statement = CreateStatementAfter ( srcNode ) ;
if ( statement = = NULL )
{
//mVisitorPos.mReadPos = prevReadPos;
break ;
}
MEMBER_SET ( fieldDtor , mBody , statement ) ;
fieldDtor - > SetSrcEnd ( statement - > GetSrcEnd ( ) ) ;
prevFieldDtor = fieldDtor ;
srcNode - > SetSrcEnd ( fieldDtor - > GetSrcEnd ( ) ) ;
nextNode = mVisitorPos . GetNext ( ) ;
// We used to NOT have this break here. Why were we allowing multiple ~'s when a block statement would have made more sense?
break ; // Wh
}
return firstFieldDtor ;
}
BfFieldDeclaration * BfReducer : : CreateFieldDeclaration ( BfTokenNode * tokenNode , BfTypeReference * typeRef , BfIdentifierNode * nameIdentifier , BfFieldDeclaration * prevFieldDeclaration )
{
auto fieldDeclaration = mAlloc - > Alloc < BfFieldDeclaration > ( ) ;
if ( prevFieldDeclaration ! = NULL )
{
ReplaceNode ( tokenNode , fieldDeclaration ) ;
MEMBER_SET ( fieldDeclaration , mPrecedingComma , tokenNode ) ;
MEMBER_SET ( fieldDeclaration , mNameNode , nameIdentifier ) ;
fieldDeclaration - > mDocumentation = prevFieldDeclaration - > mDocumentation ;
fieldDeclaration - > mAttributes = prevFieldDeclaration - > mAttributes ;
fieldDeclaration - > mInternalSpecifier = prevFieldDeclaration - > mInternalSpecifier ;
fieldDeclaration - > mProtectionSpecifier = prevFieldDeclaration - > mProtectionSpecifier ;
fieldDeclaration - > mStaticSpecifier = prevFieldDeclaration - > mStaticSpecifier ;
fieldDeclaration - > mTypeRef = prevFieldDeclaration - > mTypeRef ;
fieldDeclaration - > mConstSpecifier = prevFieldDeclaration - > mConstSpecifier ;
fieldDeclaration - > mReadOnlySpecifier = prevFieldDeclaration - > mReadOnlySpecifier ;
fieldDeclaration - > mVolatileSpecifier = prevFieldDeclaration - > mVolatileSpecifier ;
fieldDeclaration - > mNewSpecifier = prevFieldDeclaration - > mNewSpecifier ;
fieldDeclaration - > mExternSpecifier = prevFieldDeclaration - > mExternSpecifier ;
tokenNode = ExpectTokenAfter ( fieldDeclaration , BfToken_Semicolon , BfToken_AssignEquals , BfToken_Comma ) ;
if ( tokenNode = = NULL )
return fieldDeclaration ;
mVisitorPos . mReadPos - - ; // Go back to token
}
else
{
ReplaceNode ( typeRef , fieldDeclaration ) ;
fieldDeclaration - > mTypeRef = typeRef ;
fieldDeclaration - > mNameNode = nameIdentifier ;
fieldDeclaration - > mInitializer = NULL ;
MoveNode ( fieldDeclaration - > mNameNode , fieldDeclaration ) ;
//mVisitorPos.MoveNext();
}
BfToken token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_AssignEquals )
{
MEMBER_SET ( fieldDeclaration , mEqualsNode , tokenNode ) ;
MoveNode ( tokenNode , fieldDeclaration ) ;
mVisitorPos . MoveNext ( ) ;
mIsFieldInitializer = true ;
fieldDeclaration - > mInitializer = CreateExpressionAfter ( fieldDeclaration ) ;
mIsFieldInitializer = false ;
if ( fieldDeclaration - > mInitializer ! = NULL )
{
MoveNode ( fieldDeclaration - > mInitializer , fieldDeclaration ) ;
auto nextToken = ExpectTokenAfter ( fieldDeclaration , BfToken_Semicolon , BfToken_Tilde ) ;
if ( nextToken ! = NULL )
mVisitorPos . mReadPos - - ; // Backtrack, someone else eats these
}
}
else if ( token = = BfToken_Comma )
{
//
}
else if ( token = = BfToken_Tilde )
{
//
}
else if ( token ! = BfToken_Semicolon )
{
//MEMBER_SET(fieldDeclaration, mEqualsNode, tokenNode);
FailAfter ( " ';', '=', or '~' expected " , nameIdentifier ) ;
return fieldDeclaration ;
}
auto fieldDtor = CreateFieldDtorDeclaration ( fieldDeclaration ) ;
if ( fieldDtor ! = NULL )
fieldDeclaration - > mFieldDtor = fieldDtor ;
if ( ExpectTokenAfter ( fieldDeclaration , BfToken_Semicolon , BfToken_Comma ) ! = NULL )
{
// This gets taken later
mVisitorPos . mReadPos - - ;
}
fieldDeclaration - > mDocumentation = FindDocumentation ( mTypeMemberNodeStart , fieldDeclaration , true ) ;
return fieldDeclaration ;
}
BfAstNode * BfReducer : : ReadTypeMember ( BfTokenNode * tokenNode , int depth )
{
BfToken token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_Semicolon )
return tokenNode ;
if ( token = = BfToken_LBracket )
{
auto attributes = CreateAttributeDirective ( tokenNode ) ;
if ( attributes = = NULL )
return NULL ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode = = NULL )
{
FailAfter ( " Expected member " , attributes ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
auto memberNode = ReadTypeMember ( nextNode ) ;
if ( memberNode = = NULL )
return NULL ;
auto member = BfNodeDynCast < BfMemberDeclaration > ( memberNode ) ;
if ( member = = NULL )
{
if ( auto innerType = BfNodeDynCast < BfTypeDeclaration > ( memberNode ) )
{
ReplaceNode ( attributes , innerType ) ;
innerType - > mAttributes = attributes ;
return innerType ;
}
mPassInstance - > Fail ( " Invalid target for attributes " , memberNode ) ;
return memberNode ;
}
ReplaceNode ( attributes , member ) ;
member - > mAttributes = attributes ;
return member ;
}
if ( token = = BfToken_Operator )
{
auto operatorDecl = mAlloc - > Alloc < BfOperatorDeclaration > ( ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( operatorDecl - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( operatorDecl - > mCommas , mAlloc ) ;
ReplaceNode ( tokenNode , operatorDecl ) ;
operatorDecl - > mOperatorToken = tokenNode ;
auto nextIdentifier = ExpectIdentifierAfter ( operatorDecl , " type " ) ;
if ( nextIdentifier = = NULL )
return operatorDecl ;
mVisitorPos . mReadPos - - ; // Backtrack, that's part of our type
auto typeRef = CreateTypeRefAfter ( operatorDecl ) ;
MEMBER_SET_CHECKED ( operatorDecl , mReturnType , typeRef ) ;
operatorDecl - > mIsConvOperator = true ;
ParseMethod ( operatorDecl , & params , & commas ) ;
return operatorDecl ;
}
if ( token = = BfToken_This )
{
auto ctorDecl = mAlloc - > Alloc < BfConstructorDeclaration > ( ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( ctorDecl - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( ctorDecl - > mCommas , mAlloc ) ;
ctorDecl - > mReturnType = NULL ;
ReplaceNode ( tokenNode , ctorDecl ) ;
MEMBER_SET ( ctorDecl , mThisToken , tokenNode ) ;
ParseMethod ( ctorDecl , & params , & commas ) ;
return ctorDecl ;
}
if ( token = = BfToken_Tilde )
{
auto thisToken = ExpectTokenAfter ( tokenNode , BfToken_This ) ;
if ( thisToken = = NULL )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
auto nameIdentifier = BfNodeDynCast < BfIdentifierNode > ( nextNode ) ;
if ( nameIdentifier ! = NULL )
{
// Eat DTOR name
AddErrorNode ( nameIdentifier ) ;
//nameIdentifier->RemoveSelf();
}
else
{
//AddErrorNode(tokenNode);
//return NULL;
}
AddErrorNode ( tokenNode ) ;
return NULL ;
}
auto dtorDecl = mAlloc - > Alloc < BfDestructorDeclaration > ( ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( dtorDecl - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( dtorDecl - > mCommas , mAlloc ) ;
dtorDecl - > mReturnType = NULL ;
ReplaceNode ( tokenNode , dtorDecl ) ;
dtorDecl - > mTildeToken = tokenNode ;
if ( thisToken ! = NULL )
{
MEMBER_SET ( dtorDecl , mThisToken , thisToken ) ;
}
ParseMethod ( dtorDecl , & params , & commas ) ;
return dtorDecl ;
}
if ( token = = BfToken_Mixin )
{
auto methodDecl = mAlloc - > Alloc < BfMethodDeclaration > ( ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( methodDecl - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( methodDecl - > mCommas , mAlloc ) ;
ReplaceNode ( tokenNode , methodDecl ) ;
methodDecl - > mDocumentation = FindDocumentation ( methodDecl ) ;
methodDecl - > mMixinSpecifier = tokenNode ;
//mVisitorPos.MoveNext();
auto nameNode = ExpectIdentifierAfter ( methodDecl ) ;
if ( nameNode ! = NULL )
{
MEMBER_SET ( methodDecl , mNameNode , nameNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_LChevron )
{
auto genericParams = CreateGenericParamsDeclaration ( tokenNode ) ;
if ( genericParams ! = NULL )
{
MEMBER_SET ( methodDecl , mGenericParams , genericParams ) ;
}
}
}
ParseMethod ( methodDecl , & params , & commas ) ;
}
return methodDecl ;
}
if ( token = = BfToken_Case )
{
auto enumCaseDecl = mAlloc - > Alloc < BfEnumCaseDeclaration > ( ) ;
BfDeferredAstSizedArray < BfFieldDeclaration * > entries ( enumCaseDecl - > mEntries , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( enumCaseDecl - > mCommas , mAlloc ) ;
ReplaceNode ( tokenNode , enumCaseDecl ) ;
enumCaseDecl - > mCaseToken = tokenNode ;
while ( true )
{
auto caseName = ExpectIdentifierAfter ( enumCaseDecl ) ;
if ( caseName = = NULL )
break ;
auto enumEntry = mAlloc - > Alloc < BfEnumEntryDeclaration > ( ) ;
ReplaceNode ( caseName , enumEntry ) ;
enumEntry - > mNameNode = caseName ;
entries . push_back ( enumEntry ) ;
tokenNode = ExpectTokenAfter ( enumEntry , BfToken_Comma , BfToken_AssignEquals , BfToken_LParen , BfToken_Semicolon ) ;
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_LParen ) )
{
auto typeRef = CreateTypeRef ( tokenNode ) ;
tokenNode = NULL ;
auto tupleType = BfNodeDynCast < BfTupleTypeRef > ( typeRef ) ;
if ( tupleType ! = NULL )
{
MEMBER_SET ( enumEntry , mTypeRef , tupleType ) ;
tokenNode = ExpectTokenAfter ( enumEntry , BfToken_Comma , BfToken_AssignEquals , BfToken_Semicolon ) ;
}
}
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_AssignEquals ) )
{
MEMBER_SET ( enumEntry , mEqualsNode , tokenNode ) ;
tokenNode = NULL ;
auto initializer = CreateExpressionAfter ( enumEntry ) ;
if ( initializer ! = NULL )
{
MEMBER_SET ( enumEntry , mInitializer , initializer ) ;
tokenNode = ExpectTokenAfter ( enumEntry , BfToken_Comma , BfToken_Semicolon ) ;
}
}
MoveNode ( enumEntry , enumCaseDecl ) ;
if ( tokenNode = = NULL )
return enumCaseDecl ;
if ( tokenNode - > GetToken ( ) = = BfToken_Semicolon )
{
mVisitorPos . mReadPos - - ;
return enumCaseDecl ;
}
MoveNode ( tokenNode , enumCaseDecl ) ;
commas . push_back ( tokenNode ) ;
}
return enumCaseDecl ;
}
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode = = NULL )
FailAfter ( " Type expected " , tokenNode ) ;
if ( ( token = = BfToken_Struct ) | | ( token = = BfToken_Enum ) | | ( token = = BfToken_Class ) | | ( token = = BfToken_Delegate ) | |
( token = = BfToken_Function ) | | ( token = = BfToken_Interface ) | | ( token = = BfToken_Extension ) | | ( token = = BfToken_TypeAlias ) )
{
mVisitorPos . mReadPos - = depth ;
BfAstNode * startNode = mVisitorPos . GetCurrent ( ) ;
auto startToken = BfNodeDynCast < BfTokenNode > ( startNode ) ;
auto topLevelObject = CreateTopLevelObject ( startToken , NULL ) ;
auto typeDecl = BfNodeDynCast < BfTypeDeclaration > ( topLevelObject ) ;
if ( typeDecl = = NULL )
{
AddErrorNode ( tokenNode ) ;
return NULL ;
}
return typeDecl ;
}
if ( token = = BfToken_Comma )
{
auto prevNode = mVisitorPos . Get ( mVisitorPos . mWritePos - 1 ) ;
auto prevFieldDecl = BfNodeDynCast < BfFieldDeclaration > ( prevNode ) ;
if ( prevFieldDecl ! = NULL )
{
auto nameIdentifier = ExpectIdentifierAfter ( tokenNode ) ;
if ( nameIdentifier = = NULL )
{
AddErrorNode ( tokenNode ) ;
return NULL ;
}
return CreateFieldDeclaration ( tokenNode , prevFieldDecl - > mTypeRef , nameIdentifier , prevFieldDecl ) ;
}
}
switch ( token )
{
case BfToken_Sealed :
case BfToken_Static :
case BfToken_Const :
case BfToken_Mut :
case BfToken_Public :
case BfToken_Protected :
case BfToken_Private :
case BfToken_Virtual :
case BfToken_Override :
case BfToken_Abstract :
case BfToken_Concrete :
case BfToken_Internal :
case BfToken_Extern :
case BfToken_New :
case BfToken_Implicit :
case BfToken_Explicit :
case BfToken_ReadOnly :
case BfToken_Inline :
case BfToken_Volatile :
break ;
default :
AddErrorNode ( tokenNode ) ;
Fail ( " Unexpected token " , tokenNode ) ;
return NULL ;
break ;
}
int startNodeIdx = gAssertCurrentNodeIdx ;
BfAstNode * typeMember = NULL ;
nextNode = mVisitorPos . GetNext ( ) ;
if ( nextNode ! = NULL )
{
mVisitorPos . MoveNext ( ) ;
typeMember = ReadTypeMember ( nextNode , depth + 1 ) ;
}
auto memberDecl = BfNodeDynCast < BfMemberDeclaration > ( typeMember ) ;
if ( memberDecl = = NULL ) // May be an embedded type
{
if ( auto typeDecl = BfNodeDynCast < BfTypeDeclaration > ( typeMember ) )
return typeMember ;
}
if ( typeMember = = NULL )
{
auto propertyDeclaration = mAlloc - > Alloc < BfPropertyDeclaration > ( ) ;
ReplaceNode ( tokenNode , propertyDeclaration ) ;
propertyDeclaration - > mDocumentation = FindDocumentation ( propertyDeclaration ) ;
typeMember = memberDecl = propertyDeclaration ;
}
if ( memberDecl = = NULL )
return NULL ;
if ( token = = BfToken_Static )
{
if ( memberDecl - > mStaticSpecifier ! = NULL )
{
AddErrorNode ( memberDecl - > mStaticSpecifier ) ;
Fail ( " Static already specified " , memberDecl - > mStaticSpecifier ) ;
}
MEMBER_SET ( memberDecl , mStaticSpecifier , tokenNode ) ;
auto fieldDecl = BfNodeDynCast < BfFieldDeclaration > ( memberDecl ) ;
if ( fieldDecl ! = NULL )
{
if ( ( fieldDecl - > mStaticSpecifier ! = NULL ) & & ( fieldDecl - > mConstSpecifier ! = NULL ) )
Fail ( " Cannot use 'static' and 'const' together " , fieldDecl ) ;
}
return memberDecl ;
}
if ( ( token = = BfToken_Public ) | |
( token = = BfToken_Protected ) | |
( token = = BfToken_Private ) )
{
if ( memberDecl - > mProtectionSpecifier ! = NULL )
{
AddErrorNode ( memberDecl - > mProtectionSpecifier ) ;
Fail ( " Protection already specified " , memberDecl - > mProtectionSpecifier ) ;
}
MEMBER_SET ( memberDecl , mProtectionSpecifier , tokenNode ) ;
return memberDecl ;
}
if ( token = = BfToken_Internal )
{
if ( memberDecl - > mInternalSpecifier ! = NULL )
{
AddErrorNode ( memberDecl - > mInternalSpecifier ) ;
Fail ( " Internal already specified " , memberDecl - > mInternalSpecifier ) ;
}
MEMBER_SET ( memberDecl , mInternalSpecifier , tokenNode ) ;
return memberDecl ;
}
if ( auto methodDecl = BfNodeDynCast < BfMethodDeclaration > ( memberDecl ) )
{
if ( ( token = = BfToken_Virtual ) | |
( token = = BfToken_Override ) | |
( token = = BfToken_Abstract ) | |
( token = = BfToken_Concrete ) )
{
if ( methodDecl - > mVirtualSpecifier ! = NULL )
{
AddErrorNode ( methodDecl - > mVirtualSpecifier ) ;
if ( methodDecl - > mVirtualSpecifier - > GetToken ( ) = = tokenNode - > GetToken ( ) )
Fail ( StrFormat ( " Already specified '%s' " , BfTokenToString ( tokenNode - > GetToken ( ) ) ) , methodDecl - > mVirtualSpecifier ) ;
else
Fail ( StrFormat ( " Cannot specify both '%s' and '%s' " , BfTokenToString ( methodDecl - > mVirtualSpecifier - > GetToken ( ) ) , BfTokenToString ( tokenNode - > GetToken ( ) ) ) , methodDecl - > mVirtualSpecifier ) ;
}
MEMBER_SET ( methodDecl , mVirtualSpecifier , tokenNode ) ;
return memberDecl ;
}
if ( token = = BfToken_Extern )
{
if ( methodDecl - > mExternSpecifier ! = NULL )
{
AddErrorNode ( methodDecl - > mExternSpecifier ) ;
Fail ( " Extern already specified " , methodDecl - > mExternSpecifier ) ;
}
MEMBER_SET ( methodDecl , mExternSpecifier , tokenNode ) ;
return memberDecl ;
}
if ( token = = BfToken_New )
{
if ( methodDecl - > mNewSpecifier ! = NULL )
{
AddErrorNode ( methodDecl - > mNewSpecifier ) ;
Fail ( " New already specified " , methodDecl - > mNewSpecifier ) ;
}
MEMBER_SET ( methodDecl , mNewSpecifier , tokenNode ) ;
return memberDecl ;
}
if ( token = = BfToken_Mut )
{
if ( methodDecl - > mMutSpecifier ! = NULL )
{
AddErrorNode ( methodDecl - > mMutSpecifier ) ;
Fail ( " Mut already specified " , methodDecl - > mMutSpecifier ) ;
}
MEMBER_SET ( methodDecl , mMutSpecifier , tokenNode ) ;
return memberDecl ;
}
if ( token = = BfToken_ReadOnly )
{
if ( methodDecl - > mReadOnlySpecifier = = NULL )
{
MEMBER_SET ( methodDecl , mReadOnlySpecifier , tokenNode ) ;
}
return memberDecl ;
}
}
if ( auto operatorDecl = BfNodeDynCast < BfOperatorDeclaration > ( memberDecl ) )
{
if ( ( token = = BfToken_Implicit ) | |
( token = = BfToken_Explicit ) )
{
if ( operatorDecl - > mExplicitToken ! = NULL )
{
AddErrorNode ( operatorDecl - > mExplicitToken ) ;
Fail ( StrFormat ( " '%s' already specified " , BfTokenToString ( operatorDecl - > mExplicitToken - > GetToken ( ) ) ) , operatorDecl - > mExplicitToken ) ;
}
MEMBER_SET ( operatorDecl , mExplicitToken , tokenNode ) ;
return memberDecl ;
}
}
if ( auto propDecl = BfNodeDynCast < BfPropertyDeclaration > ( memberDecl ) )
{
if ( ( token = = BfToken_Virtual ) | |
( token = = BfToken_Override ) | |
( token = = BfToken_Abstract ) | |
( token = = BfToken_Concrete ) )
{
if ( propDecl - > mVirtualSpecifier ! = NULL )
{
AddErrorNode ( propDecl - > mVirtualSpecifier ) ;
if ( propDecl - > mVirtualSpecifier - > GetToken ( ) = = token )
Fail ( StrFormat ( " Already specified '%s' " , BfTokenToString ( token ) ) , propDecl - > mVirtualSpecifier ) ;
else
Fail ( StrFormat ( " Cannot specify both '%s' and '%s' " , BfTokenToString ( propDecl - > mVirtualSpecifier - > GetToken ( ) ) , BfTokenToString ( token ) ) , propDecl - > mVirtualSpecifier ) ;
}
MEMBER_SET ( propDecl , mVirtualSpecifier , tokenNode ) ;
return memberDecl ;
}
}
if ( auto fieldDecl = BfNodeDynCast < BfFieldDeclaration > ( memberDecl ) )
{
if ( token = = BfToken_Override )
{
// Must be typing an 'override' over a field declaration
auto propDecl = mAlloc - > Alloc < BfPropertyDeclaration > ( ) ;
propDecl - > mVirtualSpecifier = tokenNode ;
typeMember = memberDecl = propDecl ;
}
bool handled = false ;
if ( token = = BfToken_Const )
{
MEMBER_SET ( fieldDecl , mConstSpecifier , tokenNode ) ;
handled = true ;
}
if ( token = = BfToken_ReadOnly )
{
if ( fieldDecl - > mReadOnlySpecifier = = NULL )
{
MEMBER_SET ( fieldDecl , mReadOnlySpecifier , tokenNode ) ;
}
handled = true ;
}
if ( token = = BfToken_Inline )
{
MEMBER_SET ( fieldDecl , mReadOnlySpecifier , tokenNode ) ;
handled = true ;
}
if ( token = = BfToken_Volatile )
{
MEMBER_SET ( fieldDecl , mVolatileSpecifier , tokenNode ) ;
handled = true ;
}
if ( token = = BfToken_Extern )
{
MEMBER_SET ( fieldDecl , mExternSpecifier , tokenNode ) ;
handled = true ;
}
if ( token = = BfToken_Internal )
{
MEMBER_SET ( fieldDecl , mInternalSpecifier , tokenNode ) ;
handled = true ;
}
if ( token = = BfToken_New )
{
if ( fieldDecl - > mNewSpecifier ! = NULL )
{
Fail ( " New already specified " , tokenNode ) ;
}
MEMBER_SET ( fieldDecl , mNewSpecifier , tokenNode ) ;
handled = true ;
}
if ( ( fieldDecl - > mStaticSpecifier ! = NULL ) & & ( fieldDecl - > mConstSpecifier ! = NULL ) )
Fail ( " Cannot use 'static' and 'const' together " , fieldDecl ) ;
if ( ( fieldDecl - > mReadOnlySpecifier ! = NULL ) & & ( fieldDecl - > mConstSpecifier ! = NULL ) )
Fail ( " Cannot use 'readonly' and 'const' together " , fieldDecl ) ;
if ( ( fieldDecl - > mVolatileSpecifier ! = NULL ) & & ( fieldDecl - > mConstSpecifier ! = NULL ) )
Fail ( " Cannot use 'volatile' and 'const' together " , fieldDecl ) ;
if ( handled )
return fieldDecl ;
}
// Eat node
if ( memberDecl ! = NULL )
ReplaceNode ( tokenNode , memberDecl ) ;
Fail ( " Invalid token " , tokenNode ) ;
return memberDecl ;
}
void BfReducer : : ReadPropertyBlock ( BfPropertyDeclaration * propertyDeclaration , BfBlock * block )
{
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( block ) ) ;
BfDeferredAstSizedArray < BfPropertyMethodDeclaration * > methods ( propertyDeclaration - > mMethods , mAlloc ) ;
bool hadGet = false ;
bool hadSet = false ;
while ( true )
{
BfTokenNode * protectionSpecifier = NULL ;
BfAttributeDirective * attributes = NULL ;
auto child = mVisitorPos . GetNext ( ) ;
if ( child = = NULL )
break ;
String accessorName ;
BfTokenNode * mutSpecifier = NULL ;
while ( true )
{
auto tokenNode = BfNodeDynCast < BfTokenNode > ( child ) ;
if ( tokenNode = = NULL )
break ;
BfToken token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_LBracket )
{
mVisitorPos . MoveNext ( ) ;
attributes = CreateAttributeDirective ( tokenNode ) ;
child = mVisitorPos . GetNext ( ) ;
}
tokenNode = BfNodeDynCast < BfTokenNode > ( child ) ;
if ( tokenNode = = NULL )
break ;
token = tokenNode - > GetToken ( ) ;
if ( ( token = = BfToken_Private ) | |
( token = = BfToken_Protected ) | |
( token = = BfToken_Public ) | |
( token = = BfToken_Internal ) )
{
if ( protectionSpecifier ! = NULL )
{
Fail ( " Protection already specified " , protectionSpecifier ) ;
}
protectionSpecifier = tokenNode ;
mVisitorPos . MoveNext ( ) ;
child = mVisitorPos . GetCurrent ( ) ;
}
else if ( token = = BfToken_Mut )
{
Fail ( " 'mut' must be specified after get/set " , tokenNode ) ;
mutSpecifier = tokenNode ;
mVisitorPos . MoveNext ( ) ;
}
else
break ;
child = mVisitorPos . GetNext ( ) ;
}
auto identifierNode = child ;
auto accessorIdentifier = BfNodeDynCast < BfIdentifierNode > ( child ) ;
if ( accessorIdentifier ! = NULL )
{
accessorName = accessorIdentifier - > ToString ( ) ;
mVisitorPos . MoveNext ( ) ;
child = mVisitorPos . GetNext ( ) ;
}
if ( accessorName = = " get " )
{
// if (hadGet)
// Fail("Only one 'get' method can be specified", accessorIdentifier);
hadGet = true ;
}
else if ( accessorName = = " set " )
{
// if (hadSet)
// Fail("Only one 'set' method can be specified", accessorIdentifier);
hadSet = true ;
}
else
{
Fail ( " Expected 'set' or 'get' " , identifierNode ) ;
}
BfAstNode * bodyAfterNode = accessorIdentifier ;
BfAstNode * body = NULL ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( child ) ;
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_Mut ) )
{
if ( mutSpecifier ! = NULL )
{
Fail ( " 'mut' already specified " , mutSpecifier ) ;
}
mutSpecifier = tokenNode ;
bodyAfterNode = tokenNode ;
mVisitorPos . MoveNext ( ) ;
child = mVisitorPos . GetCurrent ( ) ;
}
auto endSemicolon = BfNodeDynCast < BfTokenNode > ( child ) ;
if ( ( endSemicolon ! = NULL ) & & ( endSemicolon - > GetToken ( ) = = BfToken_Semicolon ) )
{
body = endSemicolon ;
mVisitorPos . MoveNext ( ) ;
}
if ( body = = NULL )
{
if ( bodyAfterNode ! = NULL )
{
body = ExpectBlockAfter ( bodyAfterNode ) ;
}
else
{
auto accessorBlock = BfNodeDynCast < BfBlock > ( child ) ;
if ( accessorBlock = = NULL )
{
if ( child ! = NULL )
{
Fail ( " Block expected " , child ) ;
AddErrorNode ( child ) ;
mVisitorPos . MoveNext ( ) ;
}
continue ;
}
body = accessorBlock ;
mVisitorPos . MoveNext ( ) ;
}
}
if ( auto block = BfNodeDynCast < BfBlock > ( body ) )
{
if ( ( ( attributes = = NULL ) & & ( IsNodeRelevant ( block ) ) ) | |
( ( attributes ! = NULL ) & & ( IsNodeRelevant ( attributes , block ) ) ) )
{
HandleBlock ( block ) ;
}
}
if ( body = = NULL )
{
if ( protectionSpecifier ! = NULL )
AddErrorNode ( protectionSpecifier ) ;
if ( accessorIdentifier ! = NULL )
AddErrorNode ( accessorIdentifier ) ;
if ( mutSpecifier ! = NULL )
AddErrorNode ( mutSpecifier ) ;
continue ;
}
auto method = mAlloc - > Alloc < BfPropertyMethodDeclaration > ( ) ;
method - > mPropertyDeclaration = propertyDeclaration ;
if ( protectionSpecifier ! = NULL )
MEMBER_SET ( method , mProtectionSpecifier , protectionSpecifier ) ;
if ( accessorIdentifier ! = NULL )
MEMBER_SET ( method , mNameNode , accessorIdentifier ) ;
if ( body ! = NULL )
{
MEMBER_SET ( method , mBody , body ) ;
}
if ( mutSpecifier ! = NULL )
MEMBER_SET ( method , mMutSpecifier , mutSpecifier ) ;
// if ((accessorBlock != NULL) && (IsNodeRelevant(propertyDeclaration)))
// HandleBlock(accessorBlock);
if ( attributes ! = NULL )
MEMBER_SET ( method , mAttributes , attributes ) ;
methods . push_back ( method ) ;
}
}
BfAstNode * BfReducer : : ReadTypeMember ( BfAstNode * node , int depth )
{
SetAndRestoreValue < BfAstNode * > prevTypeMemberNodeStart ( mTypeMemberNodeStart , node , false ) ;
if ( depth = = 0 )
prevTypeMemberNodeStart . Set ( ) ;
AssertCurrentNode ( node ) ;
node = ReplaceTokenStarter ( node ) ;
BfTokenNode * refToken = NULL ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( node ) )
{
BfToken token = tokenNode - > GetToken ( ) ;
bool isTypeRef = false ;
if ( ( token = = BfToken_Delegate ) | | ( token = = BfToken_Function ) )
{
// We need to differentiate between a delegate type reference and a delegate type declaration
int endNodeIdx = - 1 ;
if ( IsTypeReference ( node , BfToken_LParen , & endNodeIdx ) )
{
isTypeRef = true ;
}
}
if ( isTypeRef )
{
// Handled below
}
else if ( ( token = = BfToken_Ref ) | | ( token = = BfToken_Mut ) )
{
refToken = tokenNode ;
mVisitorPos . MoveNext ( ) ;
// Read type member
}
else if ( ( token = = BfToken_Var ) | |
( token = = BfToken_Let ) | |
( token = = BfToken_RetType ) | |
( token = = BfToken_Decltype ) | |
( token = = BfToken_LParen ) )
{
// Read type member
}
else
return ReadTypeMember ( tokenNode , depth ) ;
}
else if ( auto block = BfNodeDynCast < BfBlock > ( node ) )
{
Fail ( " Expected method declaration " , node ) ;
HandleBlock ( block ) ;
auto methodDecl = mAlloc - > Alloc < BfMethodDeclaration > ( ) ;
ReplaceNode ( block , methodDecl ) ;
methodDecl - > mDocumentation = FindDocumentation ( methodDecl ) ;
methodDecl - > mBody = block ;
return methodDecl ;
}
BfTokenNode * indexerThisToken = NULL ;
bool isIndexProp = false ;
auto origNode = node ;
if ( refToken ! = NULL )
{
auto nextNode = mVisitorPos . Get ( mVisitorPos . mReadPos ) ;
if ( nextNode ! = NULL )
node = nextNode ;
}
auto typeRef = CreateTypeRef ( node ) ;
if ( typeRef = = NULL )
{
if ( refToken ! = NULL )
{
AddErrorNode ( refToken ) ;
if ( mVisitorPos . Get ( mVisitorPos . mReadPos ) = = node )
{
mVisitorPos . mReadPos - - ;
return NULL ;
}
}
# ifdef BF_AST_HAS_PARENT_MEMBER
BF_ASSERT ( node - > mParent ! = NULL ) ;
# endif
AddErrorNode ( node ) ;
return NULL ;
}
if ( refToken ! = NULL )
typeRef = CreateRefTypeRef ( typeRef , refToken ) ;
node = typeRef ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_This )
indexerThisToken = tokenNode ;
}
BfTokenNode * explicitInterfaceDot = NULL ;
BfTypeReference * explicitInterface = NULL ;
bool forceIsMethod = false ;
nextNode = mVisitorPos . GetNext ( ) ;
auto nameIdentifier = BfNodeDynCast < BfIdentifierNode > ( nextNode ) ;
if ( nameIdentifier ! = NULL )
{
mVisitorPos . MoveNext ( ) ;
bool doExplicitInterface = false ;
int endNodeIdx = - 1 ;
//mVisitorPos.mReadPos++;
int nameIdentifierIdx = mVisitorPos . mReadPos ;
doExplicitInterface = IsTypeReference ( nameIdentifier , BfToken_LParen , & endNodeIdx ) ;
//mVisitorPos.mReadPos--;
BfAstNode * endNode = mVisitorPos . Get ( endNodeIdx ) ;
if ( ! doExplicitInterface )
{
if ( auto endToken = BfNodeDynCastExact < BfTokenNode > ( endNode ) )
{
if ( endToken - > GetToken ( ) = = BfToken_This )
{
indexerThisToken = endToken ;
doExplicitInterface = true ;
}
}
else if ( auto block = BfNodeDynCastExact < BfBlock > ( endNode ) )
{
doExplicitInterface = true ; // Qualified property
}
}
if ( doExplicitInterface )
{
auto prevEndNode = mVisitorPos . Get ( endNodeIdx - 1 ) ;
int explicitInterfaceDotIdx = QualifiedBacktrack ( prevEndNode , endNodeIdx - 1 ) ;
if ( explicitInterfaceDotIdx ! = - 1 )
{
explicitInterfaceDot = ( BfTokenNode * ) mVisitorPos . Get ( explicitInterfaceDotIdx ) ;
mVisitorPos . mReadPos = nameIdentifierIdx ;
explicitInterfaceDot - > SetToken ( BfToken_Bar ) ; // Hack to stop TypeRef parsing
explicitInterface = CreateTypeRef ( nameIdentifier ) ;
explicitInterfaceDot - > SetToken ( BfToken_Dot ) ;
if ( explicitInterface = = NULL )
return NULL ;
mVisitorPos . mReadPos = explicitInterfaceDotIdx ;
if ( indexerThisToken = = NULL )
{
nameIdentifier = ExpectIdentifierAfter ( explicitInterfaceDot ) ;
if ( nameIdentifier = = NULL )
{
// Looks like a method declaration
auto methodDeclaration = mAlloc - > Alloc < BfMethodDeclaration > ( ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( methodDeclaration - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( methodDeclaration - > mCommas , mAlloc ) ;
if ( typeRef ! = NULL )
ReplaceNode ( typeRef , methodDeclaration ) ;
else
ReplaceNode ( nameIdentifier , methodDeclaration ) ;
methodDeclaration - > mDocumentation = FindDocumentation ( mTypeMemberNodeStart ) ;
MEMBER_SET ( methodDeclaration , mReturnType , typeRef ) ;
MEMBER_SET ( methodDeclaration , mExplicitInterface , explicitInterface ) ;
MEMBER_SET ( methodDeclaration , mExplicitInterfaceDotToken , explicitInterfaceDot ) ;
return methodDeclaration ;
}
}
}
}
}
else if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( nextToken - > GetToken ( ) = = BfToken_Operator )
{
auto operatorDecl = mAlloc - > Alloc < BfOperatorDeclaration > ( ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( operatorDecl - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( operatorDecl - > mCommas , mAlloc ) ;
ReplaceNode ( typeRef , operatorDecl ) ;
operatorDecl - > mReturnType = typeRef ;
mVisitorPos . MoveNext ( ) ;
MEMBER_SET ( operatorDecl , mOperatorToken , nextToken ) ;
bool hadFailedOperator = false ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
2019-11-17 09:28:39 -08:00
operatorDecl - > mBinOp = BfTokenToBinaryOp ( nextToken - > GetToken ( ) ) ;
2019-08-23 11:56:54 -07:00
if ( operatorDecl - > mBinOp ! = BfBinaryOp_None )
{
MEMBER_SET ( operatorDecl , mOpTypeToken , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
}
else
{
2019-11-17 09:28:39 -08:00
operatorDecl - > mUnaryOp = BfTokenToUnaryOp ( nextToken - > GetToken ( ) ) ;
2019-08-23 11:56:54 -07:00
if ( operatorDecl - > mUnaryOp ! = BfUnaryOp_None )
{
MEMBER_SET ( operatorDecl , mOpTypeToken , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
}
else
{
2019-11-17 09:28:39 -08:00
operatorDecl - > mAssignOp = BfTokenToAssignmentOp ( nextToken - > GetToken ( ) ) ;
2019-08-23 11:56:54 -07:00
if ( operatorDecl - > mAssignOp = = BfAssignmentOp_Assign )
{
Fail ( " The assignment operator '=' cannot be overridden " , nextToken ) ;
}
if ( operatorDecl - > mAssignOp ! = BfAssignmentOp_None )
{
MEMBER_SET ( operatorDecl , mOpTypeToken , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
}
else if ( nextToken - > GetToken ( ) ! = BfToken_LParen )
{
Fail ( " Invalid operator type " , nextToken ) ;
MEMBER_SET ( operatorDecl , mOpTypeToken , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
}
}
}
}
if ( ( operatorDecl - > mOpTypeToken = = NULL ) & & ( operatorDecl - > mReturnType = = NULL ) & & ( ! hadFailedOperator ) )
{
FailAfter ( " Expected operator type " , operatorDecl ) ;
return NULL ;
}
ParseMethod ( operatorDecl , & params , & commas ) ;
// This was the one ambiguous case
if ( ( operatorDecl - > mBinOp = = BfBinaryOp_Subtract ) & & ( params . size ( ) = = 1 ) )
{
operatorDecl - > mBinOp = BfBinaryOp_None ;
operatorDecl - > mUnaryOp = BfUnaryOp_Negate ;
}
return operatorDecl ;
}
else if ( nextToken - > GetToken ( ) = = BfToken_LParen )
{
Fail ( " Method name, 'this', or '~this' expected " , node ) ;
nameIdentifier = BfNodeDynCast < BfIdentifierNode > ( origNode ) ;
if ( nameIdentifier ! = NULL )
{
// Remove TypeRef
ReplaceNode ( typeRef , nameIdentifier ) ;
typeRef = NULL ;
}
}
}
if ( ( nameIdentifier ! = NULL ) | | ( forceIsMethod ) | | ( indexerThisToken ! = NULL ) )
{
//ExtractExplicitInterfaceRef
int blockAfterIdx = mVisitorPos . mReadPos + 1 ;
BfAstNode * blockAfterPos = nameIdentifier ;
BfPropertyDeclaration * propertyDeclaration = NULL ;
if ( indexerThisToken ! = NULL )
{
auto indexerDeclaration = mAlloc - > Alloc < BfIndexerDeclaration > ( ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( indexerDeclaration - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( indexerDeclaration - > mCommas , mAlloc ) ;
ReplaceNode ( typeRef , indexerDeclaration ) ;
indexerDeclaration - > mTypeRef = typeRef ;
MEMBER_SET ( indexerDeclaration , mThisToken , indexerThisToken ) ;
mVisitorPos . MoveNext ( ) ;
if ( explicitInterface ! = NULL )
{
MEMBER_SET ( indexerDeclaration , mExplicitInterface , explicitInterface ) ;
MEMBER_SET ( indexerDeclaration , mExplicitInterfaceDotToken , explicitInterfaceDot ) ;
//mVisitorPos.mReadPos = endNodeIdx;
}
auto openToken = ExpectTokenAfter ( indexerDeclaration , BfToken_LBracket ) ;
if ( openToken = = NULL )
return indexerDeclaration ;
MEMBER_SET ( indexerDeclaration , mOpenBracket , openToken ) ;
auto endToken = ParseMethodParams ( indexerDeclaration , & params , & commas , BfToken_RBracket ) ;
if ( endToken = = NULL )
return indexerDeclaration ;
MEMBER_SET ( indexerDeclaration , mCloseBracket , endToken ) ;
propertyDeclaration = indexerDeclaration ;
blockAfterPos = propertyDeclaration ;
mVisitorPos . MoveNext ( ) ;
blockAfterIdx = mVisitorPos . mReadPos + 1 ;
auto block = ExpectBlockAfter ( blockAfterPos ) ;
if ( block = = NULL )
return indexerDeclaration ;
}
else
{
blockAfterPos = nameIdentifier ;
}
nextNode = mVisitorPos . Get ( blockAfterIdx ) ;
auto block = BfNodeDynCast < BfBlock > ( nextNode ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
2019-09-30 12:24:02 -07:00
bool isExprBodyProp = ( tokenNode ! = NULL ) & & ( tokenNode - > mToken = = BfToken_FatArrow ) ;
2019-08-23 11:56:54 -07:00
// Property.
// If we don't have a token afterwards then still treat it as a property for autocomplete purposes
2019-09-30 12:24:02 -07:00
if ( ( typeRef ! = NULL ) & &
( ( block ! = NULL ) | | ( tokenNode = = NULL ) | | ( isExprBodyProp ) ) )
2019-08-23 11:56:54 -07:00
{
//mVisitorPos.mReadPos = blockAfterIdx;
if ( propertyDeclaration = = NULL )
{
2019-09-30 12:24:02 -07:00
if ( ( block = = NULL ) & & ( ! isExprBodyProp ) )
{
2019-08-23 11:56:54 -07:00
auto propDecl = mAlloc - > Alloc < BfPropertyDeclaration > ( ) ;
ReplaceNode ( typeRef , propDecl ) ;
propDecl - > mDocumentation = FindDocumentation ( mTypeMemberNodeStart ) ;
propDecl - > mTypeRef = typeRef ;
if ( explicitInterface ! = NULL )
{
MEMBER_SET ( propDecl , mExplicitInterface , explicitInterface ) ;
MEMBER_SET ( propDecl , mExplicitInterfaceDotToken , explicitInterfaceDot ) ;
}
// Don't set the name identifier, this could be bogus
//mVisitorPos.mReadPos--;
// WHY did we want to not set this?
// If we don't, then typing a new method name will end up treating the name node as a typeRef
// which can autocomplete incorrectly
MEMBER_SET ( propDecl , mNameNode , nameIdentifier ) ;
return propDecl ;
}
mVisitorPos . mReadPos = blockAfterIdx ;
propertyDeclaration = mAlloc - > Alloc < BfPropertyDeclaration > ( ) ;
ReplaceNode ( typeRef , propertyDeclaration ) ;
propertyDeclaration - > mDocumentation = FindDocumentation ( mTypeMemberNodeStart ) ;
propertyDeclaration - > mTypeRef = typeRef ;
if ( explicitInterface ! = NULL )
{
MEMBER_SET ( propertyDeclaration , mExplicitInterface , explicitInterface ) ;
MEMBER_SET ( propertyDeclaration , mExplicitInterfaceDotToken , explicitInterfaceDot ) ;
}
MEMBER_SET ( propertyDeclaration , mNameNode , nameIdentifier ) ;
//mVisitorPos.MoveNext();
}
else
mVisitorPos . mReadPos = blockAfterIdx ;
if ( block ! = NULL )
{
MEMBER_SET ( propertyDeclaration , mDefinitionBlock , block ) ;
ReadPropertyBlock ( propertyDeclaration , block ) ;
}
2019-09-30 12:24:02 -07:00
else if ( isExprBodyProp )
{
BfDeferredAstSizedArray < BfPropertyMethodDeclaration * > methods ( propertyDeclaration - > mMethods , mAlloc ) ;
auto propertyBodyExpr = mAlloc - > Alloc < BfPropertyBodyExpression > ( ) ;
ReplaceNode ( tokenNode , propertyBodyExpr ) ;
MEMBER_SET ( propertyBodyExpr , mFatTokenArrow , tokenNode ) ;
auto method = mAlloc - > Alloc < BfPropertyMethodDeclaration > ( ) ;
method - > mPropertyDeclaration = propertyDeclaration ;
method - > mNameNode = propertyDeclaration - > mNameNode ;
auto expr = CreateExpressionAfter ( tokenNode ) ;
if ( expr ! = NULL )
{
MEMBER_SET ( method , mBody , expr ) ;
propertyDeclaration - > SetSrcEnd ( expr - > GetSrcEnd ( ) ) ;
}
methods . Add ( method ) ;
MEMBER_SET ( propertyDeclaration , mDefinitionBlock , propertyBodyExpr ) ;
}
2019-08-23 11:56:54 -07:00
return propertyDeclaration ;
}
//nextNode = mVisitorPos.Get(mVisitorPos.mReadPos + 2);
/*if (tokenNode == NULL)
{
mVisitorPos . MoveNext ( ) ;
ExpectTokenAfter ( nameIdentifier , BfToken_Semicolon ) ;
// Just 'eat' the typeRef by stuffing it into a property declaration
auto fieldDecl = mAlloc - > Alloc < BfPropertyDeclaration > ( ) ;
ReplaceNode ( typeRef , fieldDecl ) ;
fieldDecl - > mTypeRef = typeRef ;
return fieldDecl ;
} */
if ( tokenNode = = NULL )
{
auto fieldDecl = mAlloc - > Alloc < BfPropertyDeclaration > ( ) ;
ReplaceNode ( nameIdentifier , fieldDecl ) ;
fieldDecl - > mDocumentation = FindDocumentation ( mTypeMemberNodeStart ) ;
fieldDecl - > mNameNode = nameIdentifier ;
return fieldDecl ;
}
BfToken token = tokenNode - > GetToken ( ) ;
if ( ( token = = BfToken_LParen ) | |
( token = = BfToken_LChevron ) )
{
if ( token = = BfToken_LChevron )
{
//mVisitorPos.mReadPos++;
bool isTypeRef = IsTypeReference ( nameIdentifier , BfToken_LParen ) ;
//mVisitorPos.mReadPos--;
if ( ! isTypeRef )
{
bool onNewLine = false ;
auto src = nameIdentifier - > GetSourceData ( ) ;
int srcStart = nameIdentifier - > GetSrcStart ( ) ;
for ( int srcIdx = typeRef - > GetSrcEnd ( ) ; srcIdx < srcStart ; srcIdx + + )
if ( src - > mSrc [ srcIdx ] = = ' \n ' )
onNewLine = false ;
if ( onNewLine )
{
// Actually it looks like a partially formed type declaration followed by a method
// which returns a generic type
FailAfter ( " Name expected " , typeRef ) ;
auto fieldDecl = mAlloc - > Alloc < BfFieldDeclaration > ( ) ;
ReplaceNode ( typeRef , fieldDecl ) ;
fieldDecl - > mDocumentation = FindDocumentation ( mTypeMemberNodeStart ) ;
fieldDecl - > mTypeRef = typeRef ;
return fieldDecl ;
}
}
}
// Looks like a method declaration
auto methodDeclaration = mAlloc - > Alloc < BfMethodDeclaration > ( ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( methodDeclaration - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( methodDeclaration - > mCommas , mAlloc ) ;
if ( typeRef ! = NULL )
ReplaceNode ( typeRef , methodDeclaration ) ;
else
ReplaceNode ( nameIdentifier , methodDeclaration ) ;
methodDeclaration - > mDocumentation = FindDocumentation ( mTypeMemberNodeStart ) ;
if ( explicitInterface ! = NULL )
{
MEMBER_SET ( methodDeclaration , mExplicitInterface , explicitInterface ) ;
MEMBER_SET ( methodDeclaration , mExplicitInterfaceDotToken , explicitInterfaceDot ) ;
}
if ( token = = BfToken_LChevron )
{
auto genericParams = CreateGenericParamsDeclaration ( tokenNode ) ;
if ( genericParams ! = NULL )
{
MEMBER_SET ( methodDeclaration , mGenericParams , genericParams ) ;
}
}
methodDeclaration - > mReturnType = typeRef ;
MEMBER_SET_CHECKED ( methodDeclaration , mNameNode , nameIdentifier ) ;
mCurMethodDecl = methodDeclaration ;
ParseMethod ( methodDeclaration , & params , & commas ) ;
mCurMethodDecl = NULL ;
return methodDeclaration ;
}
return CreateFieldDeclaration ( tokenNode , typeRef , nameIdentifier , NULL ) ;
}
FailAfter ( " Member name expected " , node ) ;
// Same fail case as "expected member declaration"
auto fieldDecl = mAlloc - > Alloc < BfPropertyDeclaration > ( ) ;
ReplaceNode ( typeRef , fieldDecl ) ;
fieldDecl - > mDocumentation = FindDocumentation ( mTypeMemberNodeStart ) ;
fieldDecl - > mTypeRef = typeRef ;
return fieldDecl ;
}
BfInvocationExpression * BfReducer : : CreateInvocationExpression ( BfAstNode * target , CreateExprFlags createExprFlags )
{
auto tokenNode = ExpectTokenAfter ( target , BfToken_LParen , BfToken_LChevron , BfToken_Bang ) ;
auto invocationExpr = mAlloc - > Alloc < BfInvocationExpression > ( ) ;
BfDeferredAstSizedArray < BfExpression * > arguments ( invocationExpr - > mArguments , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( invocationExpr - > mCommas , mAlloc ) ;
invocationExpr - > mTarget = target ;
ReplaceNode ( target , invocationExpr ) ;
if ( tokenNode = = NULL )
return invocationExpr ;
if ( tokenNode - > GetToken ( ) = = BfToken_Bang )
{
MoveNode ( tokenNode , invocationExpr ) ;
if ( tokenNode - > GetSrcEnd ( ) = = invocationExpr - > mTarget - > GetSrcEnd ( ) + 1 )
{
BfAstNode * target = invocationExpr - > mTarget ;
while ( true )
{
if ( auto qualifiedNameNode = BfNodeDynCast < BfQualifiedNameNode > ( target ) )
target = qualifiedNameNode - > mRight ;
else if ( auto memberRefExpr = BfNodeDynCast < BfMemberReferenceExpression > ( target ) )
target = memberRefExpr - > mMemberName ;
else if ( auto attribIdentifierNode = BfNodeDynCast < BfAttributedIdentifierNode > ( target ) )
target = attribIdentifierNode - > mIdentifier ;
else
break ;
}
if ( target ! = NULL )
{
BF_ASSERT ( tokenNode - > GetSrcEnd ( ) = = target - > GetSrcEnd ( ) + 1 ) ;
target - > SetSrcEnd ( tokenNode - > GetSrcEnd ( ) ) ;
invocationExpr - > mTarget - > SetSrcEnd ( tokenNode - > GetSrcEnd ( ) ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( nextToken - > GetToken ( ) = = BfToken_Colon )
{
/*auto scopedInvocationTarget = mAlloc->Alloc<BfScopedInvocationTarget>();
ReplaceNode ( invocationExpr - > mTarget , scopedInvocationTarget ) ;
scopedInvocationTarget - > mTarget = invocationExpr - > mTarget ;
invocationExpr - > mTarget = scopedInvocationTarget ;
MEMBER_SET ( scopedInvocationTarget , mColonToken , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( ( nextToken - > GetToken ( ) = = BfToken_Colon ) | | ( nextToken - > GetToken ( ) = = BfToken_Mixin ) )
{
MEMBER_SET ( scopedInvocationTarget , mScopeName , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
}
}
else if ( auto identifier = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . GetNext ( ) ) )
{
MEMBER_SET ( scopedInvocationTarget , mScopeName , identifier ) ;
mVisitorPos . MoveNext ( ) ;
}
if ( scopedInvocationTarget - > mScopeName = = NULL )
{
FailAfter ( " Expected scope name " , scopedInvocationTarget ) ;
} */
auto scopedInvocationTarget = CreateScopedInvocationTarget ( invocationExpr - > mTarget , nextToken ) ;
invocationExpr - > SetSrcEnd ( scopedInvocationTarget - > GetSrcEnd ( ) ) ;
}
}
}
}
else
Fail ( " No space allowed before token " , tokenNode ) ;
tokenNode = ExpectTokenAfter ( invocationExpr , BfToken_LParen , BfToken_LChevron ) ;
if ( tokenNode = = NULL )
return invocationExpr ;
}
if ( tokenNode - > GetToken ( ) = = BfToken_LChevron )
{
auto genericParamsDecl = CreateGenericArguments ( tokenNode ) ;
MEMBER_SET_CHECKED ( invocationExpr , mGenericArgs , genericParamsDecl ) ;
tokenNode = ExpectTokenAfter ( invocationExpr , BfToken_LParen ) ;
}
MEMBER_SET_CHECKED ( invocationExpr , mOpenParen , tokenNode ) ;
tokenNode = ReadArguments ( invocationExpr , invocationExpr , & arguments , & commas , BfToken_RParen , true ) ;
if ( tokenNode ! = NULL )
{
MEMBER_SET ( invocationExpr , mCloseParen , tokenNode ) ;
}
return invocationExpr ;
}
BfDelegateBindExpression * BfReducer : : CreateDelegateBindExpression ( BfAstNode * allocNode )
{
auto delegateBindExpr = mAlloc - > Alloc < BfDelegateBindExpression > ( ) ;
ReplaceNode ( allocNode , delegateBindExpr ) ;
MEMBER_SET ( delegateBindExpr , mNewToken , allocNode ) ;
auto tokenNode = ExpectTokenAfter ( delegateBindExpr , BfToken_FatArrow ) ;
MEMBER_SET_CHECKED ( delegateBindExpr , mFatArrowToken , tokenNode ) ;
auto expr = CreateExpressionAfter ( delegateBindExpr ) ;
MEMBER_SET_CHECKED ( delegateBindExpr , mTarget , expr ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_LChevron )
{
auto genericParamsDecl = CreateGenericArguments ( tokenNode ) ;
MEMBER_SET_CHECKED ( delegateBindExpr , mGenericArgs , genericParamsDecl ) ;
}
}
return delegateBindExpr ;
}
BfLambdaBindExpression * BfReducer : : CreateLambdaBindExpression ( BfAstNode * allocNode , BfTokenNode * parenToken )
{
auto lambdaBindExpr = mAlloc - > Alloc < BfLambdaBindExpression > ( ) ;
BfDeferredAstSizedArray < BfIdentifierNode * > params ( lambdaBindExpr - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( lambdaBindExpr - > mCommas , mAlloc ) ;
BfTokenNode * tokenNode ;
if ( allocNode ! = NULL )
{
ReplaceNode ( allocNode , lambdaBindExpr ) ;
MEMBER_SET ( lambdaBindExpr , mNewToken , allocNode ) ;
tokenNode = ExpectTokenAfter ( lambdaBindExpr , BfToken_LParen , BfToken_LBracket ) ;
}
else
{
ReplaceNode ( parenToken , lambdaBindExpr ) ;
tokenNode = parenToken ;
}
//auto tokenNode = ExpectTokenAfter(lambdaBindExpr, BfToken_LParen, BfToken_LBracket);
if ( tokenNode = = NULL )
return lambdaBindExpr ;
if ( tokenNode - > GetToken ( ) = = BfToken_LBracket )
{
auto lambdaCapture = mAlloc - > Alloc < BfLambdaCapture > ( ) ;
ReplaceNode ( tokenNode , lambdaCapture ) ;
MEMBER_SET ( lambdaBindExpr , mLambdaCapture , lambdaCapture ) ;
MEMBER_SET ( lambdaCapture , mOpenBracket , tokenNode ) ;
while ( true )
{
tokenNode = ExpectTokenAfter ( lambdaBindExpr , BfToken_Ampersand , BfToken_AssignEquals , BfToken_RBracket ) ;
if ( tokenNode = = NULL )
return lambdaBindExpr ;
if ( ( tokenNode - > GetToken ( ) = = BfToken_Ampersand ) | | ( tokenNode - > GetToken ( ) = = BfToken_AssignEquals ) )
{
MEMBER_SET ( lambdaCapture , mCaptureToken , tokenNode ) ;
lambdaBindExpr - > SetSrcEnd ( lambdaCapture - > GetSrcEnd ( ) ) ;
}
if ( tokenNode - > GetToken ( ) = = BfToken_RBracket )
{
MEMBER_SET ( lambdaCapture , mCloseBracket , tokenNode ) ;
lambdaBindExpr - > SetSrcEnd ( lambdaCapture - > GetSrcEnd ( ) ) ;
break ;
}
}
tokenNode = ExpectTokenAfter ( lambdaBindExpr , BfToken_LParen ) ;
}
MEMBER_SET_CHECKED ( lambdaBindExpr , mOpenParen , tokenNode ) ;
for ( int paramIdx = 0 ; true ; paramIdx + + )
{
bool isRParen = false ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) )
isRParen = tokenNode - > GetToken ( ) = = BfToken_RParen ;
if ( ! isRParen )
{
auto nameIdentifier = ExpectIdentifierAfter ( lambdaBindExpr , " parameter name " ) ;
if ( nameIdentifier = = NULL )
return lambdaBindExpr ;
MoveNode ( nameIdentifier , lambdaBindExpr ) ;
params . push_back ( nameIdentifier ) ;
}
tokenNode = ExpectTokenAfter ( lambdaBindExpr , BfToken_Comma , BfToken_RParen ) ;
if ( tokenNode = = NULL )
return lambdaBindExpr ;
if ( tokenNode - > GetToken ( ) = = BfToken_RParen )
{
MEMBER_SET ( lambdaBindExpr , mCloseParen , tokenNode ) ;
break ;
}
MoveNode ( tokenNode , lambdaBindExpr ) ;
commas . push_back ( tokenNode ) ;
}
tokenNode = ExpectTokenAfter ( lambdaBindExpr , BfToken_FatArrow ) ;
MEMBER_SET_CHECKED ( lambdaBindExpr , mFatArrowToken , tokenNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto block = BfNodeDynCast < BfBlock > ( nextNode ) ;
if ( block ! = NULL )
{
HandleBlock ( block , true ) ;
mVisitorPos . MoveNext ( ) ;
MEMBER_SET_CHECKED ( lambdaBindExpr , mBody , block ) ;
}
else
{
auto expr = CreateExpressionAfter ( lambdaBindExpr ) ;
MEMBER_SET_CHECKED ( lambdaBindExpr , mBody , expr ) ;
}
auto lambdaDtor = CreateFieldDtorDeclaration ( lambdaBindExpr ) ;
if ( lambdaDtor ! = NULL )
{
if ( ( mIsFieldInitializer ) & & ( ! mInParenExpr ) )
{
Fail ( " Ambiguous destructor: could be field destructor or lambda destructor. Disambiguate with parentheses, either '(lambda) ~ fieldDtor' or '(lambda ~ lambdaDtor)' " , lambdaBindExpr ) ;
}
lambdaBindExpr - > mDtor = lambdaDtor ;
}
return lambdaBindExpr ;
}
BfCollectionInitializerExpression * BfReducer : : CreateCollectionInitializerExpression ( BfBlock * block )
{
auto arrayInitializerExpression = mAlloc - > Alloc < BfCollectionInitializerExpression > ( ) ;
BfDeferredAstSizedArray < BfExpression * > values ( arrayInitializerExpression - > mValues , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( arrayInitializerExpression - > mCommas , mAlloc ) ;
ReplaceNode ( block , arrayInitializerExpression ) ;
MEMBER_SET ( arrayInitializerExpression , mOpenBrace , block - > mOpenBrace ) ;
if ( block - > mCloseBrace ! = NULL )
MEMBER_SET ( arrayInitializerExpression , mCloseBrace , block - > mCloseBrace ) ;
block - > mOpenBrace = NULL ;
block - > mCloseBrace = NULL ;
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( block ) ) ;
bool isDone = ! mVisitorPos . MoveNext ( ) ;
while ( true )
{
auto head = mVisitorPos . GetCurrent ( ) ;
if ( head = = NULL )
break ;
BfExpression * expression ;
if ( auto innerBlock = BfNodeDynCast < BfBlock > ( head ) )
expression = CreateCollectionInitializerExpression ( innerBlock ) ;
else
expression = CreateExpression ( head ) ;
if ( expression = = NULL )
break ;
auto nextNode = mVisitorPos . GetNext ( ) ;
bool atEnd = nextNode = = NULL ;
auto tokenNode = atEnd ? NULL : ExpectTokenAfter ( expression , BfToken_Comma , BfToken_RBrace ) ;
MoveNode ( expression , arrayInitializerExpression ) ;
values . push_back ( expression ) ;
if ( ( ! atEnd ) & & ( tokenNode = = NULL ) )
break ;
if ( atEnd )
break ;
MoveNode ( tokenNode , arrayInitializerExpression ) ;
commas . push_back ( tokenNode ) ;
isDone = ! mVisitorPos . MoveNext ( ) ;
}
return arrayInitializerExpression ;
}
BfCollectionInitializerExpression * BfReducer : : CreateCollectionInitializerExpression ( BfTokenNode * openToken )
{
auto arrayInitializerExpression = mAlloc - > Alloc < BfCollectionInitializerExpression > ( ) ;
BfDeferredAstSizedArray < BfExpression * > values ( arrayInitializerExpression - > mValues , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( arrayInitializerExpression - > mCommas , mAlloc ) ;
ReplaceNode ( openToken , arrayInitializerExpression ) ;
MEMBER_SET ( arrayInitializerExpression , mOpenBrace , openToken ) ;
bool isDone = ! mVisitorPos . MoveNext ( ) ;
while ( true )
{
auto head = mVisitorPos . GetCurrent ( ) ;
if ( head = = NULL )
break ;
BfExpression * expression ;
if ( auto innerBlock = BfNodeDynCast < BfBlock > ( head ) )
expression = CreateCollectionInitializerExpression ( innerBlock ) ;
else
{
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( head ) )
{
if ( tokenNode - > mToken = = BfToken_RParen )
{
MEMBER_SET ( arrayInitializerExpression , mCloseBrace , tokenNode ) ;
return arrayInitializerExpression ;
}
}
expression = CreateExpression ( head ) ;
}
if ( expression = = NULL )
break ;
auto nextNode = mVisitorPos . GetNext ( ) ;
bool atEnd = nextNode = = NULL ;
auto tokenNode = atEnd ? NULL : ExpectTokenAfter ( expression , BfToken_Comma , BfToken_RParen ) ;
MoveNode ( expression , arrayInitializerExpression ) ;
values . push_back ( expression ) ;
if ( ( ! atEnd ) & & ( tokenNode = = NULL ) )
break ;
if ( atEnd )
break ;
MoveNode ( tokenNode , arrayInitializerExpression ) ;
if ( tokenNode - > GetToken ( ) = = BfToken_RParen )
{
MEMBER_SET ( arrayInitializerExpression , mCloseBrace , tokenNode ) ;
break ;
}
commas . push_back ( tokenNode ) ;
isDone = ! mVisitorPos . MoveNext ( ) ;
}
return arrayInitializerExpression ;
}
BfScopedInvocationTarget * BfReducer : : CreateScopedInvocationTarget ( BfAstNode * & targetRef , BfTokenNode * colonToken )
{
auto scopedInvocationTarget = mAlloc - > Alloc < BfScopedInvocationTarget > ( ) ;
ReplaceNode ( targetRef , scopedInvocationTarget ) ;
scopedInvocationTarget - > mTarget = targetRef ;
targetRef = scopedInvocationTarget ;
if ( colonToken = = NULL )
return scopedInvocationTarget ;
MEMBER_SET ( scopedInvocationTarget , mColonToken , colonToken ) ;
mVisitorPos . MoveNext ( ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( ( nextToken - > GetToken ( ) = = BfToken_Colon ) | | ( nextToken - > GetToken ( ) = = BfToken_Mixin ) )
{
MEMBER_SET ( scopedInvocationTarget , mScopeName , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
}
}
else if ( auto identifier = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . GetNext ( ) ) )
{
MEMBER_SET ( scopedInvocationTarget , mScopeName , identifier ) ;
mVisitorPos . MoveNext ( ) ;
}
if ( scopedInvocationTarget - > mScopeName = = NULL )
{
FailAfter ( " Expected scope name " , scopedInvocationTarget ) ;
}
return scopedInvocationTarget ;
}
BfAstNode * BfReducer : : CreateAllocNode ( BfTokenNode * allocToken )
{
if ( allocToken - > GetToken ( ) = = BfToken_Scope )
{
auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) ;
if ( ( nextToken ! = NULL ) & & ( nextToken - > GetToken ( ) = = BfToken_Colon ) )
{
auto scopeNode = mAlloc - > Alloc < BfScopeNode > ( ) ;
ReplaceNode ( allocToken , scopeNode ) ;
scopeNode - > mScopeToken = allocToken ;
MEMBER_SET ( scopeNode , mColonToken , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( ( nextToken - > GetToken ( ) = = BfToken_Colon ) | | ( nextToken - > GetToken ( ) = = BfToken_Mixin ) )
{
MEMBER_SET ( scopeNode , mTargetNode , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
}
}
else if ( auto identifier = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . GetNext ( ) ) )
{
MEMBER_SET ( scopeNode , mTargetNode , identifier ) ;
mVisitorPos . MoveNext ( ) ;
}
if ( scopeNode - > mTargetNode = = NULL )
{
FailAfter ( " Expected scope name " , scopeNode ) ;
}
return scopeNode ;
}
}
if ( allocToken - > GetToken ( ) = = BfToken_New )
{ //
auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) ;
if ( ( nextToken ! = NULL ) & & ( nextToken - > GetToken ( ) = = BfToken_Colon ) )
{ //
auto newNode = mAlloc - > Alloc < BfNewNode > ( ) ;
ReplaceNode ( allocToken , newNode ) ;
newNode - > mNewToken = allocToken ;
MEMBER_SET ( newNode , mColonToken , nextToken ) ;
mVisitorPos . MoveNext ( ) ;
if ( auto nextTokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
BfToken nextToken = nextTokenNode - > GetToken ( ) ;
if ( ( nextToken = = BfToken_LParen ) | | ( nextToken = = BfToken_This ) | | ( nextToken = = BfToken_Null ) )
{
auto allocExpr = CreateExpressionAfter ( newNode , ( CreateExprFlags ) ( CreateExprFlags_NoCast | CreateExprFlags_ExitOnParenExpr ) ) ;
if ( allocExpr ! = NULL )
{
MEMBER_SET ( newNode , mAllocNode , allocExpr ) ;
}
}
}
else
{
int endNodeIdx = - 1 ;
int nodeIdx = mVisitorPos . mReadPos ;
mVisitorPos . MoveNext ( ) ;
if ( IsTypeReference ( mVisitorPos . GetCurrent ( ) , BfToken_Bang , & endNodeIdx ) )
{
if ( auto bangToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( endNodeIdx ) ) )
{
if ( auto prevIdentifier = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . Get ( endNodeIdx - 1 ) ) )
{
if ( bangToken - > GetSrcStart ( ) = = prevIdentifier - > GetSrcEnd ( ) )
{
if ( endNodeIdx = = nodeIdx + 2 )
{
MEMBER_SET ( newNode , mAllocNode , prevIdentifier ) ;
prevIdentifier - > SetSrcEnd ( bangToken - > GetSrcEnd ( ) ) ;
}
else
{
mVisitorPos . mReadPos = nodeIdx + 1 ;
BfExpression * expr = CreateExpression ( mVisitorPos . Get ( nodeIdx + 1 ) , CreateExprFlags_ExitOnBang ) ;
expr - > SetSrcEnd ( bangToken - > GetSrcEnd ( ) ) ;
MEMBER_SET ( newNode , mAllocNode , expr ) ;
BfAstNode * memberNode = expr ;
if ( auto memberRefExpr = BfNodeDynCast < BfMemberReferenceExpression > ( expr ) )
{
memberNode = memberRefExpr - > mMemberName ;
}
else if ( auto qualifiedIdentifier = BfNodeDynCast < BfQualifiedNameNode > ( expr ) )
{
memberNode = qualifiedIdentifier - > mRight ;
}
if ( memberNode ! = NULL )
memberNode - > SetSrcEnd ( bangToken - > GetSrcEnd ( ) ) ;
}
newNode - > SetSrcEnd ( bangToken - > GetSrcEnd ( ) ) ;
mVisitorPos . mReadPos = endNodeIdx ;
BfTokenNode * colonToken = NULL ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( endNodeIdx + 1 ) ) )
{
if ( nextToken - > GetToken ( ) = = BfToken_Colon )
colonToken = nextToken ;
}
auto scopedInvocationTarget = CreateScopedInvocationTarget ( newNode - > mAllocNode , colonToken ) ;
newNode - > SetSrcEnd ( scopedInvocationTarget - > GetSrcEnd ( ) ) ;
}
}
}
}
if ( newNode - > mAllocNode = = NULL )
{
mVisitorPos . mReadPos = nodeIdx ;
if ( auto identifier = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . GetNext ( ) ) )
{
MEMBER_SET ( newNode , mAllocNode , identifier ) ;
mVisitorPos . MoveNext ( ) ;
}
// This causes parse ambiguities
/*mVisitorPos.mReadPos = nodeIdx;
auto allocExpr = CreateExpressionAfter ( newNode , BfReducer : : CreateExprFlags_NoCast ) ;
if ( allocExpr ! = NULL )
{
MEMBER_SET ( newNode , mAllocNode , allocExpr ) ;
} */
}
}
if ( newNode - > mAllocNode = = NULL )
{
FailAfter ( " Expected allocator expression " , newNode ) ;
}
return newNode ;
}
}
return allocToken ;
}
BfObjectCreateExpression * BfReducer : : CreateObjectCreateExpression ( BfAstNode * allocNode )
{
auto objectCreateExpr = mAlloc - > Alloc < BfObjectCreateExpression > ( ) ;
BfDeferredAstSizedArray < BfExpression * > arguments ( objectCreateExpr - > mArguments , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( objectCreateExpr - > mCommas , mAlloc ) ;
ReplaceNode ( allocNode , objectCreateExpr ) ;
MEMBER_SET ( objectCreateExpr , mNewNode , allocNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
BfTokenNode * tokenNode ;
// Why did we want this syntax?
// if (tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
// {
// if (tokenNode->GetToken() == BfToken_Star)
// {
// MEMBER_SET(objectCreateExpr, mStarToken, tokenNode);
// mVisitorPos.MoveNext();
// }
// }
auto typeRef = CreateTypeRefAfter ( objectCreateExpr ) ;
if ( typeRef = = NULL )
return objectCreateExpr ;
if ( auto ptrType = BfNodeDynCast < BfPointerTypeRef > ( typeRef ) )
{
if ( auto arrayType = BfNodeDynCast < BfArrayTypeRef > ( ptrType - > mElementType ) )
{
MEMBER_SET ( objectCreateExpr , mStarToken , ptrType - > mStarNode ) ;
typeRef = ptrType - > mElementType ;
}
}
MEMBER_SET ( objectCreateExpr , mTypeRef , typeRef ) ;
if ( auto block = BfNodeDynCast < BfBlock > ( mVisitorPos . GetNext ( ) ) )
{
mVisitorPos . MoveNext ( ) ;
MEMBER_SET ( objectCreateExpr , mOpenToken , block - > mOpenBrace ) ;
//
{
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( block ) ) ;
ReadArguments ( objectCreateExpr , objectCreateExpr , & arguments , & commas , BfToken_None , true ) ;
}
MEMBER_SET ( objectCreateExpr , mCloseToken , block - > mCloseBrace ) ;
return objectCreateExpr ;
}
tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) ;
if ( tokenNode = = NULL )
return objectCreateExpr ;
if ( tokenNode - > GetToken ( ) ! = BfToken_LParen )
return objectCreateExpr ;
mVisitorPos . MoveNext ( ) ;
MEMBER_SET ( objectCreateExpr , mOpenToken , tokenNode ) ;
BfToken endToken = ( BfToken ) ( tokenNode - > GetToken ( ) + 1 ) ;
tokenNode = ReadArguments ( objectCreateExpr , objectCreateExpr , & arguments , & commas , BfToken_RParen , true ) ;
if ( tokenNode = = NULL )
return objectCreateExpr ;
MEMBER_SET ( objectCreateExpr , mCloseToken , tokenNode ) ;
return objectCreateExpr ;
}
BfExpression * BfReducer : : CreateIndexerExpression ( BfExpression * target )
{
auto tokenNode = ExpectTokenAfter ( target , BfToken_LBracket , BfToken_QuestionLBracket ) ;
auto indexerExpr = mAlloc - > Alloc < BfIndexerExpression > ( ) ;
BfDeferredAstSizedArray < BfExpression * > arguments ( indexerExpr - > mArguments , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( indexerExpr - > mCommas , mAlloc ) ;
indexerExpr - > mTarget = target ;
ReplaceNode ( target , indexerExpr ) ;
indexerExpr - > mOpenBracket = tokenNode ;
MoveNode ( indexerExpr - > mOpenBracket , indexerExpr ) ;
BfAstNode * argAfterNode = indexerExpr ;
BfAttributeDirective * attributeDirective = NULL ;
if ( auto tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( tokenNode - > mToken = = BfToken_LBracket )
{
mVisitorPos . MoveNext ( ) ;
attributeDirective = CreateAttributeDirective ( tokenNode ) ;
argAfterNode = attributeDirective ;
}
}
indexerExpr - > mCloseBracket = ReadArguments ( indexerExpr , argAfterNode , & arguments , & commas , BfToken_RBracket , false ) ;
if ( attributeDirective ! = NULL )
{
BfAttributedExpression * attribExpr = mAlloc - > Alloc < BfAttributedExpression > ( ) ;
attribExpr - > mAttributes = attributeDirective ;
MEMBER_SET ( attribExpr , mExpression , indexerExpr ) ;
return attribExpr ;
}
return indexerExpr ;
}
BfMemberReferenceExpression * BfReducer : : CreateMemberReferenceExpression ( BfAstNode * target )
{
auto tokenNode = ExpectTokenAfter ( target , BfToken_Dot , BfToken_DotDot , BfToken_QuestionDot ) ;
auto memberReferenceExpr = mAlloc - > Alloc < BfMemberReferenceExpression > ( ) ;
if ( target ! = NULL )
{
memberReferenceExpr - > mTarget = target ;
ReplaceNode ( target , memberReferenceExpr ) ;
}
MEMBER_SET_CHECKED ( memberReferenceExpr , mDotToken , tokenNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto literalExpr = BfNodeDynCast < BfLiteralExpression > ( nextNode ) )
{
// Special case for "tuple.0" type references
if ( literalExpr - > mValue . mTypeCode = = BfTypeCode_IntUnknown )
{
MEMBER_SET ( memberReferenceExpr , mMemberName , literalExpr ) ;
mVisitorPos . MoveNext ( ) ;
return memberReferenceExpr ;
}
}
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_LBracket )
{
mVisitorPos . MoveNext ( ) ;
auto attrIdentifier = CreateAttributedExpression ( tokenNode , true ) ;
if ( attrIdentifier ! = NULL )
{
MEMBER_SET ( memberReferenceExpr , mMemberName , attrIdentifier ) ;
}
}
}
if ( memberReferenceExpr - > mMemberName = = NULL )
{
auto memberName = ExpectIdentifierAfter ( memberReferenceExpr ) ;
if ( memberName ! = NULL )
{
MEMBER_SET ( memberReferenceExpr , mMemberName , memberName ) ;
}
}
return memberReferenceExpr ;
}
BfTupleExpression * BfReducer : : CreateTupleExpression ( BfTokenNode * node , BfExpression * innerExpr )
{
auto tupleExpr = mAlloc - > Alloc < BfTupleExpression > ( ) ;
ReplaceNode ( node , tupleExpr ) ;
tupleExpr - > mOpenParen = node ;
BfDeferredAstSizedArray < BfTupleNameNode * > names ( tupleExpr - > mNames , mAlloc ) ;
BfDeferredAstSizedArray < BfExpression * > values ( tupleExpr - > mValues , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( tupleExpr - > mCommas , mAlloc ) ;
while ( true )
{
BfTokenNode * closeParenToken ;
if ( innerExpr = = NULL )
{
bool skipExpr = false ;
if ( values . size ( ) ! = 0 )
{
if ( auto nextToken = BfNodeDynCastExact < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( nextToken - > GetToken ( ) = = BfToken_RParen )
{
// Unterminated - default initialize
skipExpr = true ;
}
}
}
if ( ! skipExpr )
innerExpr = CreateExpressionAfter ( tupleExpr , CreateExprFlags_PermissiveVariableDecl ) ;
}
if ( innerExpr = = NULL )
{
// Failed, but can we pull in the closing rparen?
auto nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( closeParenToken = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( closeParenToken - > GetToken ( ) = = BfToken_RParen )
{
MEMBER_SET ( tupleExpr , mCloseParen , closeParenToken ) ;
mVisitorPos . MoveNext ( ) ;
}
}
break ;
}
if ( innerExpr - > IsA < BfIdentifierNode > ( ) )
closeParenToken = ExpectTokenAfter ( innerExpr , BfToken_RParen , BfToken_Comma , BfToken_Colon ) ;
else
closeParenToken = ExpectTokenAfter ( innerExpr , BfToken_RParen , BfToken_Comma ) ;
if ( closeParenToken = = NULL )
{
values . push_back ( innerExpr ) ;
MoveNode ( innerExpr , tupleExpr ) ;
break ;
}
//TODO: Why did we have this compat mode thing? It kept us from properly creating tuples with names
if ( ( closeParenToken - > GetToken ( ) = = BfToken_Colon ) /*&& (!mCompatMode)*/ )
{
BfTupleNameNode * tupleNameNode = mAlloc - > Alloc < BfTupleNameNode > ( ) ;
ReplaceNode ( innerExpr , tupleNameNode ) ;
tupleNameNode - > mNameNode = ( BfIdentifierNode * ) innerExpr ;
MEMBER_SET ( tupleNameNode , mColonToken , closeParenToken ) ;
while ( ( int ) values . size ( ) > names . size ( ) )
names . push_back ( NULL ) ;
names . push_back ( tupleNameNode ) ;
MoveNode ( tupleNameNode , tupleExpr ) ;
innerExpr = CreateExpressionAfter ( tupleExpr ) ;
if ( innerExpr = = NULL )
break ;
closeParenToken = ExpectTokenAfter ( innerExpr , BfToken_RParen , BfToken_Comma ) ;
}
values . push_back ( innerExpr ) ;
MoveNode ( innerExpr , tupleExpr ) ;
innerExpr = NULL ;
if ( closeParenToken = = NULL )
break ;
if ( closeParenToken - > GetToken ( ) = = BfToken_RParen )
{
MEMBER_SET ( tupleExpr , mCloseParen , closeParenToken ) ;
break ;
}
commas . push_back ( closeParenToken ) ;
MoveNode ( closeParenToken , tupleExpr ) ;
}
return tupleExpr ;
}
BfAstNode * BfReducer : : HandleTopLevel ( BfBlock * node )
{
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( node ) ) ;
BfAstNode * prevNode = NULL ;
bool hadPrevFail = false ;
bool isDone = ! mVisitorPos . MoveNext ( ) ;
while ( ! isDone )
{
auto child = mVisitorPos . GetCurrent ( ) ;
if ( child = = prevNode )
{
// If we're stuck on an error and can't process any more nodes
break ;
}
prevNode = child ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( child ) ;
if ( tokenNode = = NULL )
{
if ( ! hadPrevFail )
Fail ( " Namespace or type declaration expected " , child ) ;
hadPrevFail = true ;
isDone = ! mVisitorPos . MoveNext ( ) ;
mVisitorPos . Write ( child ) ; // Just keep it...
continue ;
}
auto newNode = CreateTopLevelObject ( tokenNode , NULL ) ;
hadPrevFail = newNode = = NULL ;
isDone = ! mVisitorPos . MoveNext ( ) ;
if ( newNode ! = NULL )
mVisitorPos . Write ( newNode ) ;
}
mVisitorPos . Trim ( ) ;
return node ;
}
BfAstNode * BfReducer : : CreateTopLevelObject ( BfTokenNode * tokenNode , BfAttributeDirective * attributes )
{
AssertCurrentNode ( tokenNode ) ;
bool isSimpleEnum = false ;
if ( tokenNode - > GetToken ( ) = = BfToken_Enum )
{
int checkReadPos = mVisitorPos . mReadPos + 1 ;
// Do we just have a value list with no members?
auto nextNode = mVisitorPos . Get ( checkReadPos ) ;
auto checkNode = nextNode ;
while ( checkNode ! = NULL )
{
if ( auto block = BfNodeDynCast < BfBlock > ( checkNode ) )
{
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( block ) ) ;
mVisitorPos . MoveNext ( ) ;
BfAstNode * headNode = block - > mChildArr . GetAs < BfAstNode * > ( 0 ) ;
if ( auto nameNode = BfNodeDynCast < BfIdentifierNode > ( headNode ) )
{
auto nextNode = mVisitorPos . Get ( 1 ) ;
if ( auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( ( nextToken - > GetToken ( ) = = BfToken_Comma ) | | ( nextToken - > GetToken ( ) = = BfToken_AssignEquals ) )
isSimpleEnum = true ;
}
if ( nextNode = = NULL )
isSimpleEnum = true ;
}
break ;
}
checkReadPos + + ;
auto nextCheckNode = mVisitorPos . Get ( checkReadPos ) ;
checkNode = nextCheckNode ;
}
}
switch ( tokenNode - > GetToken ( ) )
{
case BfToken_Using :
{
if ( auto nextTokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( nextTokenNode - > mToken = = BfToken_Static )
{
auto usingDirective = mAlloc - > Alloc < BfUsingStaticDirective > ( ) ;
ReplaceNode ( tokenNode , usingDirective ) ;
usingDirective - > mUsingToken = tokenNode ;
MEMBER_SET ( usingDirective , mStaticToken , nextTokenNode ) ;
mVisitorPos . MoveNext ( ) ;
auto typeRef = CreateTypeRefAfter ( usingDirective ) ;
if ( typeRef ! = NULL )
MEMBER_SET ( usingDirective , mTypeRef , typeRef ) ;
tokenNode = ExpectTokenAfter ( usingDirective , BfToken_Semicolon ) ;
if ( tokenNode ! = NULL )
MEMBER_SET ( usingDirective , mTrailingSemicolon , tokenNode ) ;
mExteriorNodes . Add ( usingDirective ) ;
return usingDirective ;
}
}
auto usingDirective = mAlloc - > Alloc < BfUsingDirective > ( ) ;
ReplaceNode ( tokenNode , usingDirective ) ;
usingDirective - > mUsingToken = tokenNode ;
auto identifierNode = ExpectIdentifierAfter ( usingDirective ) ;
if ( identifierNode ! = NULL )
{
identifierNode = CompactQualifiedName ( identifierNode ) ;
MEMBER_SET ( usingDirective , mNamespace , identifierNode ) ;
tokenNode = ExpectTokenAfter ( usingDirective , BfToken_Semicolon ) ;
if ( tokenNode = = NULL )
{
// Failure, but eat any following dot for autocompletion purposes
auto nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_Dot )
{
auto qualifiedNameNode = mAlloc - > Alloc < BfQualifiedNameNode > ( ) ;
ReplaceNode ( usingDirective - > mNamespace , qualifiedNameNode ) ;
qualifiedNameNode - > mLeft = usingDirective - > mNamespace ;
MEMBER_SET ( qualifiedNameNode , mDot , tokenNode ) ;
usingDirective - > mNamespace = qualifiedNameNode ;
usingDirective - > SetSrcEnd ( qualifiedNameNode - > GetSrcEnd ( ) ) ;
return usingDirective ;
}
}
}
else if ( tokenNode ! = NULL )
{
MEMBER_SET ( usingDirective , mTrailingSemicolon , tokenNode ) ;
}
}
mExteriorNodes . Add ( usingDirective ) ;
return usingDirective ;
}
break ;
case BfToken_Namespace :
{
auto namespaceDeclaration = mAlloc - > Alloc < BfNamespaceDeclaration > ( ) ;
namespaceDeclaration - > mNamespaceNode = tokenNode ;
auto identifierNode = ExpectIdentifierAfter ( tokenNode ) ;
if ( identifierNode = = NULL )
return namespaceDeclaration ;
identifierNode = CompactQualifiedName ( identifierNode ) ;
namespaceDeclaration - > mNameNode = identifierNode ;
ReplaceNode ( tokenNode , namespaceDeclaration ) ;
MoveNode ( identifierNode , namespaceDeclaration ) ;
auto blockNode = ExpectBlockAfter ( namespaceDeclaration ) ;
if ( blockNode = = NULL )
return namespaceDeclaration ;
MoveNode ( blockNode , namespaceDeclaration ) ;
namespaceDeclaration - > mBlock = blockNode ;
HandleTopLevel ( namespaceDeclaration - > mBlock ) ;
return namespaceDeclaration ;
}
break ;
case BfToken_LBracket :
{
auto attributes = CreateAttributeDirective ( tokenNode ) ;
if ( attributes = = NULL )
return NULL ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( nextToken = = NULL )
{
FailAfter ( " Expected type declaration " , tokenNode ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
auto topLevelObject = CreateTopLevelObject ( nextToken , attributes ) ;
if ( topLevelObject = = NULL )
return NULL ;
auto typeDeclaration = BfNodeDynCast < BfTypeDeclaration > ( topLevelObject ) ;
if ( typeDeclaration = = NULL )
{
Fail ( " Invalid type specifier " , tokenNode ) ;
return NULL ;
}
typeDeclaration - > mAttributes = attributes ;
ReplaceNode ( attributes , typeDeclaration ) ;
return typeDeclaration ;
}
break ;
case BfToken_Sealed :
case BfToken_Abstract :
case BfToken_Concrete :
case BfToken_Internal :
case BfToken_Public :
case BfToken_Private :
case BfToken_Protected :
case BfToken_Static :
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( ( tokenNode - > GetToken ( ) = = BfToken_Static ) & & BfNodeIsA < BfBlock > ( nextNode ) )
{
// It's a global block!
auto typeDeclaration = mAlloc - > Alloc < BfTypeDeclaration > ( ) ;
ReplaceNode ( tokenNode , typeDeclaration ) ;
typeDeclaration - > mDocumentation = FindDocumentation ( typeDeclaration ) ;
typeDeclaration - > mStaticSpecifier = tokenNode ;
auto block = BfNodeDynCast < BfBlock > ( nextNode ) ;
MEMBER_SET ( typeDeclaration , mDefineNode , block ) ;
mVisitorPos . MoveNext ( ) ;
HandleTypeDeclaration ( typeDeclaration , attributes ) ;
return typeDeclaration ;
}
nextNode = mVisitorPos . GetNext ( ) ;
auto nextToken = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( nextToken = = NULL )
{
AddErrorNode ( tokenNode ) ;
FailAfter ( " Expected type declaration " , tokenNode ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
auto topLevelObject = CreateTopLevelObject ( nextToken , attributes ) ;
if ( topLevelObject = = NULL )
{
AddErrorNode ( tokenNode ) ;
return NULL ;
}
auto typeDeclaration = BfNodeDynCast < BfTypeDeclaration > ( topLevelObject ) ;
if ( typeDeclaration = = NULL )
{
AddErrorNode ( tokenNode ) ;
Fail ( " Invalid type specifier " , tokenNode ) ;
return NULL ;
}
ReplaceNode ( tokenNode , typeDeclaration ) ;
BfToken token = tokenNode - > GetToken ( ) ;
if ( ( token = = BfToken_Public ) | |
( token = = BfToken_Protected ) | |
( token = = BfToken_Private ) )
{
if ( typeDeclaration - > mProtectionSpecifier ! = NULL )
{
Fail ( " Protection already specified " , tokenNode ) ;
}
MEMBER_SET ( typeDeclaration , mProtectionSpecifier , tokenNode ) ;
}
if ( token = = BfToken_Internal )
{
if ( typeDeclaration - > mInternalSpecifier ! = NULL )
{
Fail ( " Internal already specified " , typeDeclaration - > mInternalSpecifier ) ;
}
MEMBER_SET ( typeDeclaration , mInternalSpecifier , tokenNode ) ;
}
if ( token = = BfToken_Static )
{
if ( typeDeclaration - > mStaticSpecifier ! = NULL )
{
Fail ( " Static already specified " , tokenNode ) ;
}
MEMBER_SET ( typeDeclaration , mStaticSpecifier , tokenNode ) ;
}
if ( token = = BfToken_Sealed )
{
if ( typeDeclaration - > mSealedSpecifier ! = NULL )
{
Fail ( " Sealed already specified " , tokenNode ) ;
}
MEMBER_SET ( typeDeclaration , mSealedSpecifier , tokenNode ) ;
}
if ( ( token = = BfToken_Abstract ) | | ( token = = BfToken_Concrete ) )
{
if ( typeDeclaration - > mAbstractSpecifier ! = NULL )
{
Fail ( StrFormat ( " '%s' already specified " , typeDeclaration - > mAbstractSpecifier - > ToString ( ) . c_str ( ) ) , tokenNode ) ;
}
MEMBER_SET ( typeDeclaration , mAbstractSpecifier , tokenNode ) ;
}
//TODO: Store type specifiers
return typeDeclaration ;
}
break ;
case BfToken_Delegate :
case BfToken_Function :
{
auto typeDeclaration = mAlloc - > Alloc < BfTypeDeclaration > ( ) ;
SetAndRestoreValue < BfTypeDeclaration * > prevTypeDecl ( mCurTypeDecl , typeDeclaration ) ;
ReplaceNode ( tokenNode , typeDeclaration ) ;
typeDeclaration - > mDocumentation = FindDocumentation ( typeDeclaration ) ;
typeDeclaration - > mTypeNode = tokenNode ;
auto retType = CreateTypeRefAfter ( typeDeclaration ) ;
if ( retType = = NULL )
return typeDeclaration ;
auto methodDecl = mAlloc - > Alloc < BfMethodDeclaration > ( ) ;
MEMBER_SET ( methodDecl , mReturnType , retType ) ;
BfDeferredAstSizedArray < BfParameterDeclaration * > params ( methodDecl - > mParams , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( methodDecl - > mCommas , mAlloc ) ;
methodDecl - > mDocumentation = FindDocumentation ( methodDecl ) ;
BfBlock * defineBlock = mAlloc - > Alloc < BfBlock > ( ) ;
MoveNode ( defineBlock , typeDeclaration ) ;
BfDeferredAstSizedArray < BfAstNode * > members ( defineBlock - > mChildArr , mAlloc ) ;
members . push_back ( methodDecl ) ;
MoveNode ( methodDecl , typeDeclaration ) ;
typeDeclaration - > mDefineNode = defineBlock ;
auto name = ExpectIdentifierAfter ( retType ) ;
if ( name = = NULL )
{
ReplaceNode ( retType , methodDecl ) ;
return typeDeclaration ;
}
ReplaceNode ( name , methodDecl ) ;
MEMBER_SET_CHECKED ( typeDeclaration , mNameNode , name ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_LChevron )
{
auto genericParams = CreateGenericParamsDeclaration ( tokenNode ) ;
MEMBER_SET_CHECKED ( typeDeclaration , mGenericParams , genericParams ) ;
methodDecl - > SetSrcEnd ( genericParams - > GetSrcEnd ( ) ) ;
}
}
if ( ! ParseMethod ( methodDecl , & params , & commas ) )
return typeDeclaration ;
if ( methodDecl - > mEndSemicolon = = NULL )
FailAfter ( " Expected ';' " , methodDecl - > mCloseParen ) ;
//MEMBER_SET(methodDecl, mReturnType, retType);
return typeDeclaration ;
}
break ;
case BfToken_TypeAlias :
{
auto identifierNode = ExpectIdentifierAfter ( tokenNode ) ;
if ( identifierNode = = NULL )
return NULL ;
auto typeDeclaration = mAlloc - > Alloc < BfTypeAliasDeclaration > ( ) ;
BfDeferredAstSizedArray < BfTypeReference * > baseClasses ( typeDeclaration - > mBaseClasses , mAlloc ) ;
BfDeferredAstSizedArray < BfAstNode * > baseClassCommas ( typeDeclaration - > mBaseClassCommas , mAlloc ) ;
mLastTypeDecl = typeDeclaration ;
typeDeclaration - > mTypeNode = tokenNode ;
typeDeclaration - > mNameNode = identifierNode ;
ReplaceNode ( tokenNode , typeDeclaration ) ;
MoveNode ( identifierNode , typeDeclaration ) ;
typeDeclaration - > mDocumentation = FindDocumentation ( typeDeclaration ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto chevronToken = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( chevronToken ! = NULL ) & & ( chevronToken - > GetToken ( ) = = BfToken_LChevron ) )
{
auto genericMethodParams = CreateGenericParamsDeclaration ( chevronToken ) ;
if ( genericMethodParams ! = NULL )
{
MEMBER_SET ( typeDeclaration , mGenericParams , genericMethodParams ) ;
}
}
auto tokenNode = ExpectTokenAfter ( typeDeclaration , BfToken_AssignEquals ) ;
if ( tokenNode ! = NULL )
{
MEMBER_SET ( typeDeclaration , mEqualsToken , tokenNode ) ;
auto aliasToType = CreateTypeRefAfter ( typeDeclaration ) ;
if ( aliasToType ! = NULL )
{
MEMBER_SET ( typeDeclaration , mAliasToType , aliasToType ) ;
auto tokenNode = ExpectTokenAfter ( typeDeclaration , BfToken_Semicolon ) ;
if ( tokenNode ! = NULL )
MEMBER_SET ( typeDeclaration , mEndSemicolon , tokenNode ) ;
}
}
if ( ! IsNodeRelevant ( typeDeclaration ) )
typeDeclaration - > mIgnoreDeclaration = true ;
return typeDeclaration ;
}
break ;
case BfToken_Class :
case BfToken_Struct :
case BfToken_Interface :
case BfToken_Enum :
case BfToken_Extension :
{
if ( ( tokenNode - > GetToken ( ) = = BfToken_Enum ) & & ( isSimpleEnum ) )
break ;
auto identifierNode = ExpectIdentifierAfter ( tokenNode ) ;
if ( identifierNode = = NULL )
{
AddErrorNode ( tokenNode ) ;
return NULL ;
}
// We put extra effort in here to continue after failure, since 'return NULL' failure
// means we don't parse members inside type (messes up colorization and such)
auto typeDeclaration = mAlloc - > Alloc < BfTypeDeclaration > ( ) ;
BfDeferredAstSizedArray < BfTypeReference * > baseClasses ( typeDeclaration - > mBaseClasses , mAlloc ) ;
BfDeferredAstSizedArray < BfAstNode * > baseClassCommas ( typeDeclaration - > mBaseClassCommas , mAlloc ) ;
mLastTypeDecl = typeDeclaration ;
typeDeclaration - > mTypeNode = tokenNode ;
typeDeclaration - > mNameNode = identifierNode ;
ReplaceNode ( tokenNode , typeDeclaration ) ;
MoveNode ( identifierNode , typeDeclaration ) ;
typeDeclaration - > mDocumentation = FindDocumentation ( typeDeclaration ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto chevronToken = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( chevronToken ! = NULL ) & & ( chevronToken - > GetToken ( ) = = BfToken_LChevron ) )
{
auto genericMethodParams = CreateGenericParamsDeclaration ( chevronToken ) ;
if ( genericMethodParams ! = NULL )
{
MEMBER_SET ( typeDeclaration , mGenericParams , genericMethodParams ) ;
}
}
nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_Colon ) )
{
MEMBER_SET ( typeDeclaration , mColonToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
tokenNode = NULL ;
for ( int baseTypeIdx = 0 ; true ; baseTypeIdx + + )
{
nextNode = mVisitorPos . GetNext ( ) ;
if ( ( baseTypeIdx > 0 ) & & ( BfNodeDynCast < BfBlock > ( nextNode ) ) )
break ;
if ( baseTypeIdx > 0 )
{
BfTokenNode * commaToken = NULL ;
if ( typeDeclaration - > mGenericParams ! = NULL )
{
commaToken = ExpectTokenAfter ( typeDeclaration , BfToken_Comma , BfToken_Where ) ;
if ( ( commaToken ! = NULL ) & & ( commaToken - > GetToken ( ) = = BfToken_Where ) )
{
mVisitorPos . mReadPos - - ;
break ;
}
}
else
commaToken = ExpectTokenAfter ( typeDeclaration , BfToken_Comma ) ;
if ( commaToken = = NULL )
break ;
MoveNode ( commaToken , typeDeclaration ) ;
baseClassCommas . push_back ( commaToken ) ;
}
auto baseType = CreateTypeRefAfter ( typeDeclaration ) ;
if ( baseType = = NULL )
break ;
MoveNode ( baseType , typeDeclaration ) ;
baseClasses . push_back ( baseType ) ;
}
nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
}
if ( tokenNode ! = NULL )
{
if ( tokenNode - > GetToken ( ) = = BfToken_Where )
{
mVisitorPos . MoveNext ( ) ;
auto constraints = CreateGenericConstraintsDeclaration ( tokenNode ) ;
if ( constraints ! = NULL )
{
MEMBER_SET ( typeDeclaration , mGenericConstraintsDeclaration , constraints ) ;
}
}
if ( tokenNode - > GetToken ( ) = = BfToken_Semicolon )
{
typeDeclaration - > mDefineNode = tokenNode ;
MoveNode ( tokenNode , typeDeclaration ) ;
mVisitorPos . MoveNext ( ) ;
return typeDeclaration ;
}
}
auto blockNode = ExpectBlockAfter ( typeDeclaration ) ;
if ( blockNode ! = NULL )
{
typeDeclaration - > mDefineNode = blockNode ;
MoveNode ( blockNode , typeDeclaration ) ;
HandleTypeDeclaration ( typeDeclaration , attributes ) ;
}
2019-10-14 14:08:29 -07:00
return typeDeclaration ;
2019-08-23 11:56:54 -07:00
}
break ;
2019-10-14 14:08:29 -07:00
default : break ;
2019-08-23 11:56:54 -07:00
}
if ( isSimpleEnum )
{
auto identifierNode = ExpectIdentifierAfter ( tokenNode , " enum name " ) ;
if ( identifierNode = = NULL )
return NULL ;
// We put extra effort in here to continue after failure, since 'return NULL' failure
// means we don't parse members inside type (messes up colorization and such)
auto typeDeclaration = mAlloc - > Alloc < BfTypeDeclaration > ( ) ;
BfDeferredAstSizedArray < BfTypeReference * > baseClasses ( typeDeclaration - > mBaseClasses , mAlloc ) ;
auto prevTypeDecl = mCurTypeDecl ;
mCurTypeDecl = typeDeclaration ;
typeDeclaration - > mTypeNode = tokenNode ;
typeDeclaration - > mNameNode = identifierNode ;
ReplaceNode ( tokenNode , typeDeclaration ) ;
MoveNode ( identifierNode , typeDeclaration ) ;
typeDeclaration - > mDocumentation = FindDocumentation ( typeDeclaration ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_Colon ) )
{
MEMBER_SET ( typeDeclaration , mColonToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
tokenNode = NULL ;
auto baseType = CreateTypeRefAfter ( typeDeclaration ) ;
if ( baseType = = NULL )
return NULL ;
MoveNode ( baseType , typeDeclaration ) ;
baseClasses . push_back ( baseType ) ;
}
auto blockNode = ExpectBlockAfter ( typeDeclaration ) ;
if ( blockNode ! = NULL )
{
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( blockNode ) ) ;
mVisitorPos . MoveNext ( ) ;
for ( int fieldNum = 0 ; true ; fieldNum + + )
{
BfAstNode * child = mVisitorPos . GetCurrent ( ) ;
if ( child = = NULL )
break ;
if ( fieldNum > 0 )
{
auto commaToken = BfNodeDynCast < BfTokenNode > ( child ) ;
if ( ( commaToken = = NULL ) | | ( commaToken - > GetToken ( ) ! = BfToken_Comma ) )
{
Fail ( " Comma expected " , child ) ;
break ;
}
MoveNode ( commaToken , mCurTypeDecl ) ;
mVisitorPos . MoveNext ( ) ;
mVisitorPos . Write ( commaToken ) ;
child = mVisitorPos . GetCurrent ( ) ;
}
if ( child = = NULL )
break ;
auto fieldDecl = mAlloc - > Alloc < BfEnumEntryDeclaration > ( ) ;
mVisitorPos . MoveNext ( ) ;
mVisitorPos . Write ( fieldDecl ) ;
ReplaceNode ( child , fieldDecl ) ;
auto valueName = BfNodeDynCast < BfIdentifierNode > ( child ) ;
if ( valueName = = NULL )
{
Fail ( " Enum value name expected " , child ) ;
break ;
}
MEMBER_SET ( fieldDecl , mNameNode , valueName ) ;
auto nextNode = mVisitorPos . GetCurrent ( ) ;
if ( auto equalsToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( equalsToken - > GetToken ( ) = = BfToken_AssignEquals )
{
MEMBER_SET ( fieldDecl , mEqualsNode , equalsToken ) ;
fieldDecl - > mInitializer = CreateExpressionAfter ( fieldDecl ) ;
if ( fieldDecl - > mInitializer ! = NULL )
{
mVisitorPos . MoveNext ( ) ;
MoveNode ( fieldDecl - > mInitializer , fieldDecl ) ;
}
}
}
fieldDecl - > mDocumentation = FindDocumentation ( fieldDecl , NULL , true ) ;
MoveNode ( fieldDecl , mCurTypeDecl ) ;
}
mVisitorPos . Trim ( ) ;
}
typeDeclaration - > mDefineNode = blockNode ;
if ( blockNode ! = NULL )
{
MoveNode ( blockNode , typeDeclaration ) ;
}
mCurTypeDecl = prevTypeDecl ;
return typeDeclaration ;
}
Fail ( " Unexpected token " , tokenNode ) ;
return NULL ;
}
BfTokenNode * BfReducer : : ExpectTokenAfter ( BfAstNode * node , BfToken token )
{
AssertCurrentNode ( node ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( tokenNode = = NULL ) | |
( tokenNode - > GetToken ( ) ! = token ) )
{
FailAfter ( StrFormat ( " Expected '%s' " , BfTokenToString ( token ) ) , node ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
return tokenNode ;
}
BfTokenNode * BfReducer : : ExpectTokenAfter ( BfAstNode * node , BfToken tokenA , BfToken tokenB )
{
AssertCurrentNode ( node ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( tokenNode = = NULL ) | |
( ( tokenNode - > GetToken ( ) ! = tokenA ) & & ( tokenNode - > GetToken ( ) ! = tokenB ) ) )
{
FailAfter ( StrFormat ( " Expected '%s' or '%s' " , BfTokenToString ( tokenA ) , BfTokenToString ( tokenB ) ) , node ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
return tokenNode ;
}
BfTokenNode * BfReducer : : ExpectTokenAfter ( BfAstNode * node , BfToken tokenA , BfToken tokenB , BfToken tokenC )
{
AssertCurrentNode ( node ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
BfToken token = BfToken_Null ;
if ( tokenNode ! = NULL )
token = tokenNode - > GetToken ( ) ;
if ( ( tokenNode = = NULL ) | |
( ( token ! = tokenA ) & & ( token ! = tokenB ) & & ( token ! = tokenC ) ) )
{
FailAfter ( StrFormat ( " Expected '%s', '%s', or '%s' " , BfTokenToString ( tokenA ) , BfTokenToString ( tokenB ) , BfTokenToString ( tokenC ) ) , node ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
return tokenNode ;
}
BfTokenNode * BfReducer : : ExpectTokenAfter ( BfAstNode * node , BfToken tokenA , BfToken tokenB , BfToken tokenC , BfToken tokenD )
{
AssertCurrentNode ( node ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
BfToken token = BfToken_Null ;
if ( tokenNode ! = NULL )
token = tokenNode - > GetToken ( ) ;
if ( ( tokenNode = = NULL ) | |
( ( token ! = tokenA ) & & ( token ! = tokenB ) & & ( token ! = tokenC ) & & ( token ! = tokenD ) ) )
{
FailAfter ( StrFormat ( " Expected '%s', '%s', '%s', or '%s' " , BfTokenToString ( tokenA ) , BfTokenToString ( tokenB ) , BfTokenToString ( tokenC ) , BfTokenToString ( tokenD ) ) , node ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
return tokenNode ;
}
BfIdentifierNode * BfReducer : : ExpectIdentifierAfter ( BfAstNode * node , const char * typeName )
{
AssertCurrentNode ( node ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto identifierNode = BfNodeDynCast < BfIdentifierNode > ( nextNode ) ;
if ( identifierNode = = NULL )
{
if ( typeName ! = NULL )
FailAfter ( StrFormat ( " Expected %s " , typeName ) , node ) ;
else
FailAfter ( " Expected identifier " , node ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
return identifierNode ;
}
BfBlock * BfReducer : : ExpectBlockAfter ( BfAstNode * node )
{
AssertCurrentNode ( node ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto block = BfNodeDynCast < BfBlock > ( nextNode ) ;
if ( block = = NULL )
{
FailAfter ( " Block expected " , node ) ;
return NULL ;
}
mVisitorPos . MoveNext ( ) ;
return block ;
}
BfTokenNode * BfReducer : : BreakDoubleChevron ( BfTokenNode * tokenNode )
{
// Break up those chevrons
auto firstChevron = mAlloc - > Alloc < BfTokenNode > ( ) ;
firstChevron - > SetToken ( BfToken_RChevron ) ;
int triviaStart ;
int srcStart ;
int srcEnd ;
tokenNode - > GetSrcPositions ( triviaStart , srcStart , srcEnd ) ;
firstChevron - > Init ( triviaStart , srcStart , srcEnd - 1 ) ;
tokenNode - > SetToken ( BfToken_RChevron ) ;
tokenNode - > SetSrcStart ( srcStart + 1 ) ;
tokenNode - > SetTriviaStart ( srcStart ) ;
return firstChevron ;
}
BfTokenNode * BfReducer : : BreakQuestionLBracket ( BfTokenNode * tokenNode )
{
// Break up those chevrons
auto firstToken = mAlloc - > Alloc < BfTokenNode > ( ) ;
firstToken - > SetToken ( BfToken_Question ) ;
int triviaStart ;
int srcStart ;
int srcEnd ;
tokenNode - > GetSrcPositions ( triviaStart , srcStart , srcEnd ) ;
firstToken - > Init ( triviaStart , srcStart , srcEnd - 1 ) ;
tokenNode - > SetToken ( BfToken_LBracket ) ;
tokenNode - > SetSrcStart ( srcStart + 1 ) ;
tokenNode - > SetTriviaStart ( srcStart ) ;
return firstToken ;
}
BfCommentNode * BfReducer : : FindDocumentation ( BfAstNode * defNodeHead , BfAstNode * defNodeEnd , bool checkDocAfter )
{
if ( defNodeEnd = = NULL )
defNodeEnd = defNodeHead ;
else if ( defNodeHead = = NULL )
defNodeHead = defNodeEnd ;
while ( mDocumentCheckIdx < mSource - > mSidechannelRootNode - > mChildArr . mSize )
{
auto checkComment = BfNodeDynCast < BfCommentNode > ( mSource - > mSidechannelRootNode - > mChildArr [ mDocumentCheckIdx ] ) ;
if ( ( checkComment = = NULL ) | | ( checkComment - > mCommentKind = = BfCommentKind_Normal ) )
{
mDocumentCheckIdx + + ;
continue ;
}
if ( checkComment - > GetSrcEnd ( ) > defNodeEnd - > GetSrcStart ( ) )
{
if ( checkComment - > mCommentKind = = BfCommentKind_Documentation_Post )
{
int defEnd = defNodeEnd - > GetSrcEnd ( ) ;
if ( checkDocAfter )
{
int endDiff = defEnd - checkComment - > GetSrcStart ( ) ;
if ( endDiff > 256 )
return NULL ;
for ( int idx = defEnd ; idx < checkComment - > GetSrcStart ( ) ; idx + + )
{
char c = mSource - > mSrc [ idx ] ;
if ( idx = = defEnd )
{
if ( ( c = = ' ; ' ) | | ( c = = ' , ' ) )
continue ;
}
if ( c = = ' \n ' )
return NULL ; // No newline allowed
if ( ! isspace ( ( uint8 ) c ) )
return NULL ;
}
mDocumentCheckIdx + + ;
return checkComment ;
}
}
return NULL ;
}
if ( checkComment - > mCommentKind ! = BfCommentKind_Documentation_Pre )
{
// Skip this, not used
mDocumentCheckIdx + + ;
continue ;
}
if ( mDocumentCheckIdx < mSource - > mSidechannelRootNode - > mChildArr . mSize - 1 )
{
auto nextComment = mSource - > mSidechannelRootNode - > mChildArr [ mDocumentCheckIdx + 1 ] ;
if ( nextComment - > GetSrcEnd ( ) < = defNodeHead - > GetSrcStart ( ) )
{
// This comment is still before the node in question
mDocumentCheckIdx + + ;
continue ;
}
}
mDocumentCheckIdx + + ;
int defSrcIdx = defNodeHead - > GetSrcStart ( ) ;
for ( int idx = checkComment - > GetSrcEnd ( ) ; idx < defSrcIdx ; idx + + )
{
char c = mSource - > mSrc [ idx ] ;
if ( ! isspace ( ( uint8 ) c ) )
return NULL ;
}
return checkComment ;
}
return NULL ;
}
BfTokenNode * BfReducer : : ParseMethodParams ( BfAstNode * node , SizedArrayImpl < BfParameterDeclaration * > * params , SizedArrayImpl < BfTokenNode * > * commas , BfToken endToken )
{
BfAstNode * nameAfterNode = node ;
BfAttributeDirective * attributes = NULL ;
for ( int paramIdx = 0 ; true ; paramIdx + + )
{
auto nextNode = ReplaceTokenStarter ( mVisitorPos . GetNext ( ) , mVisitorPos . mReadPos + 1 ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode ! = NULL )
{
BfToken token = tokenNode - > GetToken ( ) ;
if ( ( paramIdx > 0 ) & & ( token = = BfToken_AssignEquals ) )
{
auto paramDecl = params - > back ( ) ;
MEMBER_SET ( paramDecl , mEqualsNode , tokenNode ) ;
paramDecl - > mEqualsNode = tokenNode ;
mVisitorPos . MoveNext ( ) ;
mSkipCurrentNodeAssert = true ;
auto initExpr = CreateExpressionAfter ( node ) ;
mSkipCurrentNodeAssert = false ;
if ( initExpr = = NULL )
return NULL ;
MEMBER_SET ( paramDecl , mInitializer , initExpr ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode = = NULL )
return NULL ;
token = tokenNode - > GetToken ( ) ;
}
if ( token = = endToken )
return tokenNode ;
if ( ( paramIdx = = 0 ) & & (
( token = = BfToken_Out ) | | ( token = = BfToken_Ref ) | | ( token = = BfToken_Mut ) | |
( token = = BfToken_Delegate ) | | ( token = = BfToken_Function ) | |
( token = = BfToken_Params ) | | ( token = = BfToken_LParen ) | |
( token = = BfToken_Var ) | | ( token = = BfToken_LBracket ) ) )
{
// These get picked up below
}
else
{
if ( ( paramIdx = = 0 ) | | ( token ! = BfToken_Comma ) )
{
Fail ( " Expected ')' or parameter list " , tokenNode ) ;
return NULL ;
}
if ( paramIdx > 0 )
commas - > push_back ( tokenNode ) ;
MoveNode ( tokenNode , node ) ;
mVisitorPos . MoveNext ( ) ;
}
nameAfterNode = tokenNode ;
}
else
{
if ( paramIdx > 0 )
{
FailAfter ( " Expected ')' or additional parameters " , nameAfterNode ) ;
return NULL ;
}
}
attributes = NULL ;
BfTokenNode * modTokenNode = NULL ;
nextNode = ReplaceTokenStarter ( mVisitorPos . GetNext ( ) , mVisitorPos . mReadPos + 1 ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
BfTypeReference * typeRef = NULL ;
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_LBracket ) )
{
mVisitorPos . MoveNext ( ) ;
attributes = CreateAttributeDirective ( tokenNode ) ;
if ( attributes ! = NULL )
{
nameAfterNode = attributes ;
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
}
}
int paramStartReadPos = mVisitorPos . mReadPos ;
bool isParams = false ;
if ( tokenNode ! = NULL )
{
BfToken token = tokenNode - > GetToken ( ) ;
if ( ( token = = BfToken_Var ) | | ( token = = BfToken_LParen ) | |
( token = = BfToken_Delegate ) | | ( token = = BfToken_Function ) )
{
mVisitorPos . MoveNext ( ) ;
typeRef = CreateTypeRef ( tokenNode ) ;
}
else
{
if ( ( token ! = BfToken_Out ) & & ( token ! = BfToken_Ref ) & & ( token ! = BfToken_Mut ) & & ( token ! = BfToken_Params ) )
{
Fail ( " Invalid token " , tokenNode ) ;
return NULL ;
}
if ( token = = BfToken_Params )
isParams = true ;
modTokenNode = tokenNode ;
nameAfterNode = modTokenNode ;
mVisitorPos . MoveNext ( ) ;
}
}
if ( typeRef = = NULL )
{
auto typeIdentifierNode = ExpectIdentifierAfter ( nameAfterNode , " parameter type " ) ;
if ( typeIdentifierNode = = NULL )
{
mVisitorPos . mReadPos = paramStartReadPos ;
break ;
}
typeRef = CreateTypeRef ( typeIdentifierNode ) ;
if ( typeRef = = NULL )
{
mVisitorPos . mReadPos = paramStartReadPos ;
break ;
}
}
BfToken modToken = BfToken_None ;
if ( modTokenNode ! = NULL )
modToken = modTokenNode - > GetToken ( ) ;
if ( ( modTokenNode ! = NULL ) & & ( ( modToken = = BfToken_Ref ) | | ( modToken = = BfToken_Mut ) | | ( modToken = = BfToken_Out ) ) )
{
typeRef = CreateRefTypeRef ( typeRef , modTokenNode ) ;
modTokenNode = NULL ;
}
auto paramDecl = mAlloc - > Alloc < BfParameterDeclaration > ( ) ;
ReplaceNode ( typeRef , paramDecl ) ;
MoveNode ( paramDecl , node ) ;
params - > push_back ( paramDecl ) ;
MEMBER_SET ( paramDecl , mTypeRef , typeRef ) ;
if ( attributes ! = NULL )
{
MEMBER_SET ( paramDecl , mAttributes , attributes ) ;
attributes = NULL ;
}
if ( modTokenNode ! = NULL )
{
MEMBER_SET ( paramDecl , mModToken , modTokenNode ) ;
}
bool allowNameFail = false ;
bool nextIsName = false ;
auto afterNameTokenNode = BfNodeDynCast < BfTokenNode > ( mVisitorPos . Get ( mVisitorPos . mReadPos + 2 ) ) ;
if ( afterNameTokenNode ! = NULL )
{
BfToken afterNameToken = afterNameTokenNode - > GetToken ( ) ;
if ( ( afterNameToken = = BfToken_Comma ) | |
( afterNameToken = = BfToken_AssignEquals ) | |
( afterNameToken = = BfToken_RParen ) )
{
nextIsName = true ;
}
}
// We definitely have a failure, but we want to attempt to scan to the actual param name if we can...
if ( ! nextIsName )
{
int nameIdx = - 1 ;
int checkIdx = mVisitorPos . mReadPos + 1 ;
bool useNameIdx = true ;
int parenDepth = 1 ;
int bracketDepth = 0 ;
while ( true )
{
auto checkNode = mVisitorPos . Get ( checkIdx ) ;
auto checkTokenNode = BfNodeDynCast < BfTokenNode > ( checkNode ) ;
if ( checkTokenNode ! = NULL )
{
BfToken checkToken = checkTokenNode - > GetToken ( ) ;
if ( nameIdx = = - 1 )
{
if ( ( parenDepth = = 1 ) & & ( bracketDepth = = 0 ) )
{
if ( ( checkToken = = BfToken_Comma ) | |
( checkToken = = BfToken_AssignEquals ) | |
( checkToken = = BfToken_RParen ) )
{
if ( auto nameIdentifier = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . Get ( checkIdx - 1 ) ) )
{
nameIdx = checkIdx - 1 ;
}
else
{
useNameIdx = false ;
break ;
}
}
}
}
if ( checkToken = = BfToken_RParen )
parenDepth - - ;
else if ( checkToken = = BfToken_LParen )
parenDepth + + ;
else if ( checkToken = = BfToken_LBracket )
bracketDepth + + ;
else if ( checkToken = = BfToken_RBracket )
bracketDepth - - ;
if ( parenDepth = = 0 )
{
if ( bracketDepth ! = 0 )
useNameIdx = false ;
break ;
}
if ( checkToken = = BfToken_Semicolon )
{
useNameIdx = false ;
break ;
}
}
else if ( auto identifier = BfNodeDynCast < BfIdentifierNode > ( checkNode ) )
{
// Okay
}
else
{
// Nothing else is okay
useNameIdx = false ;
break ;
}
checkIdx + + ;
}
if ( ( useNameIdx ) & & ( nameIdx ! = - 1 ) )
{
if ( nameIdx < = mVisitorPos . mReadPos )
{
// We have a valid-enough param list but a missing name, so keep going
allowNameFail = true ;
}
else
{
for ( int errIdx = mVisitorPos . mReadPos + 1 ; errIdx < nameIdx ; errIdx + + )
{
auto node = mVisitorPos . Get ( errIdx ) ;
if ( auto token = BfNodeDynCast < BfTokenNode > ( node ) )
mPassInstance - > Fail ( " Unexpected token " , node ) ;
else
mPassInstance - > Fail ( " Unexpected identifier " , node ) ;
AddErrorNode ( node ) ;
}
auto nameIdentifierNode = BfNodeDynCast < BfIdentifierNode > ( mVisitorPos . Get ( nameIdx ) ) ;
paramDecl - > mNameNode = nameIdentifierNode ;
MoveNode ( nameIdentifierNode , paramDecl ) ;
nameAfterNode = nameIdentifierNode ;
mVisitorPos . mReadPos = nameIdx ;
continue ;
//mVisitorPos.mReadPos = nameIdx - 1;
}
}
}
if ( auto nameToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) )
{
if ( ( nameToken - > GetToken ( ) = = BfToken_This ) )
{
bool isDelegate = false ;
bool isFunction = false ;
if ( auto delegateTypeRef = BfNodeDynCast < BfDelegateTypeRef > ( node ) )
{
if ( delegateTypeRef - > mTypeToken - > GetToken ( ) = = BfToken_Function )
isFunction = true ;
else
isDelegate = true ;
}
else if ( mCurTypeDecl - > mTypeNode - > GetToken ( ) = = BfToken_Function )
isFunction = true ;
else if ( mCurTypeDecl - > mTypeNode - > GetToken ( ) = = BfToken_Delegate )
isDelegate = true ;
if ( isFunction | | isDelegate )
{
if ( paramIdx ! = 0 )
Fail ( " 'this' can only be used as the first parameter " , nameToken ) ;
if ( ! isFunction )
Fail ( " 'this' can only be specified on function types " , nameToken ) ;
mVisitorPos . MoveNext ( ) ;
paramDecl - > mNameNode = nameToken ;
MoveNode ( nameToken , paramDecl ) ;
nameAfterNode = nameToken ;
}
}
}
if ( paramDecl - > mNameNode = = NULL )
{
auto nameIdentifierNode = ExpectIdentifierAfter ( node , " parameter name " ) ;
if ( nameIdentifierNode = = NULL )
{
if ( ! allowNameFail )
return NULL ;
}
else
{
paramDecl - > mNameNode = nameIdentifierNode ;
MoveNode ( nameIdentifierNode , paramDecl ) ;
nameAfterNode = nameIdentifierNode ;
}
}
}
if ( attributes ! = NULL )
{
Fail ( " Unexpected attributes " , attributes ) ;
AddErrorNode ( attributes ) ;
}
return NULL ;
}
bool BfReducer : : ParseMethod ( BfMethodDeclaration * methodDeclaration , SizedArrayImpl < BfParameterDeclaration * > * params , SizedArrayImpl < BfTokenNode * > * commas , bool alwaysIncludeBlock )
{
2019-11-17 09:28:39 -08:00
BfTokenNode * tokenNode ;
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( methodDeclaration - > mGenericParams = = NULL )
{
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
{
if ( tokenNode - > GetToken ( ) = = BfToken_LChevron )
{
auto genericParams = CreateGenericParamsDeclaration ( tokenNode ) ;
if ( genericParams ! = NULL )
{
MEMBER_SET ( methodDeclaration , mGenericParams , genericParams ) ;
}
}
}
}
tokenNode = ExpectTokenAfter ( methodDeclaration , BfToken_LParen , BfToken_Bang ) ;
2019-08-23 11:56:54 -07:00
if ( tokenNode = = NULL )
return false ;
if ( tokenNode - > GetToken ( ) = = BfToken_Bang )
{
Fail ( " Cannot include '!' in the method declaration " , tokenNode ) ;
MoveNode ( tokenNode , methodDeclaration ) ;
tokenNode = ExpectTokenAfter ( methodDeclaration , BfToken_LParen ) ;
if ( tokenNode = = NULL )
return false ;
}
methodDeclaration - > mOpenParen = tokenNode ;
MoveNode ( methodDeclaration - > mOpenParen , methodDeclaration ) ;
methodDeclaration - > mCloseParen = ParseMethodParams ( methodDeclaration , params , commas , BfToken_RParen ) ;
// RParen
if ( methodDeclaration - > mCloseParen = = NULL )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
while ( auto checkToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
if ( checkToken - > GetToken ( ) = = BfToken_RParen )
{
methodDeclaration - > mCloseParen = checkToken ;
break ;
}
else
{
// Just eat it - for autocompletion. This helps make cases nicer where we're typing in the "in" for "int", for example
MoveNode ( checkToken , methodDeclaration ) ;
AddErrorNode ( checkToken ) ;
mVisitorPos . MoveNext ( ) ;
nextNode = mVisitorPos . GetNext ( ) ;
}
}
if ( methodDeclaration - > mCloseParen = = NULL )
return false ;
}
MoveNode ( methodDeclaration - > mCloseParen , methodDeclaration ) ;
mVisitorPos . MoveNext ( ) ;
auto typeDecl = mCurTypeDecl ;
2019-11-17 09:28:39 -08:00
nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_Mut )
{
if ( methodDeclaration - > mMutSpecifier ! = NULL )
{
AddErrorNode ( methodDeclaration - > mMutSpecifier ) ;
Fail ( " Mut already specified " , methodDeclaration - > mMutSpecifier ) ;
}
MEMBER_SET ( methodDeclaration , mMutSpecifier , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
nextNode = mVisitorPos . GetNext ( ) ;
}
}
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_Where )
{
mVisitorPos . MoveNext ( ) ;
auto genericConstraints = CreateGenericConstraintsDeclaration ( tokenNode ) ;
MEMBER_SET_CHECKED_BOOL ( methodDeclaration , mGenericConstraintsDeclaration , genericConstraints ) ;
}
}
auto ctorDecl = BfNodeDynCast < BfConstructorDeclaration > ( methodDeclaration ) ;
nextNode = mVisitorPos . GetNext ( ) ;
auto endToken = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( endToken ! = NULL ) & & ( endToken - > GetToken ( ) = = BfToken_Colon ) )
{
if ( auto ctorDecl = BfNodeDynCast < BfConstructorDeclaration > ( methodDeclaration ) )
{
MEMBER_SET ( ctorDecl , mInitializerColonToken , endToken ) ;
mVisitorPos . MoveNext ( ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
endToken = ExpectTokenAfter ( ctorDecl , BfToken_This , BfToken_Base ) ;
if ( endToken ! = NULL )
{
auto invocationExpr = CreateInvocationExpression ( endToken ) ;
if ( invocationExpr ! = NULL )
{
MEMBER_SET ( ctorDecl , mInitializer , invocationExpr ) ;
}
}
else if ( auto identifierAfter = BfNodeDynCast < BfIdentifierNode > ( nextNode ) )
{
// In process of typing - just eat identifier so we don't error out on whole method
MoveNode ( identifierAfter , ctorDecl ) ;
}
}
endToken = NULL ;
}
if ( ( endToken ! = NULL ) & & ( endToken - > GetToken ( ) = = BfToken_Semicolon ) )
{
MEMBER_SET_CHECKED_BOOL ( methodDeclaration , mEndSemicolon , endToken ) ;
mVisitorPos . MoveNext ( ) ;
}
else
{
nextNode = mVisitorPos . GetNext ( ) ;
auto blockNode = BfNodeDynCast < BfBlock > ( nextNode ) ;
if ( blockNode ! = NULL )
{
methodDeclaration - > mBody = blockNode ;
MoveNode ( blockNode , methodDeclaration ) ;
mVisitorPos . MoveNext ( ) ;
if ( ( IsNodeRelevant ( methodDeclaration ) ) | | ( alwaysIncludeBlock ) )
{
SetAndRestoreValue < BfMethodDeclaration * > prevMethodDeclaration ( mCurMethodDecl , methodDeclaration ) ;
HandleBlock ( blockNode , methodDeclaration - > mMixinSpecifier ! = NULL ) ;
}
return true ;
}
else
{
nextNode = mVisitorPos . GetNext ( ) ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( ( tokenNode ! = NULL ) & & ( tokenNode - > GetToken ( ) = = BfToken_FatArrow ) )
{
MEMBER_SET ( methodDeclaration , mFatArrowToken , tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
auto methodExpression = CreateExpressionAfter ( methodDeclaration ) ;
MEMBER_SET_CHECKED_BOOL ( methodDeclaration , mBody , methodExpression ) ;
auto semicolonToken = ExpectTokenAfter ( methodDeclaration , BfToken_Semicolon ) ;
MEMBER_SET_CHECKED_BOOL ( methodDeclaration , mEndSemicolon , semicolonToken ) ;
return true ;
}
}
FailAfter ( " Expected method body " , methodDeclaration ) ;
}
return true ;
}
BfGenericArgumentsNode * BfReducer : : CreateGenericArguments ( BfTokenNode * tokenNode )
{
auto genericArgs = mAlloc - > Alloc < BfGenericArgumentsNode > ( ) ;
BfDeferredAstSizedArray < BfTypeReference * > genericArgsArray ( genericArgs - > mGenericArgs , mAlloc ) ;
BfDeferredAstSizedArray < BfAstNode * > commas ( genericArgs - > mCommas , mAlloc ) ;
ReplaceNode ( tokenNode , genericArgs ) ;
genericArgs - > mOpenChevron = tokenNode ;
while ( true )
{
auto genericArg = CreateTypeRefAfter ( genericArgs ) ;
if ( genericArg = = NULL )
{
genericArgsArray . push_back ( NULL ) ; // Leave empty for purposes of generic argument count
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode ! = NULL )
{
// Try to get right chevron. Reduces error count when we're typing out a generic argument list
if ( tokenNode - > GetToken ( ) = = BfToken_RDblChevron )
tokenNode = BreakDoubleChevron ( tokenNode ) ;
if ( tokenNode - > GetToken ( ) = = BfToken_RChevron )
{
MoveNode ( tokenNode , genericArgs ) ;
genericArgs - > mCloseChevron = tokenNode ;
mVisitorPos . MoveNext ( ) ;
}
}
return genericArgs ;
}
MoveNode ( genericArg , genericArgs ) ;
genericArgsArray . push_back ( genericArg ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode = = NULL )
{
FailAfter ( " Expected ',' or '>' " , genericArgs ) ;
return genericArgs ;
}
BfToken token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_RDblChevron )
tokenNode = BreakDoubleChevron ( tokenNode ) ;
if ( token = = BfToken_RChevron )
{
MoveNode ( tokenNode , genericArgs ) ;
genericArgs - > mCloseChevron = tokenNode ;
mVisitorPos . MoveNext ( ) ;
break ;
}
if ( token ! = BfToken_Comma )
{
Fail ( " Either , or > expected " , tokenNode ) ;
return genericArgs ;
}
MoveNode ( tokenNode , genericArgs ) ;
commas . push_back ( tokenNode ) ;
mVisitorPos . MoveNext ( ) ;
}
return genericArgs ;
}
BfGenericParamsDeclaration * BfReducer : : CreateGenericParamsDeclaration ( BfTokenNode * tokenNode )
{
auto genericParams = mAlloc - > Alloc < BfGenericParamsDeclaration > ( ) ;
BfDeferredAstSizedArray < BfIdentifierNode * > genericParamsArr ( genericParams - > mGenericParams , mAlloc ) ;
BfDeferredAstSizedArray < BfAstNode * > commas ( genericParams - > mCommas , mAlloc ) ;
ReplaceNode ( tokenNode , genericParams ) ;
genericParams - > mOpenChevron = tokenNode ;
mVisitorPos . MoveNext ( ) ;
while ( true )
{
auto genericIdentifier = ExpectIdentifierAfter ( genericParams , " generic parameters " ) ;
if ( genericIdentifier = = NULL )
return genericParams ;
MoveNode ( genericIdentifier , genericParams ) ;
genericParamsArr . push_back ( genericIdentifier ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ;
if ( tokenNode = = NULL )
{
FailAfter ( " Expected ',' or '>' " , genericParams ) ;
return genericParams ;
}
BfToken token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_RDblChevron )
tokenNode = BreakDoubleChevron ( tokenNode ) ;
MoveNode ( tokenNode , genericParams ) ;
mVisitorPos . MoveNext ( ) ;
if ( token = = BfToken_RChevron )
{
genericParams - > mCloseChevron = tokenNode ;
break ;
}
if ( token ! = BfToken_Comma )
{
Fail ( " Either , or > expected " , tokenNode ) ;
return genericParams ;
}
commas . push_back ( tokenNode ) ;
}
return genericParams ;
}
BfGenericConstraintsDeclaration * BfReducer : : CreateGenericConstraintsDeclaration ( BfTokenNode * tokenNode )
{
auto constraintsDeclaration = mAlloc - > Alloc < BfGenericConstraintsDeclaration > ( ) ;
BfDeferredAstSizedArray < BfGenericConstraint * > genericConstraintsArr ( constraintsDeclaration - > mGenericConstraints , mAlloc ) ;
bool isDone = false ;
for ( int constraintIdx = 0 ; ! isDone ; constraintIdx + + )
2019-11-17 09:28:39 -08:00
{
2019-08-23 11:56:54 -07:00
BfGenericConstraint * genericConstraint = mAlloc - > Alloc < BfGenericConstraint > ( ) ;
BfDeferredAstSizedArray < BfAstNode * > constraintTypes ( genericConstraint - > mConstraintTypes , mAlloc ) ;
BfDeferredAstSizedArray < BfTokenNode * > commas ( genericConstraint - > mCommas , mAlloc ) ;
ReplaceNode ( tokenNode , genericConstraint ) ;
genericConstraint - > mWhereToken = tokenNode ;
genericConstraintsArr . push_back ( genericConstraint ) ;
2019-11-17 09:28:39 -08:00
auto genericParamName = CreateTypeRefAfter ( genericConstraint ) ;
2019-08-23 11:56:54 -07:00
if ( genericParamName ! = NULL )
{
2019-11-17 09:28:39 -08:00
MEMBER_SET ( genericConstraint , mTypeRef , genericParamName ) ;
tokenNode = ExpectTokenAfter ( genericConstraint , BfToken_Colon , BfToken_AssignEquals ) ;
2019-08-23 11:56:54 -07:00
}
else
isDone = true ;
if ( tokenNode ! = NULL )
{
MEMBER_SET ( genericConstraint , mColonToken , tokenNode ) ;
}
else
isDone = true ;
for ( int typeIdx = 0 ; ! isDone ; typeIdx + + )
{
if ( typeIdx > 0 )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( BfNodeDynCast < BfBlock > ( nextNode ) )
{
isDone = true ;
break ;
}
tokenNode = ExpectTokenAfter ( genericConstraint , BfToken_Comma , BfToken_LBrace , BfToken_Where , BfToken_Semicolon ) ;
if ( tokenNode = = NULL )
{
isDone = true ;
break ;
}
BfToken token = tokenNode - > GetToken ( ) ;
if ( token = = BfToken_Where )
break ;
if ( ( token = = BfToken_LBrace ) | | ( token = = BfToken_Semicolon ) )
{
//return constraintsDeclaration;
isDone = true ;
break ;
}
MoveNode ( tokenNode , genericConstraint ) ;
commas . push_back ( tokenNode ) ;
}
auto nextNode = mVisitorPos . GetNext ( ) ;
if ( auto constraintToken = BfNodeDynCast < BfTokenNode > ( nextNode ) )
{
2019-11-17 09:28:39 -08:00
BfAstNode * constraintNode = NULL ;
2019-08-23 11:56:54 -07:00
bool addToConstraint = false ;
switch ( constraintToken - > GetToken ( ) )
{
case BfToken_Class :
case BfToken_Struct :
case BfToken_Const :
case BfToken_Var :
addToConstraint = true ;
break ;
2019-11-17 09:28:39 -08:00
case BfToken_Operator :
{
BfGenericOperatorConstraint * opConstraint = mAlloc - > Alloc < BfGenericOperatorConstraint > ( ) ;
constraintNode = opConstraint ;
ReplaceNode ( constraintToken , opConstraint ) ;
MEMBER_SET ( opConstraint , mOperatorToken , constraintToken ) ;
mVisitorPos . MoveNext ( ) ;
auto opToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) ;
if ( opToken = = NULL )
{
auto typeRef = CreateTypeRefAfter ( opConstraint ) ;
if ( typeRef = = NULL )
break ;
MEMBER_SET ( opConstraint , mLeftType , typeRef ) ;
opToken = BfNodeDynCast < BfTokenNode > ( mVisitorPos . GetNext ( ) ) ;
}
if ( opToken = = NULL )
break ;
MEMBER_SET ( opConstraint , mOpToken , opToken ) ;
mVisitorPos . MoveNext ( ) ;
auto typeRef = CreateTypeRefAfter ( opConstraint ) ;
if ( typeRef = = NULL )
break ;
MEMBER_SET ( opConstraint , mRightType , typeRef ) ;
}
break ;
2019-10-14 14:08:29 -07:00
default : break ;
2019-08-23 11:56:54 -07:00
}
if ( addToConstraint )
{
2019-11-17 09:28:39 -08:00
constraintNode = constraintToken ;
2019-08-23 11:56:54 -07:00
bool addToConstraint = false ;
mVisitorPos . MoveNext ( ) ;
if ( constraintToken - > GetToken ( ) = = BfToken_Struct )
{
addToConstraint = true ;
nextNode = mVisitorPos . GetNext ( ) ;
2019-10-14 14:08:29 -07:00
if ( ( tokenNode = BfNodeDynCast < BfTokenNode > ( nextNode ) ) )
2019-08-23 11:56:54 -07:00
{
if ( tokenNode - > GetToken ( ) = = BfToken_Star )
{
auto tokenPair = mAlloc - > Alloc < BfTokenPairNode > ( ) ;
ReplaceNode ( constraintToken , tokenPair ) ;
MEMBER_SET ( tokenPair , mLeft , constraintToken ) ;
MEMBER_SET ( tokenPair , mRight , tokenNode ) ;
constraintNode = tokenPair ;
MoveNode ( constraintToken , genericConstraint ) ;
genericConstraint - > SetSrcEnd ( tokenNode - > GetSrcEnd ( ) ) ;
mVisitorPos . MoveNext ( ) ;
}
}
}
else if ( constraintToken - > GetToken ( ) = = BfToken_Const )
{
constraintTypes . push_back ( constraintNode ) ;
auto typeRef = CreateTypeRefAfter ( nextNode ) ;
if ( typeRef = = NULL )
{
isDone = true ;
break ;
}
MoveNode ( typeRef , genericConstraint ) ;
constraintTypes . push_back ( typeRef ) ;
continue ;
2019-11-17 09:28:39 -08:00
}
}
if ( constraintNode ! = NULL )
{
MoveNode ( constraintNode , genericConstraint ) ;
2019-08-23 11:56:54 -07:00
constraintTypes . push_back ( constraintNode ) ;
continue ;
}
}
auto typeRef = CreateTypeRefAfter ( genericConstraint ) ;
if ( typeRef = = NULL )
{
isDone = true ;
break ;
}
MoveNode ( typeRef , genericConstraint ) ;
constraintTypes . push_back ( typeRef ) ;
}
if ( constraintIdx = = 0 )
ReplaceNode ( genericConstraint , constraintsDeclaration ) ;
else
MoveNode ( genericConstraint , constraintsDeclaration ) ;
}
return constraintsDeclaration ;
}
void BfReducer : : HandleBlock ( BfBlock * block , bool allowEndingExpression )
{
//for (auto node : block->mChildren)
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( block ) ) ;
bool isDone = ! mVisitorPos . MoveNext ( ) ;
BfAstNode * nextNode = NULL ;
while ( ! isDone )
{
BfAstNode * node = mVisitorPos . GetCurrent ( ) ;
CreateStmtFlags flags = ( CreateStmtFlags ) ( CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_AllowLocalFunction ) ;
if ( allowEndingExpression )
flags = ( CreateStmtFlags ) ( flags | CreateStmtFlags_AllowUnterminatedExpression ) ;
auto statement = CreateStatement ( node , flags ) ;
if ( statement = = NULL )
{
auto nextNode = mVisitorPos . GetNext ( ) ;
isDone = ! mVisitorPos . MoveNext ( ) ;
# ifdef BF_AST_HAS_PARENT_MEMBER
BF_ASSERT ( node - > mParent ! = NULL ) ;
# endif
node - > RemoveSelf ( ) ;
BF_ASSERT ( node - > GetSourceData ( ) = = mSource - > mSourceData ) ;
mSource - > AddErrorNode ( node ) ;
if ( nextNode = = NULL )
break ;
continue ;
}
isDone = ! mVisitorPos . MoveNext ( ) ;
mVisitorPos . Write ( statement ) ;
}
mVisitorPos . Trim ( ) ;
}
void BfReducer : : HandleTypeDeclaration ( BfTypeDeclaration * typeDecl , BfAttributeDirective * attributes )
{
SetAndRestoreValue < BfTypeDeclaration * > prevTypeDecl ( mCurTypeDecl , typeDecl ) ;
SetAndRestoreValue < BfVisitorPos > prevVisitorPos ( mVisitorPos , BfVisitorPos ( BfNodeDynCast < BfBlock > ( typeDecl - > mDefineNode ) ) ) ;
if ( attributes ! = NULL )
{
MEMBER_SET ( typeDecl , mAttributes , attributes ) ;
}
if ( ! IsNodeRelevant ( typeDecl ) )
{
typeDecl - > mIgnoreDeclaration = true ;
return ;
}
BfAstNode * prevNode = NULL ;
bool isDone = ! mVisitorPos . MoveNext ( ) ;
while ( ! isDone )
{
auto node = mVisitorPos . GetCurrent ( ) ;
if ( node = = prevNode )
{
BF_FATAL ( " Should have handled node already " ) ;
// If we're stuck on an error and can't process any more nodes
break ;
}
prevNode = node ;
BfAstNode * typeMember = BfNodeDynCast < BfMemberDeclaration > ( node ) ;
if ( typeMember = = NULL )
typeMember = ReadTypeMember ( node ) ;
//methodDeclaration->mDocumentation = FindDocumentation(methodDeclaration);
isDone = ! mVisitorPos . MoveNext ( ) ;
if ( typeMember ! = NULL )
{
mVisitorPos . Write ( typeMember ) ;
}
}
mVisitorPos . Trim ( ) ;
}
void BfReducer : : HandleRoot ( BfRootNode * rootNode )
{
String fileName ;
auto parser = rootNode - > GetSourceData ( ) - > ToParserData ( ) ;
if ( parser ! = NULL )
fileName = parser - > mFileName ;
BP_ZONE_F ( " BfReducer::HandleRoot %s " , fileName . c_str ( ) ) ;
mAlloc = & rootNode - > GetSourceData ( ) - > mAlloc ;
mSystem = mSource - > mSystem ;
HandleTopLevel ( rootNode ) ;
BfSizedArrayInitIndirect ( mSource - > mSourceData - > mExteriorNodes , mExteriorNodes , mAlloc ) ;
mAlloc = NULL ;
if ( mPassInstance - > HasFailed ( ) )
mSource - > mParsingFailed = true ;
}
static String NodeToString ( BfAstNode * node )
{
return String ( & node - > GetSourceData ( ) - > mSrc [ node - > GetSrcStart ( ) ] , node - > GetSrcLength ( ) ) ;
}
BfInlineAsmStatement * BfReducer : : CreateInlineAsmStatement ( BfAstNode * asmNode )
{
auto asmToken = BfNodeDynCast < BfTokenNode > ( asmNode ) ;
auto nextNode = mVisitorPos . GetNext ( ) ;
auto blockNode = BfNodeDynCast < BfInlineAsmStatement > ( nextNode ) ;
if ( blockNode = = NULL )
return ( BfInlineAsmStatement * ) Fail ( " Expected inline assembly block " , asmNode ) ;
ReplaceNode ( asmToken , blockNode ) ;
BfInlineAsmStatement * asmStatement = ( BfInlineAsmStatement * ) blockNode ;
{
auto processInstrNodes = [ & ] ( const Array < BfAstNode * > & nodes ) - > BfInlineAsmInstruction *
{
int nodeCount = ( int ) nodes . size ( ) ;
int curNodeIdx = 0 ;
auto instNode = mAlloc - > Alloc < BfInlineAsmInstruction > ( ) ;
//instNode->mSource = asmStatement->mSource;
int srcStart = nodes . front ( ) - > GetSrcStart ( ) ;
int srcEnd = nodes . back ( ) - > GetSrcEnd ( ) ;
instNode - > Init ( srcStart , srcStart , srcEnd ) ;
auto replaceWithLower = [ ] ( String & s )
{
std : : transform ( s . begin ( ) , s . end ( ) , s . begin ( ) , : : tolower ) ;
} ;
auto readIdent = [ & ] ( String & outStr , bool forceLowerCase , const StringImpl & errorExpectation , bool peekOnly ) - > bool
{
if ( curNodeIdx > = nodeCount )
{
if ( ! peekOnly )
Fail ( StrFormat ( " Expected %s " , errorExpectation . c_str ( ) ) , instNode ) ;
return false ;
}
BfAstNode * curNode = nodes [ curNodeIdx ] ;
if ( ! peekOnly )
+ + curNodeIdx ;
if ( ! BfNodeDynCast < BfIdentifierNode > ( curNode ) )
{
if ( ! peekOnly )
Fail ( StrFormat ( " Found \" %s \" , expected %s " , NodeToString ( curNode ) . c_str ( ) , errorExpectation . c_str ( ) ) , instNode ) ;
return false ;
}
outStr = NodeToString ( curNode ) ;
if ( forceLowerCase )
replaceWithLower ( outStr ) ;
return true ;
} ;
auto readToken = [ & ] ( BfToken tokenType , const StringImpl & errorExpectation , bool peekOnly ) - > bool
{
if ( curNodeIdx > = nodeCount )
{
if ( ! peekOnly )
Fail ( StrFormat ( " Expected %s " , errorExpectation . c_str ( ) ) , instNode ) ;
return false ;
}
BfAstNode * curNode = nodes [ curNodeIdx ] ;
if ( ! peekOnly )
+ + curNodeIdx ;
auto tokenNode = BfNodeDynCast < BfTokenNode > ( curNode ) ;
if ( ! tokenNode | | tokenNode - > GetToken ( ) ! = tokenType )
{
if ( ! peekOnly )
Fail ( StrFormat ( " Found \" %s \" , expected %s " , NodeToString ( curNode ) . c_str ( ) , errorExpectation . c_str ( ) ) , instNode ) ;
return false ;
}
return true ;
} ;
auto readInteger = [ & ] ( int & outInt , const StringImpl & errorExpectation , bool peekOnly , int & outAdvanceTokenCount ) - > bool
{
int origCurNodeIdx = curNodeIdx ;
outAdvanceTokenCount = 0 ;
bool negate = false ;
if ( readToken ( BfToken_Minus , " " , true ) )
{
+ + curNodeIdx ;
+ + outAdvanceTokenCount ;
negate = true ;
}
if ( curNodeIdx > = nodeCount )
{
if ( ! peekOnly )
Fail ( StrFormat ( " Expected %s " , errorExpectation . c_str ( ) ) , instNode ) ;
else
curNodeIdx = origCurNodeIdx ;
return false ;
}
BfAstNode * curNode = nodes [ curNodeIdx ] ;
+ + curNodeIdx ;
+ + outAdvanceTokenCount ;
auto litNode = BfNodeDynCast < BfLiteralExpression > ( curNode ) ;
if ( ! litNode | | litNode - > mValue . mTypeCode ! = BfTypeCode_Int32 )
{
if ( ! peekOnly )
Fail ( StrFormat ( " Found \" %s \" , expected %s " , NodeToString ( curNode ) . c_str ( ) , errorExpectation . c_str ( ) ) , instNode ) ;
else
curNodeIdx = origCurNodeIdx ;
return false ;
}
outInt = litNode - > mValue . mInt32 ;
if ( negate )
outInt = - outInt ;
if ( peekOnly )
curNodeIdx = origCurNodeIdx ;
return true ;
} ;
auto readArgMemPrimaryExpr = [ & ] ( BfInlineAsmInstruction : : AsmArg & outArg ) - > bool
{
String primaryIdent ;
int primaryInt ;
int advanceTokenCount = 0 ;
if ( readIdent ( primaryIdent , false , " " , true ) )
{
outArg . mMemFlags = BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg ;
outArg . mReg = primaryIdent ;
+ + curNodeIdx ;
return true ;
}
else if ( readInteger ( primaryInt , " " , true , advanceTokenCount ) )
{
outArg . mMemFlags = BfInlineAsmInstruction : : AsmArg : : ARGMEMF_ImmediateDisp ;
outArg . mInt = primaryInt ;
curNodeIdx + = advanceTokenCount ;
return true ;
}
else
{
Fail ( StrFormat ( " Found \" %s \" , expected integer or identifier " , NodeToString ( nodes [ curNodeIdx ] ) . c_str ( ) ) , instNode ) ;
return false ;
}
} ;
std : : function < bool ( BfInlineAsmInstruction : : AsmArg & ) > readArgMemMulExpr = [ & ] ( BfInlineAsmInstruction : : AsmArg & outArg ) - > bool
{
BfInlineAsmInstruction : : AsmArg exprArgLeft , exprArgRight ;
if ( ! readArgMemPrimaryExpr ( exprArgLeft ) )
return false ;
if ( ! readToken ( BfToken_Star , " " , true ) )
{
outArg = exprArgLeft ;
return true ;
}
+ + curNodeIdx ;
if ( ! readArgMemMulExpr ( exprArgRight ) )
return false ;
bool leftIdent = ( exprArgLeft . mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg ) ! = 0 ;
bool rightIdent = ( exprArgRight . mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg ) ! = 0 ;
if ( leftIdent & & rightIdent )
{
Fail ( StrFormat ( " Memory expressions can only scale by an integer " , NodeToString ( nodes [ curNodeIdx ] ) . c_str ( ) ) , instNode ) ;
return false ;
}
else if ( leftIdent | | rightIdent )
{
if ( leftIdent )
{
outArg = exprArgLeft ;
outArg . mAdjRegScalar = exprArgRight . mInt ;
}
else
{
outArg = exprArgRight ;
outArg . mAdjRegScalar = exprArgLeft . mInt ;
}
outArg . mMemFlags & = ~ BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg ;
outArg . mMemFlags | = BfInlineAsmInstruction : : AsmArg : : ARGMEMF_AdjReg ;
outArg . mAdjReg = outArg . mReg ;
outArg . mReg . clear ( ) ;
}
else
{
outArg = exprArgLeft ;
outArg . mInt = exprArgLeft . mInt * exprArgRight . mInt ;
}
return true ;
} ;
std : : function < bool ( BfInlineAsmInstruction : : AsmArg & , bool ) > readArgMemAddExpr = [ & ] ( BfInlineAsmInstruction : : AsmArg & outArg , bool subtractLeft ) - > bool // can't use 'auto' here since it's recursive
{
BfInlineAsmInstruction : : AsmArg exprArgLeft , exprArgRight ;
if ( ! readArgMemMulExpr ( exprArgLeft ) )
return false ;
if ( subtractLeft )
{
if ( exprArgLeft . mMemFlags ! = BfInlineAsmInstruction : : AsmArg : : ARGMEMF_ImmediateDisp )
{
Fail ( " Memory expressions can only subtract by an integer " , instNode ) ;
return false ;
}
exprArgLeft . mInt = - exprArgLeft . mInt ;
}
bool subtract = false ;
if ( ! readToken ( BfToken_Plus , " " , true ) )
{
if ( ! readToken ( BfToken_Minus , " " , true ) )
{
outArg = exprArgLeft ;
return true ;
}
else
subtract = true ;
}
+ + curNodeIdx ;
if ( ! readArgMemAddExpr ( exprArgRight , subtract ) )
return false ;
bool leftScaling = ( exprArgLeft . mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_AdjReg ) ! = 0 ;
bool rightScaling = ( exprArgRight . mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_AdjReg ) ! = 0 ;
if ( leftScaling & & rightScaling )
{
Fail ( " Memory expressions can only have one scaling register and one non-scaling register " , instNode ) ;
return false ;
}
BfInlineAsmInstruction : : AsmArg * scaledArg = leftScaling ? & exprArgLeft : ( rightScaling ? & exprArgRight : nullptr ) ;
if ( scaledArg )
{
BfInlineAsmInstruction : : AsmArg * otherArg = leftScaling ? & exprArgRight : & exprArgLeft ;
outArg = * scaledArg ;
outArg . mMemFlags | = otherArg - > mMemFlags ;
if ( otherArg - > mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg )
{
if ( scaledArg - > mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg )
{
Fail ( " Memory expressions can involve at most two registers " , instNode ) ;
return false ;
}
outArg . mReg = otherArg - > mReg ;
}
if ( otherArg - > mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_ImmediateDisp )
{
outArg . mInt + = otherArg - > mInt ;
}
}
else
{
outArg . mInt = 0 ;
if ( exprArgLeft . mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_ImmediateDisp )
{
outArg . mMemFlags | = BfInlineAsmInstruction : : AsmArg : : ARGMEMF_ImmediateDisp ;
outArg . mInt + = exprArgLeft . mInt ;
}
if ( exprArgRight . mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_ImmediateDisp )
{
outArg . mMemFlags | = BfInlineAsmInstruction : : AsmArg : : ARGMEMF_ImmediateDisp ;
outArg . mInt + = exprArgRight . mInt ;
}
bool leftIdent = ( exprArgLeft . mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg ) ! = 0 ;
bool rightIdent = ( exprArgRight . mMemFlags & BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg ) ! = 0 ;
if ( leftIdent & & rightIdent )
{
outArg . mMemFlags | = ( BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg | BfInlineAsmInstruction : : AsmArg : : ARGMEMF_AdjReg ) ;
outArg . mReg = exprArgLeft . mReg ;
outArg . mAdjReg = exprArgRight . mReg ;
outArg . mAdjRegScalar = 1 ;
}
else if ( leftIdent )
{
outArg . mMemFlags | = BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg ;
outArg . mReg = exprArgLeft . mReg ;
}
else if ( rightIdent )
{
outArg . mMemFlags | = BfInlineAsmInstruction : : AsmArg : : ARGMEMF_BaseReg ;
outArg . mReg = exprArgRight . mReg ;
}
}
return true ;
} ;
auto parseArg = [ & ] ( BfInlineAsmInstruction : : AsmArg & outArg ) - > bool
{
bool keepGoing = true ;
while ( keepGoing )
{
keepGoing = false ;
int peekInt ;
String peekStr ;
int advanceTokenCount ;
if ( readInteger ( peekInt , " " , true , advanceTokenCount ) )
{
outArg . mType = BfInlineAsmInstruction : : AsmArg : : ARGTYPE_Immediate ;
outArg . mInt = peekInt ;
curNodeIdx + = advanceTokenCount ;
}
else if ( readIdent ( peekStr , false , " " , true ) )
{
+ + curNodeIdx ;
String s ( peekStr ) ;
replaceWithLower ( s ) ;
String tempIdent ;
if ( ( s = = " cs " | | s = = " ds " | | s = = " es " | | s = = " fs " | | s = = " gs " | | s = = " ss " ) & & readToken ( BfToken_Colon , " " , true ) )
{
+ + curNodeIdx ;
outArg . mSegPrefix = s ;
keepGoing = true ;
}
else if ( s = = " st " & & readToken ( BfToken_LParen , " " , true ) )
{
+ + curNodeIdx ;
outArg . mType = BfInlineAsmInstruction : : AsmArg : : ARGTYPE_FloatReg ;
if ( ! readInteger ( peekInt , " integer floating-point register number " , false , advanceTokenCount ) )
return false ;
outArg . mInt = peekInt ;
if ( ! readToken ( BfToken_RParen , " ')' " , false ) )
return false ;
}
else if ( ( s = = " byte " | | s = = " word " | | s = = " dword " | | s = = " qword " | | s = = " xword " | | s = = " xmmword " | | s = = " opaque " ) & & readIdent ( tempIdent , true , " " , true ) )
{
if ( tempIdent ! = " ptr " )
{
Fail ( StrFormat ( " Found \" %s \" , expected \" ptr \" " , NodeToString ( nodes [ curNodeIdx ] ) . c_str ( ) ) , instNode ) ;
return false ;
}
+ + curNodeIdx ;
outArg . mSizePrefix = s ;
keepGoing = true ;
}
else
{
outArg . mType = BfInlineAsmInstruction : : AsmArg : : ARGTYPE_IntReg ;
outArg . mReg = peekStr ;
}
}
else if ( readToken ( BfToken_LBracket , " " , true ) )
{
+ + curNodeIdx ;
BfInlineAsmInstruction : : AsmArg exprArgLeft ;
if ( ! readArgMemAddExpr ( exprArgLeft , false ) )
return false ;
if ( ! readToken ( BfToken_RBracket , " ']' " , false ) )
return false ;
if ( readToken ( BfToken_Dot , " " , true ) )
{
+ + curNodeIdx ;
if ( ! readIdent ( outArg . mMemberSuffix , false , " struct member suffix identifier " , false ) )
return false ;
}
outArg . mType = BfInlineAsmInstruction : : AsmArg : : ARGTYPE_Memory ;
outArg . mMemFlags = exprArgLeft . mMemFlags ;
//outArg.mSegPrefix = already_set_leave_me_alone;
//outArg.mSizePrefix = already_set_leave_me_alone;
outArg . mInt = exprArgLeft . mInt ;
outArg . mReg = exprArgLeft . mReg ;
outArg . mAdjReg = exprArgLeft . mAdjReg ;
outArg . mAdjRegScalar = exprArgLeft . mAdjRegScalar ;
//outArg.mMemberSuffix = already_set_leave_me_alone;
return true ;
}
else
return false ;
}
return true ;
} ;
BfInlineAsmInstruction : : AsmInst & outInst = instNode - > mAsmInst ;
// instruction / instruction prefix / label
String opStr ;
if ( ! readIdent ( opStr , false , " instruction, instruction prefix, or label " , false ) )
return nullptr ;
if ( readToken ( BfToken_Colon , " " , true ) )
{
+ + curNodeIdx ;
outInst . mLabel = opStr ;
if ( curNodeIdx > = nodeCount )
return instNode ;
if ( ! readIdent ( opStr , false , " instruction or instruction prefix " , false ) )
return nullptr ;
}
replaceWithLower ( opStr ) ;
// check for instruction prefix(s)
while ( opStr = = " lock " | | opStr = = " rep " | | opStr = = " repe " | | opStr = = " repne " | | opStr = = " repz " | | opStr = = " repnz " )
{
if ( curNodeIdx > = nodeCount ) // in case prefix is listed like a separate instruction
break ;
outInst . mOpPrefixes . push_back ( opStr ) ;
if ( ! readIdent ( opStr , true , " instruction or instruction prefix " , false ) )
return nullptr ;
}
outInst . mOpCode = opStr ;
BfInlineAsmInstruction : : AsmArg asmArg ;
while ( parseArg ( asmArg ) )
{
outInst . mArgs . push_back ( asmArg ) ;
asmArg = BfInlineAsmInstruction : : AsmArg ( ) ;
if ( ! readToken ( BfToken_Comma , " " , true ) )
break ;
+ + curNodeIdx ;
}
if ( curNodeIdx < nodeCount )
return ( BfInlineAsmInstruction * ) Fail ( StrFormat ( " Found unexpected \" %s \" " , NodeToString ( nodes [ curNodeIdx ] ) . c_str ( ) ) , instNode ) ;
//String testStr = outInst.ToString();
int unusedLineChar = 0 ;
auto bfParser = instNode - > GetSourceData ( ) - > ToParserData ( ) ;
if ( bfParser ! = NULL )
bfParser - > GetLineCharAtIdx ( instNode - > GetSrcStart ( ) , outInst . mDebugLine , unusedLineChar ) ;
//return (BfInlineAsmInstruction*)Fail(StrFormat("Line %d\n", outInst.mDebugLine), instNode);
return instNode ;
} ;
// split nodes by newlines into individual instructions, skipping empty lines
Array < BfAstNode * > instrNodes ;
Array < BfInlineAsmInstruction * > dstInstructions ;
//BCF: Add this back
/*for (auto child = asmStatement->mChildren.mHead; child; child = child->mNext)
{
auto childToken = BfNodeDynCast < BfTokenNode > ( child ) ;
if ( childToken & & childToken - > GetToken ( ) = = BfToken_AsmNewline )
{
if ( ! instrNodes . empty ( ) )
{
BfInlineAsmInstruction * instNode = processInstrNodes ( instrNodes ) ;
if ( instNode )
dstInstructions . push_back ( instNode ) ;
instrNodes . clear ( ) ;
}
}
else if ( childToken & & childToken - > GetToken ( ) = = BfToken_Asm )
{
// ignore the actual 'asm' keyword as we no longer need it
continue ; //CDH FIXME this is because ReplaceNode adds the original 'asm' keyword as a child, which I don't need; maybe I'm missing how the CST->AST replacment pattern is intended to work?
}
else
{
instrNodes . push_back ( child ) ;
}
} */
if ( ! instrNodes . empty ( ) )
{
BfInlineAsmInstruction * instNode = processInstrNodes ( instrNodes ) ;
if ( instNode )
dstInstructions . push_back ( instNode ) ;
instrNodes . Clear ( ) ;
}
for ( auto & instNode : dstInstructions )
MoveNode ( instNode , asmStatement ) ;
asmStatement - > mInstructions = std : : move ( dstInstructions ) ;
}
return asmStatement ;
}