Add template algorithm sort

This commit is contained in:
drmortalwombat 2023-08-15 11:05:52 +02:00
parent ae2fbb6256
commit 50cc2afb52
11 changed files with 215 additions and 24 deletions

37
include/opp/algorithm.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef OPP_ALGORITHM_H
#define OPP_ALGORITHM_H
template <class T>
inline void swap(T & x, T & y)
{
T t(x); x = y; y = t;
}
template<class T, class LT>
void sort(T s, T e)
{
while (s != e)
{
auto p = s;
auto q = s;
q++;
while (q != e)
{
if (LT(*q, *p))
{
swap(*q, *p);
p++;
swap(*q, *p);
}
q++;
}
sort<T, LT>(s, p);
p++;
s = p;
}
}
#endif

View File

@ -16,6 +16,11 @@ static inline char sstrlen(const char * sp)
return n; return n;
} }
inline void swap(string & u, string & v)
{
char * p = u.cstr; u.cstr = v.cstr; v.cstr = p;
}
string::string(void) : cstr(nullptr) string::string(void) : cstr(nullptr)
{} {}

View File

@ -6,6 +6,8 @@ class string
private: private:
char * cstr; char * cstr;
friend void swap(string & u, string & v);
public: public:
string(void); string(void);
string(const string & s); string(const string & s);
@ -70,6 +72,8 @@ protected:
string(char l, char * b); string(char l, char * b);
}; };
void swap(string & u, string & v);
#pragma compile("string.cpp") #pragma compile("string.cpp")
#endif #endif

View File

@ -70,6 +70,36 @@ public:
return _data[at]; return _data[at];
} }
T * begin(void)
{
return _data;
}
const T * begin(void) const
{
return _data;
}
const T * cbegin(void) const
{
return _data;
}
T * end(void)
{
return _data + _size;
}
const T * end(void) const
{
return _data + _size;
}
const T * cend(void) const
{
return _data + _size;
}
T & front(void) T & front(void)
{ {
return _data[0]; return _data[0];

View File

@ -842,7 +842,7 @@ Declaration::Declaration(const Location& loc, DecType type)
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr),
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr),
mVTable(nullptr), mTemplate(nullptr), mVTable(nullptr), mTemplate(nullptr),
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr),
mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1),
mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr) mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr)
{} {}
@ -947,6 +947,10 @@ const Ident* Declaration::MangleIdent(void)
sprintf_s(buffer, "%d", (int)mInteger); sprintf_s(buffer, "%d", (int)mInteger);
mMangleIdent = Ident::Unique(buffer); mMangleIdent = Ident::Unique(buffer);
} }
else if (mType == DT_CONST_FUNCTION)
{
mMangleIdent = mQualIdent;
}
else if (mType == DT_TYPE_INTEGER) else if (mType == DT_TYPE_INTEGER)
{ {
char buffer[20]; char buffer[20];
@ -1532,7 +1536,7 @@ bool Declaration::IsTemplateSameParams(const Declaration* dec, const Declaration
bool Declaration::IsSameParams(const Declaration* dec) const bool Declaration::IsSameParams(const Declaration* dec) const
{ {
if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION || mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE) if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION)
{ {
Declaration* ld = mParams, * rd = dec->mParams; Declaration* ld = mParams, * rd = dec->mParams;
while (ld && rd) while (ld && rd)
@ -1545,6 +1549,24 @@ bool Declaration::IsSameParams(const Declaration* dec) const
return !ld && !rd; return !ld && !rd;
} }
else if (mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE)
{
Declaration* ld = mParams, * rd = dec->mParams;
while (ld && rd)
{
if (ld->mType == DT_CONST_FUNCTION && rd->mType == DT_CONST_FUNCTION)
{
if (ld->mValue != rd->mValue)
return false;
}
else if (!ld->mBase->IsSame(rd->mBase))
return false;
ld = ld->mNext;
rd = rd->mNext;
}
return !ld && !rd;
}
else else
return false; return false;
} }

View File

@ -272,7 +272,7 @@ public:
TokenSequence * mTokens; TokenSequence * mTokens;
Parser * mParser; Parser * mParser;
GrowingArray<Declaration*> mCallers, mCalled; GrowingArray<Declaration*> mCallers, mCalled, mFriends;
bool CanAssign(const Declaration* fromType) const; bool CanAssign(const Declaration* fromType) const;
bool IsSame(const Declaration* dec) const; bool IsSame(const Declaration* dec) const;

View File

@ -162,6 +162,28 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p
{ {
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign numeric value to pointer"); mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign numeric value to pointer");
} }
else if( type->mType == DT_TYPE_BOOL && v.mType->mType == DT_TYPE_POINTER)
{
InterInstruction* zins = new InterInstruction(exp->mLocation, IC_CONSTANT);
zins->mDst.mType = IT_POINTER;
zins->mDst.mTemp = proc->AddTemporary(IT_POINTER);
zins->mConst.mType = IT_POINTER;
zins->mConst.mMemory = IM_ABSOLUTE;
zins->mConst.mIntConst = 0;
block->Append(zins);
InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR);
cins->mOperator = IA_CMPNE;
cins->mSrc[0].mType = IT_POINTER;
cins->mSrc[0].mTemp = v.mTemp;
cins->mSrc[1].mType = IT_POINTER;
cins->mSrc[1].mTemp = zins->mDst.mTemp;
cins->mDst.mType = IT_BOOL;
cins->mDst.mTemp = proc->AddTemporary(IT_BOOL);
block->Append(cins);
v.mTemp = cins->mDst.mTemp;
v.mType = type;
}
else if (v.mType->mSize < type->mSize) else if (v.mType->mSize < type->mSize)
{ {
if (v.mType->mSize == 1 && type->mSize == 2) if (v.mType->mSize == 1 && type->mSize == 2)
@ -3697,6 +3719,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID)
mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type"); mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type");
else if (procType->mBase->mType == DT_TYPE_BOOL && (vr.mType->IsIntegerType() || vr.mType->mType == DT_TYPE_POINTER))
;
else if (!procType->mBase->CanAssign(vr.mType)) else if (!procType->mBase->CanAssign(vr.mType))
mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type"); mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type");

View File

@ -19,6 +19,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn
mInlineCall = false; mInlineCall = false;
mCompilerOptionSP = 0; mCompilerOptionSP = 0;
mThisPointer = nullptr; mThisPointer = nullptr;
mFunction = nullptr;
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
mCharMap[i] = i; mCharMap[i] = i;
@ -248,6 +249,13 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
flags |= DTF_PRIVATE | DTF_PROTECTED; flags |= DTF_PRIVATE | DTF_PROTECTED;
ConsumeToken(TK_COLON); ConsumeToken(TK_COLON);
} }
else if (ConsumeTokenIf(TK_FRIEND))
{
mScope = oscope;
Declaration* fdec = ParseDeclaration(nullptr, true, false);
dec->mFriends.Push(fdec);
mScope = dec->mScope;
}
else if (ConsumeTokenIf(TK_CLOSE_BRACE)) else if (ConsumeTokenIf(TK_CLOSE_BRACE))
{ {
break; break;
@ -3210,7 +3218,7 @@ void Parser::ParseVariableInit(Declaration* ndec)
mErrors->Error(pexp->mLocation, EERR_INCOMPATIBLE_TYPES, "Can not initialize variable with expression", ndec->mIdent); mErrors->Error(pexp->mLocation, EERR_INCOMPATIBLE_TYPES, "Can not initialize variable with expression", ndec->mIdent);
} }
Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis) Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis, Declaration* ptempl)
{ {
bool definingType = false, destructor = false; bool definingType = false, destructor = false;
uint64 storageFlags = 0, typeFlags = 0; uint64 storageFlags = 0, typeFlags = 0;
@ -3734,14 +3742,30 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
} }
else else
{ {
if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) if (ptempl)
ptempl->mBase = ndec;
if (ptempl && mTemplateScope && ndec->mIdent)
{ {
if (ConsumeTokenIf(TK_CONST)) if (!strstr(ndec->mQualIdent->mString, mTemplateScope->mName->mString))
PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildConstPointer(ndec->mLocation)); {
else ndec->mIdent = ndec->mIdent->Mangle(mTemplateScope->mName->mString);
PrependThisArgument(ndec->mBase, pthis); ndec->mQualIdent = ndec->mQualIdent->Mangle(mTemplateScope->mName->mString);
}
} }
if (ndec->mBase->mType == DT_TYPE_FUNCTION)
{
if (pthis)
{
if (ConsumeTokenIf(TK_CONST))
PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildConstPointer(ndec->mLocation));
else
PrependThisArgument(ndec->mBase, pthis);
}
}
if (variable) if (variable)
{ {
ndec->mFlags |= storageFlags; ndec->mFlags |= storageFlags;
@ -3776,11 +3800,15 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
if (ndec->mIdent == ndec->mQualIdent) if (ndec->mIdent == ndec->mQualIdent)
{ {
Declaration* ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec); Declaration* ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec);
#if 0
if (ldec && ldec->mTemplate && mTemplateScope) if (ldec && ldec->mTemplate && mTemplateScope)
{ {
ndec->mQualIdent = ndec->mQualIdent->Mangle(mTemplateScope->mName->mString); ndec->mQualIdent = ndec->mQualIdent->Mangle(mTemplateScope->mName->mString);
} }
else if (ldec && ldec != pdec) else
#endif
if (ldec && ldec != pdec)
mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition");
} }
else if (!pdec) else if (!pdec)
@ -4085,14 +4113,16 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
if (ndec->mBase->mType == DT_TYPE_FUNCTION) if (ndec->mBase->mType == DT_TYPE_FUNCTION)
{ {
if (ndec->mFlags & DTF_DEFINED) if (ndec->mFlags & DTF_DEFINED)
mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition"); mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition", ndec->mQualIdent);
ndec->mCompilerOptions = mCompilerOptions; ndec->mCompilerOptions = mCompilerOptions;
ndec->mBase->mCompilerOptions = mCompilerOptions; ndec->mBase->mCompilerOptions = mCompilerOptions;
ndec->mVarIndex = -1; ndec->mVarIndex = -1;
mFunction = ndec;
ndec->mValue = ParseFunction(ndec->mBase); ndec->mValue = ParseFunction(ndec->mBase);
mFunction = nullptr;
if (pthis) if (pthis)
ndec->mFlags |= DTF_REQUEST_INLINE; ndec->mFlags |= DTF_REQUEST_INLINE;
@ -4309,6 +4339,10 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
exp = new Expression(mScanner->mLocation, EX_TYPE); exp = new Expression(mScanner->mLocation, EX_TYPE);
exp->mDecValue = nullptr; exp->mDecValue = nullptr;
exp->mDecType = ParseBaseTypeDeclaration(0, true); exp->mDecType = ParseBaseTypeDeclaration(0, true);
while (ConsumeTokenIf(TK_MUL))
exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation);
while (ConsumeTokenIf(TK_BINARY_AND))
exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation);
} }
break; break;
case TK_CONST: case TK_CONST:
@ -4555,6 +4589,10 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
exp = new Expression(mScanner->mLocation, EX_TYPE); exp = new Expression(mScanner->mLocation, EX_TYPE);
exp->mDecValue = nullptr; exp->mDecValue = nullptr;
exp->mDecType = dec; exp->mDecType = dec;
while (ConsumeTokenIf(TK_MUL))
exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation);
while (ConsumeTokenIf(TK_BINARY_AND))
exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation);
} }
} }
else if (dec->mType == DT_ELEMENT) else if (dec->mType == DT_ELEMENT)
@ -4737,7 +4775,12 @@ Expression* Parser::ParseQualify(Expression* exp)
if (tp && tp->mType == DT_ARGUMENT) if (tp && tp->mType == DT_ARGUMENT)
tp = tp->mBase; tp = tp->mBase;
if (!(tp && tp->mBase->IsConstSame(dtype))) if (!(tp && tp->mBase->IsConstSame(dtype)))
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident); {
if (dtype->mFriends.Contains(mFunction))
;
else
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident);
}
} }
mScanner->NextToken(); mScanner->NextToken();
@ -4952,7 +4995,13 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
else if (ptype->IsSame(ex->mDecType)) else if (ptype->IsSame(ex->mDecType))
; ;
else if (CanCoerceExpression(ex, ptype)) else if (CanCoerceExpression(ex, ptype))
{
dist += 512; dist += 512;
if (ptype->mType == DT_TYPE_REFERENCE)
dist += 4;
else if (ptype->mType == DT_TYPE_RVALUEREF)
dist += 2;
}
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)
{ {
if (ex->IsLValue()) if (ex->IsLValue())
@ -5247,7 +5296,9 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2)
while (fdec) while (fdec)
{ {
int d = OverloadDistance(fdec, exp->mRight); int d = OverloadDistance(fdec, exp->mRight);
if (d < ibest) if (d == NOOVERLOAD)
;
else if (d < ibest)
{ {
dbest = fdec; dbest = fdec;
pbest = exp->mRight; pbest = exp->mRight;
@ -5262,7 +5313,9 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2)
while (fdec2) while (fdec2)
{ {
int d = OverloadDistance(fdec2, exp2->mRight); int d = OverloadDistance(fdec2, exp2->mRight);
if (d < ibest) if (d == NOOVERLOAD)
;
else if (d < ibest)
{ {
dbest = fdec2; dbest = fdec2;
pbest = exp2->mRight; pbest = exp2->mRight;
@ -6244,6 +6297,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
if (exp->mType == EX_ASSIGNMENT) if (exp->mType == EX_ASSIGNMENT)
{ {
Declaration* tdec = exp->mLeft->mDecType; Declaration* tdec = exp->mLeft->mDecType;
while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF)
tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)
{ {
const Ident* opident = nullptr; const Ident* opident = nullptr;
@ -6320,7 +6376,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
texp->mLeft = exp->mLeft; texp->mLeft = exp->mLeft;
texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = exp->mDecType; texp->mDecType->mBase = tdec;
texp->mDecType->mSize = 2; texp->mDecType->mSize = 2;
Expression* lexp = new Expression(nexp->mLocation, EX_LIST); Expression* lexp = new Expression(nexp->mLocation, EX_LIST);
@ -7138,7 +7194,10 @@ Expression* Parser::ParseStatement(void)
exp = new Expression(mScanner->mLocation, EX_RETURN); exp = new Expression(mScanner->mLocation, EX_RETURN);
if (mScanner->mToken != TK_SEMICOLON) if (mScanner->mToken != TK_SEMICOLON)
{ {
exp->mLeft = CleanupExpression(ParseRExpression()); exp->mLeft = ParseRExpression();
if (mReturnType)
exp->mLeft = CoerceExpression(exp->mLeft, mReturnType);
exp->mLeft = CleanupExpression(exp->mLeft);
if (exp->mLeft->mType == EX_CONSTRUCT && mReturnType && mReturnType->mType == DT_TYPE_STRUCT) if (exp->mLeft->mType == EX_CONSTRUCT && mReturnType && mReturnType->mType == DT_TYPE_STRUCT)
{ {
Expression* cexp = exp->mLeft->mLeft->mLeft; Expression* cexp = exp->mLeft->mLeft->mLeft;
@ -7325,8 +7384,13 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
{ {
if (exp->mType == EX_TYPE) if (exp->mType == EX_TYPE)
epdec->mBase = exp->mDecType; epdec->mBase = exp->mDecType;
else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_FUNCTION)
epdec->mBase = exp->mDecValue;
else else
{
mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Type parameter expected", pdec->mIdent); mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Type parameter expected", pdec->mIdent);
epdec->mBase = TheVoidTypeDeclaration;
}
} }
else else
{ {
@ -7367,14 +7431,13 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
p->mScanner->Replay(tmpld->mTokens); p->mScanner->Replay(tmpld->mTokens);
tdec->mScope->mName = tdec->MangleIdent(); tdec->mScope->mName = tdec->MangleIdent();
p->mTemplateScope = tdec->mScope;
tdec->mBase = p->ParseDeclaration(nullptr, true, false);
p->mTemplateScope = nullptr;
tdec->mNext = tmpld->mNext; tdec->mNext = tmpld->mNext;
tmpld->mNext = tdec; tmpld->mNext = tdec;
p->mTemplateScope = tdec->mScope;
tdec->mBase = p->ParseDeclaration(nullptr, true, false, nullptr, tdec);
p->mTemplateScope = nullptr;
if (tdec->mBase->mType == DT_ANON) if (tdec->mBase->mType == DT_ANON)
{ {
tdec->mBase = tdec->mBase->mBase; tdec->mBase = tdec->mBase->mBase;
@ -7533,6 +7596,8 @@ void Parser::ParseTemplateDeclaration(void)
// Function template // Function template
mTemplateScope = tdec->mScope; mTemplateScope = tdec->mScope;
ConsumeTokenIf(TK_INLINE);
Declaration* bdec = ParseBaseTypeDeclaration(0, false); Declaration* bdec = ParseBaseTypeDeclaration(0, false);
Declaration* adec = ParsePostfixDeclaration(); Declaration* adec = ParsePostfixDeclaration();

View File

@ -15,7 +15,7 @@ public:
DeclarationScope * mGlobals, * mScope, * mTemplateScope; DeclarationScope * mGlobals, * mScope, * mTemplateScope;
int mLocalIndex; int mLocalIndex;
CompilationUnits * mCompilationUnits; CompilationUnits * mCompilationUnits;
Declaration * mThisPointer, * mReturnType; Declaration * mThisPointer, * mReturnType, * mFunction;
LinkerSection * mCodeSection, * mDataSection, * mBSSection; LinkerSection * mCodeSection, * mDataSection, * mBSSection;
@ -58,7 +58,7 @@ protected:
Expression* CleanupExpression(Expression* exp); Expression* CleanupExpression(Expression* exp);
Declaration* ParseBaseTypeDeclaration(uint64 flags, bool qualified); Declaration* ParseBaseTypeDeclaration(uint64 flags, bool qualified);
Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr); Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr, Declaration * ptempl = nullptr);
Declaration* ParseStructDeclaration(uint64 flags, DecType dt); Declaration* ParseStructDeclaration(uint64 flags, DecType dt);
Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp);

View File

@ -163,6 +163,7 @@ const char* TokenNames[] =
"'virtual'", "'virtual'",
"'operator'", "'operator'",
"'template'", "'template'",
"'friend'",
}; };
@ -1511,6 +1512,8 @@ void Scanner::NextRawToken(void)
mToken = TK_VIRTUAL; mToken = TK_VIRTUAL;
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "template")) else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "template"))
mToken = TK_TEMPLATE; mToken = TK_TEMPLATE;
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "friend"))
mToken = TK_FRIEND;
else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator"))
{ {
NextRawToken(); NextRawToken();

View File

@ -162,6 +162,7 @@ enum Token
TK_VIRTUAL, TK_VIRTUAL,
TK_OPERATOR, TK_OPERATOR,
TK_TEMPLATE, TK_TEMPLATE,
TK_FRIEND,
NUM_TOKENS NUM_TOKENS
}; };