Improve C++ compliance

This commit is contained in:
drmortalwombat 2023-08-08 14:19:08 +02:00
parent c46870ec10
commit b7630450f1
9 changed files with 358 additions and 17 deletions

View File

@ -51,6 +51,8 @@ enum DecType
DT_NAMESPACE, DT_NAMESPACE,
DT_BASECLASS, DT_BASECLASS,
DT_TEMPLATE,
DT_VTABLE DT_VTABLE
}; };

View File

@ -545,6 +545,12 @@ int Emulator::Emulate(int startIP, int trace)
mIP = mMemory[0x101 + mRegS] + 256 * mMemory[0x102 + mRegS] + 1; mIP = mMemory[0x101 + mRegS] + 256 * mMemory[0x102 + mRegS] + 1;
mRegS += 2; mRegS += 2;
} }
else if (mIP == 0xff81)
{
printf("------------------ CLEAR ---------------\n");
mIP = mMemory[0x101 + mRegS] + 256 * mMemory[0x102 + mRegS] + 1;
mRegS += 2;
}
uint8 opcode = mMemory[mIP]; uint8 opcode = mMemory[mIP];
AsmInsData d = DecInsData[opcode]; AsmInsData d = DecInsData[opcode];

View File

@ -80,6 +80,7 @@ enum ErrorID
EERR_INVALID_OPERATOR, EERR_INVALID_OPERATOR,
EERR_MISSING_TEMP, EERR_MISSING_TEMP,
EERR_NON_STATIC_MEMBER, EERR_NON_STATIC_MEMBER,
EERR_TEMPLATE_PARAMS,
ERRR_STACK_OVERFLOW, ERRR_STACK_OVERFLOW,
ERRR_INVALID_NUMBER, ERRR_INVALID_NUMBER,

View File

@ -13420,6 +13420,18 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
sins->mSrc[0].mFinal = false; sins->mSrc[0].mFinal = false;
assert(nins->mSrc[0].mTemp >= 0); assert(nins->mSrc[0].mTemp >= 0);
// Propagate all loads to move temps
for (int t = j + 1; t < mInstructions.Size(); t++)
{
InterInstruction* ti = mInstructions[t];
if (ti->mCode == IC_LOAD && SameMem(ti->mSrc[0], ins->mSrc[0]))
{
ti->mCode = IC_LOAD_TEMPORARY;
ti->mSrc[0].mTemp = ins->mDst.mTemp;
}
}
// Move store behind loop // Move store behind loop
tailBlock->mInstructions.Insert(0, sins); tailBlock->mInstructions.Insert(0, sins);
mInstructions.Remove(j); mInstructions.Remove(j);
@ -16724,7 +16736,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "playSong"); CheckFunc = !strcmp(mIdent->mString, "MenuItem::+MenuItem");
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];
@ -16899,6 +16911,8 @@ void InterCodeProcedure::Close(void)
TempForwarding(); TempForwarding();
RemoveUnusedInstructions(); RemoveUnusedInstructions();
DisassembleDebug("pre single block loop opt");
ResetVisited(); ResetVisited();
mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet, mModule->mGlobalVars); mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet, mModule->mGlobalVars);

View File

@ -4111,6 +4111,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
vr = Dereference(proc, exp, block, vr); vr = Dereference(proc, exp, block, vr);
return CoerceType(proc, exp, block, vr, exp->mDecType); return CoerceType(proc, exp, block, vr, exp->mDecType);
} }
else if (exp->mDecType->mType == DT_TYPE_VOID)
{
}
else else
{ {
vr = Dereference(proc, exp, block, vr); vr = Dereference(proc, exp, block, vr);

View File

@ -284,6 +284,15 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
if (dec->mScope->Insert(mdec->mIdent, mdec)) if (dec->mScope->Insert(mdec->mIdent, mdec))
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent);
if (dec->mConst)
{
Declaration* cmdec = mdec->Clone();
cmdec->mBase = mdec->mBase->ToConstType();
dec->mConst->mScope->Insert(cmdec->mIdent, cmdec);
dec->mConst->mSize = dec->mSize;
}
if (mlast) if (mlast)
mlast->mNext = mdec; mlast->mNext = mdec;
else else
@ -442,6 +451,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified)
{ {
Declaration* dec = nullptr; Declaration* dec = nullptr;
const Ident* pident = nullptr;
switch (mScanner->mToken) switch (mScanner->mToken)
{ {
@ -551,6 +561,7 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified)
break; break;
case TK_IDENT: case TK_IDENT:
pident = mScanner->mTokenIdent;
dec = mScope->Lookup(mScanner->mTokenIdent); dec = mScope->Lookup(mScanner->mTokenIdent);
if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS) if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS)
dec = mScope->mParent->Lookup(mScanner->mTokenIdent); dec = mScope->mParent->Lookup(mScanner->mTokenIdent);
@ -560,6 +571,7 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified)
{ {
if (ExpectToken(TK_IDENT)) if (ExpectToken(TK_IDENT))
{ {
pident = mScanner->mTokenIdent;
dec = dec->mScope->Lookup(mScanner->mTokenIdent); dec = dec->mScope->Lookup(mScanner->mTokenIdent);
mScanner->NextToken(); mScanner->NextToken();
} }
@ -594,15 +606,9 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified)
} }
} }
else if (!dec) else if (!dec)
{ mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident);
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", mScanner->mTokenIdent);
mScanner->NextToken();
}
else else
{ mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent);
mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", mScanner->mTokenIdent);
mScanner->NextToken();
}
break; break;
case TK_ENUM: case TK_ENUM:
@ -3424,6 +3430,21 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
if (mScanner->mToken == TK_OPEN_BRACE) if (mScanner->mToken == TK_OPEN_BRACE)
{ {
//
// Take parameter names from new declaration
//
Declaration* npdec = ctdec->mParams, * ppdec = cdec->mBase->mParams;
while (npdec && ppdec)
{
if (npdec->mIdent)
{
ppdec->mIdent = npdec->mIdent;
ppdec->mQualIdent = npdec->mQualIdent;
}
npdec = npdec->mNext;
ppdec = ppdec->mNext;
}
if (cdec->mFlags & DTF_DEFINED) if (cdec->mFlags & DTF_DEFINED)
mErrors->Error(cdec->mLocation, EERR_DUPLICATE_DEFINITION, "Function already has a body"); mErrors->Error(cdec->mLocation, EERR_DUPLICATE_DEFINITION, "Function already has a body");
@ -4001,7 +4022,7 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec)
texp->mLeft = vexp; texp->mLeft = vexp;
texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = pdec->mBase; texp->mDecType->mBase = dec->mBase;
texp->mDecType->mSize = 2; texp->mDecType->mSize = 2;
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
@ -4014,12 +4035,13 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec)
Expression* aexp; Expression* aexp;
if (dec->mBase->mCopyConstructor && !(dec->mValue->mType == EX_CALL && dec->mValue->mDecType->mType == DT_TYPE_STRUCT)) Declaration* fcons = dec->mBase->mScope->Lookup(dec->mBase->mIdent->PreMangle("+"));
if (fcons && !(dec->mValue->mType == EX_CALL && dec->mValue->mDecType->mType == DT_TYPE_STRUCT))
{ {
Declaration* mdec = dec->mBase->mCopyConstructor;
Expression* cexp = new Expression(dec->mLocation, EX_CONSTANT); Expression* cexp = new Expression(dec->mLocation, EX_CONSTANT);
cexp->mDecValue = mdec; cexp->mDecValue = fcons;
cexp->mDecType = cexp->mDecValue->mBase; cexp->mDecType = cexp->mDecValue->mBase;
aexp = new Expression(mScanner->mLocation, EX_CALL); aexp = new Expression(mScanner->mLocation, EX_CALL);
@ -4027,6 +4049,8 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec)
aexp->mRight = new Expression(dec->mLocation, EX_LIST); aexp->mRight = new Expression(dec->mLocation, EX_LIST);
aexp->mRight->mLeft = texp; aexp->mRight->mLeft = texp;
aexp->mRight->mRight = dec->mValue; aexp->mRight->mRight = dec->mValue;
ResolveOverloadCall(aexp);
} }
else else
{ {
@ -4710,6 +4734,8 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
dist += 4; dist += 4;
else if (ptype->IsSame(ex->mDecType)) else if (ptype->IsSame(ex->mDecType))
; ;
else if (CanCoerceExpression(ex, ptype))
dist += 512;
else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT) else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT)
{ {
int ncast = 0; int ncast = 0;
@ -4771,12 +4797,52 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
return dist; return dist;
} }
bool Parser::CanCoerceExpression(Expression* exp, Declaration* type)
{
Declaration* tdec = exp->mDecType;
while (tdec->mType == DT_TYPE_REFERENCE)
tdec = tdec->mBase;
while (type->mType == DT_TYPE_REFERENCE)
type = type->mBase;
if (tdec->mType == DT_TYPE_STRUCT)
{
Declaration* fexp = tdec->mScope->Lookup(Ident::Unique("(cast)"));
if (fexp)
{
while (fexp && !fexp->mBase->mBase->IsSame(type))
fexp = fexp->mNext;
if (fexp)
return true;
}
}
if (type->mType == DT_TYPE_STRUCT)
{
if (!type->IsConstSame(tdec))
{
Declaration* fcons = type->mScope->Lookup(type->mIdent->PreMangle("+"));
if (fcons)
{
while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && fcons->mBase->mParams->mNext->mBase->CanAssign(tdec)))
fcons = fcons->mNext;
if (fcons)
return true;
}
}
}
return false;
}
Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) Expression* Parser::CoerceExpression(Expression* exp, Declaration* type)
{ {
Declaration* tdec = exp->mDecType; Declaration* tdec = exp->mDecType;
while (tdec->mType == DT_TYPE_REFERENCE) while (tdec->mType == DT_TYPE_REFERENCE)
tdec = tdec->mBase; tdec = tdec->mBase;
while (type->mType == DT_TYPE_REFERENCE)
type = type->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)
{ {
@ -4802,6 +4868,78 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type)
} }
} }
} }
if (type->mType == DT_TYPE_STRUCT)
{
if (!type->IsConstSame(tdec))
{
Declaration* fcons = type->mScope->Lookup(type->mIdent->PreMangle("+"));
if (fcons)
{
while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && fcons->mBase->mParams->mNext->mBase->CanAssign(tdec)))
fcons = fcons->mNext;
if (fcons)
{
Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE);
vdec->mBase = type->ToMutableType();
vdec->mVarIndex = mLocalIndex++;
vdec->mSize = type->mSize;
vdec->mFlags |= DTF_DEFINED;
Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE);
vexp->mDecType = vdec->mBase;
vexp->mDecValue = vdec;
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = fcons;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* fexp = new Expression(mScanner->mLocation, EX_CALL);
fexp->mLeft = cexp;
fexp->mRight = exp;
Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = vexp;
texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = vdec->mBase;
texp->mDecType->mSize = 2;
Expression* lexp = new Expression(mScanner->mLocation, EX_LIST);
lexp->mLeft = texp;
lexp->mRight = fexp->mRight;
fexp->mRight = lexp;
Expression* dexp = nullptr;
if (type->mDestructor)
{
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = type->mDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = texp;
}
Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT);
nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST);
nexp->mLeft->mLeft = fexp;
nexp->mLeft->mRight = dexp;
nexp->mRight = vexp;
nexp->mDecType = vexp->mDecType;
return nexp;
}
}
}
}
return exp; return exp;
} }
@ -4817,13 +4955,19 @@ void Parser::CompleteFunctionDefaultParams(Expression* exp)
{ {
if (pexp) if (pexp)
{ {
Expression* exp = pexp;
if (pexp->mType == EX_LIST) if (pexp->mType == EX_LIST)
{ {
pexp->mLeft = CoerceExpression(pexp->mLeft, pdec->mBase);
lexp = pexp; lexp = pexp;
pexp = pexp->mRight; pexp = pexp->mRight;
} }
else else
{
lexp->mRight = CoerceExpression(lexp->mRight, pdec->mBase);
pexp = nullptr; pexp = nullptr;
}
} }
else if (pdec->mValue) else if (pdec->mValue)
{ {
@ -4887,9 +5031,14 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2)
} }
if (ibest == NOOVERLOAD) if (ibest == NOOVERLOAD)
mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call"); {
#if _DEBUG
int d = OverloadDistance(exp->mLeft->mDecValue->mBase, exp->mRight);
#endif
mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call", exp->mLeft->mDecValue->mQualIdent);
}
else if (nbest > 1) else if (nbest > 1)
mErrors->Error(exp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call"); mErrors->Error(exp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call", exp->mLeft->mDecValue->mQualIdent);
else else
{ {
exp->mLeft->mDecValue = dbest; exp->mLeft->mDecValue = dbest;
@ -6831,6 +6980,69 @@ Expression* Parser::ParseSwitchStatement(void)
return sexp; return sexp;
} }
void Parser::ParseTemplate(void)
{
ConsumeToken(TK_LESS_THAN);
Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE);
Declaration* ppdec = nullptr;
for (;;)
{
Declaration* pdec = nullptr;
if (ConsumeTokenIf(TK_CLASS))
{
if (mScanner->mToken == TK_IDENT)
{
Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT);
pdec->mIdent = mScanner->mTokenIdent;
pdec->mBase = TheVoidTypeDeclaration;
mScanner->NextToken();
}
else
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected");
}
else if (ConsumeTokenIf(TK_INT))
{
if (mScanner->mToken == TK_IDENT)
{
Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT);
pdec->mIdent = mScanner->mTokenIdent;
pdec->mBase = TheSignedIntTypeDeclaration;
mScanner->NextToken();
}
else
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected");
}
else
mErrors->Error(mScanner->mLocation, EERR_TEMPLATE_PARAMS, "'class' or 'int' expected as template parameter");
if (pdec)
{
if (ppdec)
ppdec->mNext = pdec;
else
tdec->mParams = pdec;
ppdec = pdec;
}
if (!ConsumeTokenIf(TK_COMMA))
break;
}
ConsumeToken(TK_GREATER_THAN);
if (mScanner->mToken == TK_CLASS)
{
// Class template
}
else
{
// Function template
}
}
Expression* Parser::ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset) Expression* Parser::ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset)
@ -7541,6 +7753,11 @@ void Parser::ParsePragma(void)
} }
ConsumeToken(TK_CLOSE_PARENTHESIS); ConsumeToken(TK_CLOSE_PARENTHESIS);
} }
else if (!strcmp(mScanner->mTokenIdent->mString, "once"))
{
mScanner->MarkSourceOnce();
mScanner->NextToken();
}
else if (!strcmp(mScanner->mTokenIdent->mString, "compile")) else if (!strcmp(mScanner->mTokenIdent->mString, "compile"))
{ {
mScanner->NextToken(); mScanner->NextToken();
@ -8453,6 +8670,11 @@ void Parser::Parse(void)
} }
else if (mScanner->mToken == TK_SEMICOLON) else if (mScanner->mToken == TK_SEMICOLON)
mScanner->NextToken(); mScanner->NextToken();
else if (mScanner->mToken == TK_TEMPLATE)
{
mScanner->NextToken();
ParseTemplate();
}
else if (mScanner->mToken == TK_NAMESPACE) else if (mScanner->mToken == TK_NAMESPACE)
{ {
mScanner->NextToken(); mScanner->NextToken();

View File

@ -90,8 +90,11 @@ protected:
int OverloadDistance(Declaration* pdec, Expression* pexp); int OverloadDistance(Declaration* pdec, Expression* pexp);
Expression * ResolveOverloadCall(Expression* exp, Expression * exp2 = nullptr); Expression * ResolveOverloadCall(Expression* exp, Expression * exp2 = nullptr);
Expression* CoerceExpression(Expression* exp, Declaration* type); Expression* CoerceExpression(Expression* exp, Declaration* type);
bool CanCoerceExpression(Expression* exp, Declaration* type);
void CompleteFunctionDefaultParams(Expression* exp); void CompleteFunctionDefaultParams(Expression* exp);
void ParseTemplate(void);
Expression* ParseSimpleExpression(bool lhs); Expression* ParseSimpleExpression(bool lhs);
Expression* ParsePrefixExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs);
Expression* ParsePostfixExpression(bool lhs); Expression* ParsePostfixExpression(bool lhs);

View File

@ -162,6 +162,7 @@ const char* TokenNames[] =
"'delete'", "'delete'",
"'virtual'", "'virtual'",
"'operator'", "'operator'",
"'template'",
}; };
@ -306,6 +307,25 @@ Macro* MacroDict::Lookup(const Ident* ident)
} }
TokenSequence::TokenSequence(Scanner* scanner)
: mNext(nullptr), mLocation(scanner->mLocation), mToken(scanner->mToken),
mTokenIdent(scanner->mTokenIdent), mTokenChar(scanner->mTokenChar),
mTokenInteger(scanner->mTokenInteger), mTokenNumber(scanner->mTokenNumber),
mTokenString(nullptr)
{
if (mToken == TK_STRING)
{
int ssize = strlen(scanner->mTokenString);
char * str = new char[ssize + 1];
strcpy_s(str, ssize + 1, scanner->mTokenString);
mTokenString = str;
}
}
TokenSequence::~TokenSequence(void)
{
delete[] mTokenString;
}
Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) Scanner::Scanner(Errors* errors, Preprocessor* preprocessor)
: mErrors(errors), mPreprocessor(preprocessor) : mErrors(errors), mPreprocessor(preprocessor)
@ -324,6 +344,9 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor)
mDefineArguments = nullptr; mDefineArguments = nullptr;
mToken = TK_NONE; mToken = TK_NONE;
mUngetToken = TK_NONE; mUngetToken = TK_NONE;
mReplay = nullptr;
mOnceDict = new MacroDict();
NextChar(); NextChar();
@ -336,6 +359,18 @@ Scanner::~Scanner(void)
} }
TokenSequence* Scanner::Record(void)
{
return new TokenSequence(this);
}
const TokenSequence* Scanner::Replay(const TokenSequence* replay)
{
const TokenSequence* seq = mReplay;
mReplay = replay;
return seq;
}
const char* Scanner::TokenName(Token token) const const char* Scanner::TokenName(Token token) const
{ {
return TokenNames[token]; return TokenNames[token];
@ -412,8 +447,32 @@ void Scanner::AddMacro(const Ident* ident, const char* value)
mDefines->Insert(macro); mDefines->Insert(macro);
} }
void Scanner::MarkSourceOnce(void)
{
const Ident* fident = Ident::Unique(mPreprocessor->mSource->mFileName);
Macro* macro = new Macro(fident, nullptr);
mOnceDict->Insert(macro);
}
void Scanner::NextToken(void) void Scanner::NextToken(void)
{ {
if (mReplay)
{
mLocation = mReplay->mLocation;
mToken = mReplay->mToken;
mTokenIdent = mReplay->mTokenIdent;
mTokenChar = mReplay->mTokenChar;
mTokenNumber = mReplay->mTokenNumber;
mTokenInteger = mReplay->mTokenInteger;
if (mReplay->mTokenString)
strcpy_s(mTokenString, mReplay->mTokenString);
mReplay = mReplay->mNext;
return;
}
for (;;) for (;;)
{ {
NextRawToken(); NextRawToken();
@ -503,6 +562,8 @@ void Scanner::NextToken(void)
{ {
if (!mPreprocessor->OpenSource("Including", mTokenString, true)) if (!mPreprocessor->OpenSource("Including", mTokenString, true))
mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Could not open source file", mTokenString); mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Could not open source file", mTokenString);
else if (mOnceDict->Lookup(Ident::Unique(mPreprocessor->mSource->mFileName)))
mPreprocessor->CloseSource();
} }
else if (mToken == TK_LESS_THAN) else if (mToken == TK_LESS_THAN)
{ {
@ -510,6 +571,8 @@ void Scanner::NextToken(void)
StringToken('>', 'a'); StringToken('>', 'a');
if (!mPreprocessor->OpenSource("Including", mTokenString, false)) if (!mPreprocessor->OpenSource("Including", mTokenString, false))
mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Could not open source file", mTokenString); mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Could not open source file", mTokenString);
else if (mOnceDict->Lookup(Ident::Unique(mPreprocessor->mSource->mFileName)))
mPreprocessor->CloseSource();
} }
} }
else if (mToken == TK_PREP_DEFINE) else if (mToken == TK_PREP_DEFINE)
@ -1426,6 +1489,8 @@ void Scanner::NextRawToken(void)
mToken = TK_DELETE; mToken = TK_DELETE;
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "virtual")) else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "virtual"))
mToken = TK_VIRTUAL; mToken = TK_VIRTUAL;
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "template"))
mToken = TK_TEMPLATE;
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator"))
{ {
NextRawToken(); NextRawToken();

View File

@ -161,6 +161,7 @@ enum Token
TK_DELETE, TK_DELETE,
TK_VIRTUAL, TK_VIRTUAL,
TK_OPERATOR, TK_OPERATOR,
TK_TEMPLATE,
NUM_TOKENS NUM_TOKENS
}; };
@ -204,6 +205,24 @@ protected:
MacroDict * mParent; MacroDict * mParent;
}; };
class Scanner;
struct TokenSequence
{
TokenSequence * mNext;
Location mLocation;
Token mToken;
const Ident * mTokenIdent;
char mTokenChar;
const char * mTokenString;
double mTokenNumber;
int64 mTokenInteger;
TokenSequence(Scanner* scanner);
~TokenSequence(void);
};
class Scanner class Scanner
{ {
public: public:
@ -214,6 +233,9 @@ public:
void NextToken(void); void NextToken(void);
TokenSequence* Record(void);
const TokenSequence* Replay(const TokenSequence * sequence);
void Warning(const char * error); void Warning(const char * error);
void Error(const char * error); void Error(const char * error);
@ -247,6 +269,7 @@ public:
uint64 mCompilerOptions; uint64 mCompilerOptions;
void AddMacro(const Ident* ident, const char* value); void AddMacro(const Ident* ident, const char* value);
void MarkSourceOnce(void);
protected: protected:
void NextRawToken(void); void NextRawToken(void);
@ -261,10 +284,12 @@ protected:
int mMacroExpansionDepth; int mMacroExpansionDepth;
MacroDict* mDefines, * mDefineArguments; MacroDict* mDefines, * mDefineArguments, * mOnceDict;
Token mUngetToken; Token mUngetToken;
const TokenSequence* mReplay;
void StringToken(char terminator, char mode); void StringToken(char terminator, char mode);
void CharToken(char mode); void CharToken(char mode);
bool NextChar(void); bool NextChar(void);