diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 7cec76d..e08c748 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1658,7 +1658,7 @@ uint8* Parser::ParseStringLiteral(int & msize) return d; } -Expression* Parser::ParseInitExpression(Declaration* dtype) +Expression* Parser::ParseInitExpression(Declaration* dtype, bool inner) { Expression* exp = nullptr; Declaration* dec; @@ -1676,8 +1676,33 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) else mErrors->Error(mScanner->mLocation, EERR_UNDEFINED_OBJECT, "Constant for undefined anonymous type"); } - if (ConsumeTokenIf(TK_OPEN_BRACE)) + + if (mScanner->mToken == TK_STRING && dtype->mType == DT_TYPE_ARRAY && dtype->mBase->mType == DT_TYPE_INTEGER && dtype->mBase->mSize == 1) { + int ds = dtype->mSize; + uint8* d = ParseStringLiteral(ds); + + if (!(dtype->mFlags & DTF_DEFINED)) + { + dtype->mFlags |= DTF_DEFINED; + dtype->mSize = int(ds); + } + + dec = new Declaration(mScanner->mLocation, DT_CONST_DATA); + dec->mBase = dtype; + dec->mSize = dtype->mSize; + dec->mSection = mDataSection; + + dec->mData = d; + + if (ds > dtype->mSize + 1) + mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "String constant is too large for char array"); + } + else if ((inner && !dtype->mDefaultConstructor) || ConsumeTokenIf(TK_OPEN_BRACE)) + { + if (inner && ConsumeTokenIf(TK_OPEN_BRACE)) + inner = false; + dec = new Declaration(mScanner->mLocation, DT_CONST_STRUCT); dec->mBase = dtype; dec->mSize = dtype->mSize; @@ -1732,7 +1757,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) ConsumeToken(TK_ASSIGN); } - Expression* texp = ParseInitExpression(dtype->mBase); + Expression* texp = ParseInitExpression(dtype->mBase, true); texp = texp->ConstantFold(mErrors, mDataSection); for (int i = 0; i < nrep; i++) { @@ -1748,8 +1773,15 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) size += dtype->mBase->mSize; } + if (inner && (dtype->mFlags & DTF_DEFINED) && size >= dtype->mSize) + break; if (!ConsumeTokenIf(TK_COMMA)) break; + if (inner && mScanner->mToken == TK_OPEN_BRACKET) + { + mScanner->UngetToken(TK_COMMA); + break; + } if (mScanner->mToken == TK_CLOSE_BRACE) break; } @@ -1826,6 +1858,8 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) while (!mdec && path.Size()) mdec = path.Pop()->mParams; } + else if (inner) + break; else if (!ConsumeTokenIf(TK_COMMA)) break; @@ -1834,35 +1868,18 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) } } - ConsumeToken(TK_CLOSE_BRACE); + if (!inner) + { + ConsumeTokenIf(TK_COMMA); + ConsumeToken(TK_CLOSE_BRACE); + } if (last) last->mNext = nullptr; else dec->mParams = nullptr; } - else if (mScanner->mToken == TK_STRING && dtype->mType == DT_TYPE_ARRAY && dtype->mBase->mType == DT_TYPE_INTEGER && dtype->mBase->mSize == 1) - { - int ds = dtype->mSize; - uint8* d = ParseStringLiteral(ds); - - if (!(dtype->mFlags & DTF_DEFINED)) - { - dtype->mFlags |= DTF_DEFINED; - dtype->mSize = int(ds); - } - - dec = new Declaration(mScanner->mLocation, DT_CONST_DATA); - dec->mBase = dtype; - dec->mSize = dtype->mSize; - dec->mSection = mDataSection; - - dec->mData = d; - - if (ds > dtype->mSize + 1) - mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "String constant is too large for char array"); - } - else + else { exp = ParseRExpression(); return exp; diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 121eeb6..a8b027f 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -71,7 +71,7 @@ protected: Declaration* ParseStructDeclaration(uint64 flags, DecType dt, Declaration* ptempl = nullptr); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); - Expression* ParseInitExpression(Declaration* dtype); + Expression* ParseInitExpression(Declaration* dtype, bool inner = false); Expression* ParseDeclarationExpression(Declaration* pdec); Declaration* ParsePostfixDeclaration(void); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 86422d9..dab6b86 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -478,6 +478,12 @@ bool Scanner::IsIntegerToken(void) const return mToken == TK_INTEGER || mToken == TK_INTEGERU || mToken == TK_INTEGERL || mToken == TK_INTEGERUL; } +void Scanner::UngetToken(Token token) +{ + mUngetToken = mToken; + mToken = token; +} + void Scanner::NextToken(void) { if (mReplay) diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index daea112..3b616ba 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -240,6 +240,7 @@ public: const char* TokenName(Token token) const; void NextToken(void); + void UngetToken(Token token); void BeginRecord(void); TokenSequence* CompleteRecord(void); @@ -266,6 +267,7 @@ public: uint8 * mTokenEmbed; int mTokenEmbedSize; + Token mUndoToken; Token mToken; double mTokenNumber; int64 mTokenInteger;