Commit fd8e1010 by John Kessenich

Simply compile-time error handling: mostly removed the need to test an error…

Simply compile-time error handling: mostly removed the need to test an error occurred and the need to call recover(). git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21959 e7fa87d3-cd2b-0410-9028-fcbf551c1848
parent fbe01520
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, EProfile p, EShLanguage L, TInfoSink& is, TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, EProfile p, EShLanguage L, TInfoSink& is,
bool fc, EShMessages m) : bool fc, EShMessages m) :
intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0), intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0), numErrors(0), lexAfterType(false), loopNestingLevel(0),
inTypeParen(false), inTypeParen(false),
version(v), profile(p), forwardCompatible(fc), messages(m), version(v), profile(p), forwardCompatible(fc), messages(m),
contextPragma(true, false) contextPragma(true, false)
...@@ -97,6 +97,8 @@ const char* TParseContext::getPreamble() ...@@ -97,6 +97,8 @@ const char* TParseContext::getPreamble()
// Look at a '.' field selector string and change it into offsets // Look at a '.' field selector string and change it into offsets
// for a vector. // for a vector.
// //
// Returns true if there is no error.
//
bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line) bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
{ {
fields.num = (int) compString.size(); fields.num = (int) compString.size();
...@@ -192,15 +194,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV ...@@ -192,15 +194,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// Track whether errors have occurred. // Used to output syntax, parsing, and semantic errors.
//
void TParseContext::recover()
{
recoveredFromError = true;
}
//
// Used by flex/bison to output all syntax and parsing errors.
// //
void C_DECL TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken, void C_DECL TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken,
const char *szExtraInfoFormat, ...) const char *szExtraInfoFormat, ...)
...@@ -242,10 +236,8 @@ TIntermTyped* TParseContext::handleVariable(int line, TSymbol* symbol, TString* ...@@ -242,10 +236,8 @@ TIntermTyped* TParseContext::handleVariable(int line, TSymbol* symbol, TString*
// The symbol table search was done in the lexical phase, but // The symbol table search was done in the lexical phase, but
// if this is a new symbol, it wouldn't have found it. // if this is a new symbol, it wouldn't have found it.
const TVariable* variable = symbol ? symbol->getAsVariable() : 0; const TVariable* variable = symbol ? symbol->getAsVariable() : 0;
if (symbol && ! variable) { if (symbol && ! variable)
error(line, "variable name expected", string->c_str(), ""); error(line, "variable name expected", string->c_str(), "");
recover();
}
if (! variable) if (! variable)
variable = new TVariable(string, TType(EbtVoid)); variable = new TVariable(string, TType(EbtVoid));
...@@ -299,7 +291,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin ...@@ -299,7 +291,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin
// it was not found as a variable in the symbol table. If so, give the error // it was not found as a variable in the symbol table. If so, give the error
// message and insert a dummy variable in the symbol table to prevent future errors. // message and insert a dummy variable in the symbol table to prevent future errors.
// //
void TParseContext::variableErrorCheck(TIntermTyped*& nodePtr) void TParseContext::variableCheck(TIntermTyped*& nodePtr)
{ {
TIntermSymbol* symbol = nodePtr->getAsSymbolNode(); TIntermSymbol* symbol = nodePtr->getAsSymbolNode();
if (! symbol) if (! symbol)
...@@ -307,7 +299,6 @@ void TParseContext::variableErrorCheck(TIntermTyped*& nodePtr) ...@@ -307,7 +299,6 @@ void TParseContext::variableErrorCheck(TIntermTyped*& nodePtr)
if (symbol->getType().getBasicType() == EbtVoid) { if (symbol->getType().getBasicType() == EbtVoid) {
error(symbol->getLine(), "undeclared identifier", symbol->getSymbol().c_str(), ""); error(symbol->getLine(), "undeclared identifier", symbol->getSymbol().c_str(), "");
recover();
// Add to symbol table to prevent future error messages on the same name // Add to symbol table to prevent future error messages on the same name
...@@ -437,48 +428,32 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod ...@@ -437,48 +428,32 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
// Both test, and if necessary spit out an error, to see if the node is really // Both test, and if necessary spit out an error, to see if the node is really
// a constant. // a constant.
// //
// Returns true if the was an error. void TParseContext::constCheck(TIntermTyped* node)
//
bool TParseContext::constErrorCheck(TIntermTyped* node)
{ {
if (node->getQualifier().storage == EvqConst) if (node->getQualifier().storage != EvqConst)
return false; error(node->getLine(), "constant expression required", "", "");
error(node->getLine(), "constant expression required", "", "");
return true;
} }
// //
// Both test, and if necessary spit out an error, to see if the node is really // Both test, and if necessary spit out an error, to see if the node is really
// an integer. // an integer.
// //
// Returns true if the was an error. void TParseContext::integerCheck(TIntermTyped* node, const char* token)
//
bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
{ {
if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar() && ! node->isArray()) if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar() && ! node->isArray())
return false; return;
error(node->getLine(), "scalar integer expression required", token, ""); error(node->getLine(), "scalar integer expression required", token, "");
return true;
} }
// //
// Both test, and if necessary spit out an error, to see if we are currently // Both test, and if necessary spit out an error, to see if we are currently
// globally scoped. // globally scoped.
// //
// Returns true if the was an error. void TParseContext::globalCheck(int line, bool global, const char* token)
//
bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
{ {
if (global) if (! global)
return false; error(line, "only allowed at global scope", token, "");
error(line, "only allowed at global scope", token, "");
return true;
} }
// //
...@@ -486,8 +461,6 @@ bool TParseContext::globalErrorCheck(int line, bool global, const char* token) ...@@ -486,8 +461,6 @@ bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
// of scope. Except, if the symbol table is at the built-in push-level, // of scope. Except, if the symbol table is at the built-in push-level,
// which is when we are parsing built-ins. // which is when we are parsing built-ins.
// //
// Returns true if there was an error.
//
bool TParseContext::reservedErrorCheck(int line, const TString& identifier) bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
{ {
if (!symbolTable.atBuiltInLevel()) { if (!symbolTable.atBuiltInLevel()) {
...@@ -513,7 +486,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier) ...@@ -513,7 +486,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
// //
// Returns true if there was an error in construction. // Returns true if there was an error in construction.
// //
bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type) bool TParseContext::constructorError(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
{ {
*type = function.getReturnType(); *type = function.getReturnType();
...@@ -640,32 +613,18 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP ...@@ -640,32 +613,18 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP
return false; return false;
} }
// This function checks to see if the node (for the expression) contains a scalar boolean expression or not // Checks to see if the node (for the expression) contains a scalar boolean expression or not
// void TParseContext::boolCheck(int line, const TIntermTyped* type)
// returns true in case of an error
//
bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
{ {
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
error(line, "boolean expression expected", "", ""); error(line, "boolean expression expected", "", "");
return true;
}
return false;
} }
// This function checks to see if the node (for the expression) contains a scalar boolean expression or not // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
// void TParseContext::boolCheck(int line, const TPublicType& pType)
// returns true in case of an error
//
bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
{ {
if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1)) { if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1))
error(line, "boolean expression expected", "", ""); error(line, "boolean expression expected", "", "");
return true;
}
return false;
} }
bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason) bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
...@@ -687,10 +646,10 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const ...@@ -687,10 +646,10 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
return false; return false;
} }
bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualifier, const TPublicType& publicType) void TParseContext::globalQualifierFix(int line, TQualifier& qualifier, const TPublicType& publicType)
{ {
if (! symbolTable.atGlobalLevel()) if (! symbolTable.atGlobalLevel())
return false; return;
// First, move from parameter qualifiers to shader in/out qualifiers // First, move from parameter qualifiers to shader in/out qualifiers
...@@ -712,7 +671,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif ...@@ -712,7 +671,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
qualifier.storage = EvqVaryingIn; qualifier.storage = EvqVaryingIn;
error(line, "cannot use 'inout' at global scope", "", ""); error(line, "cannot use 'inout' at global scope", "", "");
return true; return;
default: default:
break; break;
} }
...@@ -720,22 +679,24 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif ...@@ -720,22 +679,24 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
// Do non-in/out error checks // Do non-in/out error checks
if (qualifier.storage != EvqUniform && samplerErrorCheck(line, publicType, "samplers and images must be uniform")) if (qualifier.storage != EvqUniform && samplerErrorCheck(line, publicType, "samplers and images must be uniform"))
return true; return;
if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut) if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
return false; return;
// now, knowing it is a shader in/out, do all the in/out semantic checks // now, knowing it is a shader in/out, do all the in/out semantic checks
if (publicType.basicType == EbtBool) { if (publicType.basicType == EbtBool) {
error(line, "cannot be bool", getStorageQualifierString(qualifier.storage), ""); error(line, "cannot be bool", getStorageQualifierString(qualifier.storage), "");
return true;
return;
} }
if (language == EShLangVertex && qualifier.storage == EvqVaryingIn) { if (language == EShLangVertex && qualifier.storage == EvqVaryingIn) {
if (publicType.basicType == EbtStruct) { if (publicType.basicType == EbtStruct) {
error(line, "cannot be a structure or array", getStorageQualifierString(qualifier.storage), ""); error(line, "cannot be a structure or array", getStorageQualifierString(qualifier.storage), "");
return true;
return;
} }
if (publicType.arraySizes) { if (publicType.arraySizes) {
requireProfile(line, (EProfileMask)~EEsProfileMask, "vertex input arrays"); requireProfile(line, (EProfileMask)~EEsProfileMask, "vertex input arrays");
...@@ -747,7 +708,8 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif ...@@ -747,7 +708,8 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
profileRequires(line, EEsProfile, 300, 0, "fragment shader output"); profileRequires(line, EEsProfile, 300, 0, "fragment shader output");
if (publicType.basicType == EbtStruct) { if (publicType.basicType == EbtStruct) {
error(line, "cannot be a structure", getStorageQualifierString(qualifier.storage), ""); error(line, "cannot be a structure", getStorageQualifierString(qualifier.storage), "");
return true;
return;
} }
} }
...@@ -757,7 +719,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif ...@@ -757,7 +719,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
language != EShLangFragment && qualifier.storage == EvqVaryingOut && ! qualifier.flat) { language != EShLangFragment && qualifier.storage == EvqVaryingOut && ! qualifier.flat) {
error(line, "must be qualified as 'flat'", getStorageQualifierString(qualifier.storage), TType::getBasicString(publicType.basicType)); error(line, "must be qualified as 'flat'", getStorageQualifierString(qualifier.storage), TType::getBasicString(publicType.basicType));
return true; return;
} }
} }
...@@ -765,10 +727,8 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif ...@@ -765,10 +727,8 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
(qualifier.isAuxillary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)) { (qualifier.isAuxillary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)) {
error(line, "vertex input cannot be further qualified", "", ""); error(line, "vertex input cannot be further qualified", "", "");
return true; return;
} }
return false;
} }
// //
...@@ -776,9 +736,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif ...@@ -776,9 +736,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
// If there is duplication, issue error messages, unless 'force' // If there is duplication, issue error messages, unless 'force'
// is specified, which means to just override default settings. // is specified, which means to just override default settings.
// //
// Return true if there was an error. void TParseContext::mergeQualifiers(int line, TPublicType& dst, const TPublicType& src, bool force)
//
bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& dst, const TPublicType& src, bool force)
{ {
bool bad = false; bool bad = false;
...@@ -825,8 +783,6 @@ bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& dst, const ...@@ -825,8 +783,6 @@ bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& dst, const
if (bad) if (bad)
error(line, "replicated qualifiers", "", ""); error(line, "replicated qualifiers", "", "");
return bad;
} }
void TParseContext::setDefaultPrecision(int line, TPublicType& publicType, TPrecisionQualifier qualifier) void TParseContext::setDefaultPrecision(int line, TPublicType& publicType, TPrecisionQualifier qualifier)
...@@ -844,18 +800,12 @@ void TParseContext::setDefaultPrecision(int line, TPublicType& publicType, TPrec ...@@ -844,18 +800,12 @@ void TParseContext::setDefaultPrecision(int line, TPublicType& publicType, TPrec
} }
error(line, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), ""); error(line, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), "");
recover();
} }
bool TParseContext::parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type) void TParseContext::parameterSamplerCheck(int line, TStorageQualifier qualifier, const TType& type)
{ {
if ((qualifier == EvqOut || qualifier == EvqInOut) && if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct && type.getBasicType() == EbtSampler)
type.getBasicType() != EbtStruct && type.getBasicType() == EbtSampler) {
error(line, "samplers cannot be output parameters", type.getCompleteTypeString().c_str(), ""); error(line, "samplers cannot be output parameters", type.getCompleteTypeString().c_str(), "");
return true;
}
return false;
} }
bool TParseContext::containsSampler(const TType& type) bool TParseContext::containsSampler(const TType& type)
...@@ -904,15 +854,14 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel() ...@@ -904,15 +854,14 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel()
// //
// Do size checking for an array type's size. // Do size checking for an array type's size.
// //
// Returns true if there was an error. void TParseContext::arraySizeCheck(int line, TIntermTyped* expr, int& size)
//
bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
{ {
TIntermConstantUnion* constant = expr->getAsConstantUnion(); TIntermConstantUnion* constant = expr->getAsConstantUnion();
if (constant == 0 || (constant->getBasicType() != EbtInt && constant->getBasicType() != EbtUint)) { if (constant == 0 || (constant->getBasicType() != EbtInt && constant->getBasicType() != EbtUint)) {
error(line, "array size must be a constant integer expression", "", ""); error(line, "array size must be a constant integer expression", "", "");
size = 1; size = 1;
return true;
return;
} }
size = constant->getUnionArrayPointer()->getIConst(); size = constant->getUnionArrayPointer()->getIConst();
...@@ -920,10 +869,9 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) ...@@ -920,10 +869,9 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
if (size <= 0) { if (size <= 0) {
error(line, "array size must be a positive integer", "", ""); error(line, "array size must be a positive integer", "", "");
size = 1; size = 1;
return true;
}
return false; return;
}
} }
// //
...@@ -931,7 +879,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) ...@@ -931,7 +879,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
// //
// Returns true if there is an error. // Returns true if there is an error.
// //
bool TParseContext::arrayQualifierErrorCheck(int line, const TPublicType& type) bool TParseContext::arrayQualifierError(int line, const TPublicType& type)
{ {
if (type.qualifier.storage == EvqConst) if (type.qualifier.storage == EvqConst)
profileRequires(line, ENoProfile, 120, "GL_3DL_array_objects", "const array"); profileRequires(line, ENoProfile, 120, "GL_3DL_array_objects", "const array");
...@@ -947,18 +895,12 @@ bool TParseContext::arrayQualifierErrorCheck(int line, const TPublicType& type) ...@@ -947,18 +895,12 @@ bool TParseContext::arrayQualifierErrorCheck(int line, const TPublicType& type)
// //
// Require array to have size // Require array to have size
// //
// Returns true if there is an error. void TParseContext::arraySizeRequiredCheck(int line, int& size)
//
bool TParseContext::arraySizeRequiredErrorCheck(int line, int& size)
{ {
if (size == 0) { if (size == 0) {
error(line, "array size required", "", ""); error(line, "array size required", "", "");
size = 1; size = 1;
return true;
} }
return false;
} }
// //
...@@ -967,9 +909,7 @@ bool TParseContext::arraySizeRequiredErrorCheck(int line, int& size) ...@@ -967,9 +909,7 @@ bool TParseContext::arraySizeRequiredErrorCheck(int line, int& size)
// //
// size == 0 means no specified size. // size == 0 means no specified size.
// //
// Returns true if there was an error. void TParseContext::arrayCheck(int line, TString& identifier, const TPublicType& type, TVariable*& variable)
//
bool TParseContext::arrayErrorCheck(int line, TString& identifier, const TPublicType& type, TVariable*& variable)
{ {
// //
// Don't check for reserved word use until after we know it's not in the symbol table, // Don't check for reserved word use until after we know it's not in the symbol table,
...@@ -980,42 +920,43 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, const TPublic ...@@ -980,42 +920,43 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, const TPublic
TSymbol* symbol = symbolTable.find(identifier, 0, &sameScope); TSymbol* symbol = symbolTable.find(identifier, 0, &sameScope);
if (symbol == 0 || !sameScope) { if (symbol == 0 || !sameScope) {
if (reservedErrorCheck(line, identifier)) if (reservedErrorCheck(line, identifier))
return true; return;
variable = new TVariable(&identifier, TType(type)); variable = new TVariable(&identifier, TType(type));
if (! symbolTable.insert(*variable)) { if (! symbolTable.insert(*variable)) {
delete variable; delete variable;
error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), ""); error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
return true;
return;
} }
} else { } else {
variable = symbol->getAsVariable(); variable = symbol->getAsVariable();
if (! variable) { if (! variable) {
error(line, "array variable name expected", identifier.c_str(), ""); error(line, "array variable name expected", identifier.c_str(), "");
return true; return;
} }
if (! variable->getType().isArray()) { if (! variable->getType().isArray()) {
error(line, "redeclaring non-array as array", identifier.c_str(), ""); error(line, "redeclaring non-array as array", identifier.c_str(), "");
return true; return;
} }
if (variable->getType().getArraySize() > 0) { if (variable->getType().getArraySize() > 0) {
error(line, "redeclaration of array with size", identifier.c_str(), ""); error(line, "redeclaration of array with size", identifier.c_str(), "");
return true; return;
} }
if (! variable->getType().sameElementType(TType(type))) { if (! variable->getType().sameElementType(TType(type))) {
error(line, "redeclaration of array with a different type", identifier.c_str(), ""); error(line, "redeclaration of array with a different type", identifier.c_str(), "");
return true; return;
} }
TType* t = variable->getArrayInformationType(); TType* t = variable->getArrayInformationType();
while (t != 0) { while (t != 0) {
if (t->getMaxArraySize() > type.arraySizes->front()) { if (t->getMaxArraySize() > type.arraySizes->front()) {
error(line, "higher index value already used for the array", identifier.c_str(), ""); error(line, "higher index value already used for the array", identifier.c_str(), "");
return true; return;
} }
t->setArraySizes(type.arraySizes); t->setArraySizes(type.arraySizes);
t = t->getArrayInformationType(); t = t->getArrayInformationType();
...@@ -1024,10 +965,7 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, const TPublic ...@@ -1024,10 +965,7 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, const TPublic
variable->getType().setArraySizes(type.arraySizes); variable->getType().setArraySizes(type.arraySizes);
} }
if (voidErrorCheck(line, identifier, type)) voidErrorCheck(line, identifier, type);
return true;
return false;
} }
bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line) bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
...@@ -1084,9 +1022,7 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, ...@@ -1084,9 +1022,7 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
// //
// Enforce non-initializer type/qualifier rules. // Enforce non-initializer type/qualifier rules.
// //
// Returns true if there was an error. void TParseContext::nonInitConstCheck(int line, TString& identifier, TPublicType& type)
//
bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type)
{ {
// //
// Make the qualifier make sense. // Make the qualifier make sense.
...@@ -1094,56 +1030,45 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli ...@@ -1094,56 +1030,45 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
if (type.qualifier.storage == EvqConst) { if (type.qualifier.storage == EvqConst) {
type.qualifier.storage = EvqTemporary; type.qualifier.storage = EvqTemporary;
error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), ""); error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
return true;
} }
return false;
} }
// //
// Do semantic checking for a variable declaration that has no initializer, // Do semantic checking for a variable declaration that has no initializer,
// and update the symbol table. // and update the symbol table.
// //
// Returns true if there was an error. void TParseContext::nonInitCheck(int line, TString& identifier, TPublicType& type)
//
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
{ {
if (reservedErrorCheck(line, identifier)) reservedErrorCheck(line, identifier);
recover();
TVariable* variable = new TVariable(&identifier, TType(type)); TVariable* variable = new TVariable(&identifier, TType(type));
if (! symbolTable.insert(*variable)) { if (! symbolTable.insert(*variable)) {
error(line, "redefinition", variable->getName().c_str(), ""); error(line, "redefinition", variable->getName().c_str(), "");
delete variable; delete variable;
return true; } else
} voidErrorCheck(line, identifier, type);
if (voidErrorCheck(line, identifier, type))
return true;
return false;
} }
bool TParseContext::paramErrorCheck(int line, TStorageQualifier qualifier, TType* type) void TParseContext::paramCheck(int line, TStorageQualifier qualifier, TType* type)
{ {
switch (qualifier) { switch (qualifier) {
case EvqConst: case EvqConst:
case EvqConstReadOnly: case EvqConstReadOnly:
type->getQualifier().storage = EvqConstReadOnly; type->getQualifier().storage = EvqConstReadOnly;
return false; break;
case EvqIn: case EvqIn:
case EvqOut: case EvqOut:
case EvqInOut: case EvqInOut:
type->getQualifier().storage = qualifier; type->getQualifier().storage = qualifier;
return false; break;
case EvqTemporary: case EvqTemporary:
type->getQualifier().storage = EvqIn; type->getQualifier().storage = EvqIn;
return false; break;
default: default:
type->getQualifier().storage = EvqIn; type->getQualifier().storage = EvqIn;
error(line, "qualifier not allowed on function parameter", getStorageQualifierString(qualifier), ""); error(line, "qualifier not allowed on function parameter", getStorageQualifierString(qualifier), "");
return true; break;
} }
} }
...@@ -1242,8 +1167,8 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu ...@@ -1242,8 +1167,8 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu
// Initializers show up in several places in the grammar. Have one set of // Initializers show up in several places in the grammar. Have one set of
// code to handle them here. // code to handle them here.
// //
bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, bool TParseContext::executeInitializerError(TSourceLoc line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
{ {
TType type(pType); TType type(pType);
...@@ -1482,7 +1407,6 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T ...@@ -1482,7 +1407,6 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
default: default:
error(line, "unsupported construction", "", ""); error(line, "unsupported construction", "", "");
recover();
return 0; return 0;
} }
...@@ -1515,8 +1439,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ ...@@ -1515,8 +1439,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
if (! converted || converted->getType() != type) { if (! converted || converted->getType() != type) {
error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
node->getAsTyped()->getType().getCompleteTypeString().c_str(), type.getCompleteTypeString().c_str()); node->getAsTyped()->getType().getCompleteTypeString().c_str(), type.getCompleteTypeString().c_str());
recover();
return 0; return 0;
} }
...@@ -1530,19 +1453,14 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b ...@@ -1530,19 +1453,14 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
{ {
// First, error checks // First, error checks
if (reservedErrorCheck(line, blockName)) { if (reservedErrorCheck(line, blockName))
recover();
return; return;
}
if (instanceName && reservedErrorCheck(line, *instanceName)) {
recover();
if (instanceName && reservedErrorCheck(line, *instanceName))
return; return;
}
if (publicType.basicType != EbtVoid) { if (publicType.basicType != EbtVoid) {
error(line, "interface blocks cannot be declared with a type", blockName.c_str(), ""); error(line, "interface blocks cannot be declared with a type", blockName.c_str(), "");
recover();
return; return;
} }
...@@ -1551,7 +1469,6 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b ...@@ -1551,7 +1469,6 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
profileRequires(line, EEsProfile, 300, 0, "uniform block"); profileRequires(line, EEsProfile, 300, 0, "uniform block");
} else { } else {
error(line, "only uniform interface blocks are supported", blockName.c_str(), ""); error(line, "only uniform interface blocks are supported", blockName.c_str(), "");
recover();
return; return;
} }
...@@ -1559,23 +1476,14 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b ...@@ -1559,23 +1476,14 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
// check for qualifiers and types that don't belong within a block // check for qualifiers and types that don't belong within a block
for (unsigned int member = 0; member < typeList.size(); ++member) { for (unsigned int member = 0; member < typeList.size(); ++member) {
TQualifier memberQualifier = typeList[member].type->getQualifier(); TQualifier memberQualifier = typeList[member].type->getQualifier();
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != publicType.qualifier.storage)
memberQualifier.storage != publicType.qualifier.storage) {
error(line, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), ""); error(line, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), "");
recover(); if (publicType.qualifier.storage == EvqUniform && memberQualifier.isInterpolation() || memberQualifier.isAuxillary())
} error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
if (publicType.qualifier.storage == EvqUniform) {
if (memberQualifier.isInterpolation() || memberQualifier.isAuxillary()) {
error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
recover();
}
}
TBasicType basicType = typeList[member].type->getBasicType(); TBasicType basicType = typeList[member].type->getBasicType();
if (basicType == EbtSampler) { if (basicType == EbtSampler)
error(line, "member of block cannot be a sampler type", typeList[member].type->getFieldName().c_str(), ""); error(line, "member of block cannot be a sampler type", typeList[member].type->getFieldName().c_str(), "");
recover();
}
} }
// Make default block qualification, and adjust the member qualifications // Make default block qualification, and adjust the member qualifications
...@@ -1597,7 +1505,6 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b ...@@ -1597,7 +1505,6 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
TVariable* userTypeDef = new TVariable(&blockName, blockType, true); TVariable* userTypeDef = new TVariable(&blockName, blockType, true);
if (! symbolTable.insert(*userTypeDef)) { if (! symbolTable.insert(*userTypeDef)) {
error(line, "redefinition", blockName.c_str(), "block name"); error(line, "redefinition", blockName.c_str(), "block name");
recover();
return; return;
} }
...@@ -1614,7 +1521,6 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b ...@@ -1614,7 +1521,6 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
error(line, "nameless block contains a member that already has a name at global scope", blockName.c_str(), ""); error(line, "nameless block contains a member that already has a name at global scope", blockName.c_str(), "");
else else
error(line, "block instance name redefinition", variable->getName().c_str(), ""); error(line, "block instance name redefinition", variable->getName().c_str(), "");
recover();
return; return;
} }
...@@ -1631,10 +1537,8 @@ void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TInter ...@@ -1631,10 +1537,8 @@ void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TInter
TIntermSequence* switchSequence = switchSequenceStack.back(); TIntermSequence* switchSequence = switchSequenceStack.back();
if (statements) { if (statements) {
if (switchSequence->size() == 0) { if (switchSequence->size() == 0)
error(statements->getLine(), "cannot have statements before first case/default label", "switch", ""); error(statements->getLine(), "cannot have statements before first case/default label", "switch", "");
recover();
}
statements->setOperator(EOpSequence); statements->setOperator(EOpSequence);
switchSequence->push_back(statements); switchSequence->push_back(statements);
} }
...@@ -1657,10 +1561,8 @@ TIntermNode* TParseContext::addSwitch(int line, TIntermTyped* expression, TInter ...@@ -1657,10 +1561,8 @@ TIntermNode* TParseContext::addSwitch(int line, TIntermTyped* expression, TInter
if (expression == 0 || if (expression == 0 ||
expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint || expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint ||
expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector()) { expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector())
error(line, "condition must be a scalar integer expression", "switch", ""); error(line, "condition must be a scalar integer expression", "switch", "");
recover();
}
// If there is nothing to do, drop the switch but still execute the expression // If there is nothing to do, drop the switch but still execute the expression
TIntermSequence* switchSequence = switchSequenceStack.back(); TIntermSequence* switchSequence = switchSequenceStack.back();
...@@ -1669,7 +1571,6 @@ TIntermNode* TParseContext::addSwitch(int line, TIntermTyped* expression, TInter ...@@ -1669,7 +1571,6 @@ TIntermNode* TParseContext::addSwitch(int line, TIntermTyped* expression, TInter
if (lastStatements == 0) { if (lastStatements == 0) {
error(line, "last case/default label must be followed by statements", "switch", ""); error(line, "last case/default label must be followed by statements", "switch", "");
recover();
return expression; return expression;
} }
...@@ -1708,10 +1609,8 @@ void TParseContext::updateDefaults(int line, const TPublicType& publicType, cons ...@@ -1708,10 +1609,8 @@ void TParseContext::updateDefaults(int line, const TPublicType& publicType, cons
} }
} }
if (cantHaveId && id) { if (cantHaveId && id)
error(line, "cannot set global layout qualifiers on uniform variable, use just 'uniform' or a block", id->c_str(), ""); error(line, "cannot set global layout qualifiers on uniform variable, use just 'uniform' or a block", id->c_str(), "");
recover();
}
} }
// //
...@@ -1732,13 +1631,11 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy ...@@ -1732,13 +1631,11 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
if (!unionArray) { // this error message should never be raised if (!unionArray) { // this error message should never be raised
infoSink.info.message(EPrefixInternalError, "constUnion not initialized in addConstVectorNode function", line); infoSink.info.message(EPrefixInternalError, "constUnion not initialized in addConstVectorNode function", line);
recover();
return node; return node;
} }
} else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
error(line, "Cannot offset into the vector", "Error", ""); error(line, "Cannot offset into the vector", "Error", "");
recover();
return 0; return 0;
} }
...@@ -1748,14 +1645,13 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy ...@@ -1748,14 +1645,13 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
for (int i = 0; i < fields.num; i++) { for (int i = 0; i < fields.num; i++) {
if (fields.offsets[i] >= node->getType().getObjectSize()) { if (fields.offsets[i] >= node->getType().getObjectSize()) {
error(line, "", "[", "vector index out of range '%d'", fields.offsets[i]); error(line, "", "[", "vector index out of range '%d'", fields.offsets[i]);
recover();
fields.offsets[i] = 0; fields.offsets[i] = 0;
} }
constArray[i] = unionArray[fields.offsets[i]]; constArray[i] = unionArray[fields.offsets[i]];
} }
typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
return typedNode; return typedNode;
} }
...@@ -1772,7 +1668,6 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T ...@@ -1772,7 +1668,6 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T
if (index >= node->getType().getMatrixCols()) { if (index >= node->getType().getMatrixCols()) {
error(line, "", "[", "matrix field selection out of range '%d'", index); error(line, "", "[", "matrix field selection out of range '%d'", index);
recover();
index = 0; index = 0;
} }
...@@ -1783,7 +1678,6 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T ...@@ -1783,7 +1678,6 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T
typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
} else { } else {
error(line, "Cannot offset into the matrix", "Error", ""); error(line, "Cannot offset into the matrix", "Error", "");
recover();
return 0; return 0;
} }
...@@ -1808,7 +1702,6 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS ...@@ -1808,7 +1702,6 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
if (index >= node->getType().getArraySize() || index < 0) { if (index >= node->getType().getArraySize() || index < 0) {
error(line, "", "[", "array index '%d' out of range", index); error(line, "", "[", "array index '%d' out of range", index);
recover();
index = 0; index = 0;
} }
...@@ -1819,7 +1712,6 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS ...@@ -1819,7 +1712,6 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
} else { } else {
error(line, "Cannot offset into the array", "Error", ""); error(line, "Cannot offset into the array", "Error", "");
recover();
return 0; return 0;
} }
...@@ -1855,7 +1747,6 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n ...@@ -1855,7 +1747,6 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n
typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
} else { } else {
error(line, "Cannot offset into the structure", "Error", ""); error(line, "Cannot offset into the structure", "Error", "");
recover();
return 0; return 0;
} }
......
...@@ -74,8 +74,7 @@ struct TParseContext { ...@@ -74,8 +74,7 @@ struct TParseContext {
TInfoSink& infoSink; TInfoSink& infoSink;
EShLanguage language; // vertex or fragment language EShLanguage language; // vertex or fragment language
TIntermNode* treeRoot; // root of parse tree being created TIntermNode* treeRoot; // root of parse tree being created
bool recoveredFromError; // true if a parse error has occurred, but we continue to parse int numErrors; // number of compile-time errors encountered
int numErrors;
bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
int loopNestingLevel; // 0 if outside all loops int loopNestingLevel; // 0 if outside all loops
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
...@@ -101,45 +100,44 @@ struct TParseContext { ...@@ -101,45 +100,44 @@ struct TParseContext {
void C_DECL error(TSourceLoc, const char *szReason, const char *szToken, void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
const char *szExtraInfoFormat, ...); const char *szExtraInfoFormat, ...);
bool reservedErrorCheck(int line, const TString& identifier); bool reservedErrorCheck(int line, const TString& identifier);
void recover();
TIntermTyped* handleVariable(int line, TSymbol* symbol, TString* string); TIntermTyped* handleVariable(int line, TSymbol* symbol, TString* string);
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line); bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
void assignError(int line, const char* op, TString left, TString right); void assignError(int line, const char* op, TString left, TString right);
void unaryOpError(int line, const char* op, TString operand); void unaryOpError(int line, const char* op, TString operand);
void binaryOpError(int line, const char* op, TString left, TString right); void binaryOpError(int line, const char* op, TString left, TString right);
void variableErrorCheck(TIntermTyped*& nodePtr); void variableCheck(TIntermTyped*& nodePtr);
bool lValueErrorCheck(int line, const char* op, TIntermTyped*); bool lValueErrorCheck(int line, const char* op, TIntermTyped*);
bool constErrorCheck(TIntermTyped* node); void constCheck(TIntermTyped* node);
bool integerErrorCheck(TIntermTyped* node, const char* token); void integerCheck(TIntermTyped* node, const char* token);
bool globalErrorCheck(int line, bool global, const char* token); void globalCheck(int line, bool global, const char* token);
bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*); bool constructorError(int line, TIntermNode*, TFunction&, TOperator, TType*);
bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size); void arraySizeCheck(int line, TIntermTyped* expr, int& size);
bool arrayQualifierErrorCheck(int line, const TPublicType&); bool arrayQualifierError(int line, const TPublicType&);
bool arraySizeRequiredErrorCheck(int line, int& size); void arraySizeRequiredCheck(int line, int& size);
bool arrayErrorCheck(int line, TString& identifier, const TPublicType&, TVariable*& variable); void arrayCheck(int line, TString& identifier, const TPublicType&, TVariable*& variable);
bool insertBuiltInArrayAtGlobalLevel(); bool insertBuiltInArrayAtGlobalLevel();
bool voidErrorCheck(int, const TString&, const TPublicType&); bool voidErrorCheck(int, const TString&, const TPublicType&);
bool boolErrorCheck(int, const TIntermTyped*); void boolCheck(int, const TIntermTyped*);
bool boolErrorCheck(int, const TPublicType&); void boolCheck(int, const TPublicType&);
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason); bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
bool globalQualifierFixAndErrorCheck(int line, TQualifier&, const TPublicType&); void globalQualifierFix(int line, TQualifier&, const TPublicType&);
bool structQualifierErrorCheck(int line, const TPublicType& pType); bool structQualifierErrorCheck(int line, const TPublicType& pType);
bool mergeQualifiersErrorCheck(int line, TPublicType& dst, const TPublicType& src, bool force); void mergeQualifiers(int line, TPublicType& dst, const TPublicType& src, bool force);
void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier); void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier);
bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type); void parameterSamplerCheck(int line, TStorageQualifier qualifier, const TType& type);
bool containsSampler(const TType& type); bool containsSampler(const TType& type);
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type); void nonInitConstCheck(int line, TString& identifier, TPublicType& type);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type); void nonInitCheck(int line, TString& identifier, TPublicType& type);
bool paramErrorCheck(int line, TStorageQualifier qualifier, TType* type); void paramCheck(int line, TStorageQualifier qualifier, TType* type);
void setLayoutQualifier(int line, TPublicType&, TString&); void setLayoutQualifier(int line, TPublicType&, TString&);
void setLayoutQualifier(int line, TPublicType&, TString&, int); void setLayoutQualifier(int line, TPublicType&, TString&, int);
void mergeLayoutQualifiers(int line, TQualifier& dest, const TQualifier& src); void mergeLayoutQualifiers(int line, TQualifier& dest, const TQualifier& src);
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0); const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, bool executeInitializerError(TSourceLoc line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
TIntermTyped* addConstructor(TIntermNode*, const TType&, TOperator, TFunction*, TSourceLoc); TIntermTyped* addConstructor(TIntermNode*, const TType&, TOperator, TFunction*, TSourceLoc);
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc); TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
...@@ -153,6 +151,7 @@ struct TParseContext { ...@@ -153,6 +151,7 @@ struct TParseContext {
TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc); TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc); bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
void requireProfile(int line, EProfileMask profileMask, const char *featureDesc); void requireProfile(int line, EProfileMask profileMask, const char *featureDesc);
void requireStage(int line, EShLanguageMask languageMask, const char *featureDesc); void requireStage(int line, EShLanguageMask languageMask, const char *featureDesc);
void profileRequires(int line, EProfile callingProfile, int minVersion, int numExtensions, const char* extensions[], const char *featureDesc); void profileRequires(int line, EProfile callingProfile, int minVersion, int numExtensions, const char* extensions[], const char *featureDesc);
......
...@@ -66,10 +66,8 @@ const char* ProfileName[EProfileCount] = { ...@@ -66,10 +66,8 @@ const char* ProfileName[EProfileCount] = {
// //
void TParseContext::requireProfile(int line, EProfileMask profileMask, const char *featureDesc) void TParseContext::requireProfile(int line, EProfileMask profileMask, const char *featureDesc)
{ {
if (((1 << profile) & profileMask) == 0) { if (((1 << profile) & profileMask) == 0)
error(line, "not supported with this profile:", featureDesc, ProfileName[profile]); error(line, "not supported with this profile:", featureDesc, ProfileName[profile]);
recover();
}
} }
// //
...@@ -79,10 +77,8 @@ void TParseContext::requireProfile(int line, EProfileMask profileMask, const cha ...@@ -79,10 +77,8 @@ void TParseContext::requireProfile(int line, EProfileMask profileMask, const cha
// //
void TParseContext::requireStage(int line, EShLanguageMask languageMask, const char *featureDesc) void TParseContext::requireStage(int line, EShLanguageMask languageMask, const char *featureDesc)
{ {
if (((1 << language) & languageMask) == 0) { if (((1 << language) & languageMask) == 0)
error(line, "not supported in this stage:", featureDesc, StageName[language]); error(line, "not supported in this stage:", featureDesc, StageName[language]);
recover();
}
} }
// //
...@@ -112,10 +108,8 @@ void TParseContext::profileRequires(int line, EProfile callingProfile, int minVe ...@@ -112,10 +108,8 @@ void TParseContext::profileRequires(int line, EProfile callingProfile, int minVe
} }
} }
if (! okay) { if (! okay)
error(line, "not supported for this version or the enabled extensions", featureDesc, ""); error(line, "not supported for this version or the enabled extensions", featureDesc, "");
recover();
}
} }
} }
...@@ -133,13 +127,11 @@ void TParseContext::checkDeprecated(int line, EProfile callingProfile, int depVe ...@@ -133,13 +127,11 @@ void TParseContext::checkDeprecated(int line, EProfile callingProfile, int depVe
{ {
if (profile == callingProfile) { if (profile == callingProfile) {
if (version >= depVersion) { if (version >= depVersion) {
if (forwardCompatible) { if (forwardCompatible)
error(line, "deprecated, may be removed in future release", featureDesc, ""); error(line, "deprecated, may be removed in future release", featureDesc, "");
recover(); else if (! (messages & EShMsgSuppressWarnings))
} else if (! (messages & EShMsgSuppressWarnings)) {
infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " + infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " +
String(depVersion) + "; may be removed in future release").c_str(), line); String(depVersion) + "; may be removed in future release").c_str(), line);
}
} }
} }
} }
...@@ -156,7 +148,6 @@ void TParseContext::requireNotRemoved(int line, EProfile callingProfile, int rem ...@@ -156,7 +148,6 @@ void TParseContext::requireNotRemoved(int line, EProfile callingProfile, int rem
char buf[maxSize]; char buf[maxSize];
snprintf(buf, maxSize, "%s profile; removed in version %d", ProfileName[profile], removedVersion); snprintf(buf, maxSize, "%s profile; removed in version %d", ProfileName[profile], removedVersion);
error(line, "no longer supported in", featureDesc, buf); error(line, "no longer supported in", featureDesc, buf);
recover();
} }
} }
} }
......
...@@ -536,12 +536,12 @@ int yy_input(char* buf, int max_size); ...@@ -536,12 +536,12 @@ int yy_input(char* buf, int max_size);
0[xX]{H}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return INTCONSTANT; } 0[xX]{H}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return INTCONSTANT; }
0{O}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return INTCONSTANT; } 0{O}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return INTCONSTANT; }
0{D}+ { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;} 0{D}+ { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); return 0;}
{D}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return INTCONSTANT; } {D}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return INTCONSTANT; }
0[xX]{H}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return UINTCONSTANT; } 0[xX]{H}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return UINTCONSTANT; }
0{O}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return UINTCONSTANT; } 0{O}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return UINTCONSTANT; }
0{D}+{U} { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;} 0{D}+{U} { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); return 0;}
{D}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return UINTCONSTANT; } {D}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return UINTCONSTANT; }
{D}+{F} { pyylval->lex.line = yylineno; pyylval->lex.d = atof(yytext); return FLOATCONSTANT; } {D}+{F} { pyylval->lex.line = yylineno; pyylval->lex.d = atof(yytext); return FLOATCONSTANT; }
...@@ -657,7 +657,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon ...@@ -657,7 +657,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
if (! argv[i]) { if (! argv[i]) {
parseContextLocal.error(0, "Null shader source string", "", ""); parseContextLocal.error(0, "Null shader source string", "", "");
parseContextLocal.recover();
return 1; return 1;
} }
} }
...@@ -709,7 +709,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon ...@@ -709,7 +709,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
ret = yyparse((void*)(&parseContextLocal)); ret = yyparse((void*)(&parseContextLocal));
#endif #endif
delete writeablePreamble; delete writeablePreamble;
if (cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0) if (cpp->CompileError == 1 || parseContextLocal.numErrors > 0)
return 1; return 1;
else else
return 0; return 0;
...@@ -725,20 +725,15 @@ void yyerror(const char *s) ...@@ -725,20 +725,15 @@ void yyerror(const char *s)
TParseContext& pc = *((TParseContext *)cpp->pC); TParseContext& pc = *((TParseContext *)cpp->pC);
if (pc.AfterEOF) { if (pc.AfterEOF) {
if (cpp->tokensBeforeEOF == 1) { if (cpp->tokensBeforeEOF == 1)
GlobalParseContext->error(yylineno, "", "pre-mature EOF", s, ""); GlobalParseContext->error(yylineno, "", "pre-mature EOF", s, "");
GlobalParseContext->recover(); } else
}
} else {
GlobalParseContext->error(yylineno, "", yytext, s, ""); GlobalParseContext->error(yylineno, "", yytext, s, "");
GlobalParseContext->recover();
}
} }
void PaReservedWord() void PaReservedWord()
{ {
GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", ""); GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", "");
GlobalParseContext->recover();
} }
int PaIdentOrType(const char* yytext, TParseContext& parseContextLocal, YYSTYPE* pyylval) int PaIdentOrType(const char* yytext, TParseContext& parseContextLocal, YYSTYPE* pyylval)
...@@ -907,6 +902,7 @@ int Pa2ndGenerationImage(TParseContext& pc, int line, const char* text, YYSTYPE* ...@@ -907,6 +902,7 @@ int Pa2ndGenerationImage(TParseContext& pc, int line, const char* text, YYSTYPE*
return PaIdentOrType(text, pc, pyylval); return PaIdentOrType(text, pc, pyylval);
} }
// TODO: CPP: is this dead code? Combine with other comment parsers.
int PaParseComment(int& lineno, TParseContext& parseContextLocal) int PaParseComment(int& lineno, TParseContext& parseContextLocal)
{ {
int transitionFlag = 0; int transitionFlag = 0;
...@@ -926,14 +922,14 @@ int PaParseComment(int& lineno, TParseContext& parseContextLocal) ...@@ -926,14 +922,14 @@ int PaParseComment(int& lineno, TParseContext& parseContextLocal)
} }
break; break;
case EOF : case EOF :
/* Raise error message here */
parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", ""); parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", "");
GlobalParseContext->recover();
return YY_NULL; return YY_NULL;
default : /* Any other character will be a part of the comment */ default : /* Any other character will be a part of the comment */
transitionFlag = 0; transitionFlag = 0;
} }
} }
return 1; return 1;
} }
...@@ -959,7 +955,6 @@ void ShPpErrorToInfoLog(const char *msg) ...@@ -959,7 +955,6 @@ void ShPpErrorToInfoLog(const char *msg)
TParseContext& pc = *((TParseContext *)cpp->pC); TParseContext& pc = *((TParseContext *)cpp->pC);
pc.error(yylineno, "", "Preprocessor", msg, ""); pc.error(yylineno, "", "Preprocessor", msg, "");
GlobalParseContext->recover();
} }
// return 1 if error // return 1 if error
......
...@@ -263,13 +263,12 @@ postfix_expression ...@@ -263,13 +263,12 @@ postfix_expression
$$ = $1; $$ = $1;
} }
| postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
parseContext.variableErrorCheck($1); parseContext.variableCheck($1);
if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) { if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) {
if ($1->getAsSymbolNode()) if ($1->getAsSymbolNode())
parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), ""); parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), "");
else else
parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", ""); parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
parseContext.recover();
} }
if ($1->getType().getQualifier().storage == EvqConst && $3->getQualifier().storage == EvqConst) { if ($1->getType().getQualifier().storage == EvqConst && $3->getQualifier().storage == EvqConst) {
if ($1->isArray()) { // constant folding for arrays if ($1->isArray()) { // constant folding for arrays
...@@ -286,32 +285,24 @@ postfix_expression ...@@ -286,32 +285,24 @@ postfix_expression
if ($3->getQualifier().storage == EvqConst) { if ($3->getQualifier().storage == EvqConst) {
int index = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); int index = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
if (! $1->isArray() && ($1->isVector() && $1->getType().getVectorSize() <= index || if (! $1->isArray() && ($1->isVector() && $1->getType().getVectorSize() <= index ||
$1->isMatrix() && $1->getType().getMatrixCols() <= index)) { $1->isMatrix() && $1->getType().getMatrixCols() <= index))
parseContext.error($2.line, "", "[", "index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); parseContext.error($2.line, "", "[", "index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
parseContext.recover(); else {
} else {
if ($1->isArray()) { if ($1->isArray()) {
if ($1->getType().getArraySize() == 0) { if ($1->getType().getArraySize() == 0) {
if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) { if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst())
if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line)) parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line);
parseContext.recover(); else
} else { parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line);
if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
parseContext.recover();
}
} else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize() || } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize() ||
$3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() < 0) { $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() < 0)
parseContext.error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()); parseContext.error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
parseContext.recover();
}
} }
$$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line); $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
} }
} else { } else {
if ($1->isArray() && $1->getType().getArraySize() == 0) { if ($1->isArray() && $1->getType().getArraySize() == 0)
parseContext.error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable"); parseContext.error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
parseContext.recover();
}
if ($1->getBasicType() == EbtBlock) if ($1->getBasicType() == EbtBlock)
parseContext.requireProfile($1->getLine(), static_cast<EProfileMask>(~EEsProfileMask), "variable indexing block array"); parseContext.requireProfile($1->getLine(), static_cast<EProfileMask>(~EEsProfileMask), "variable indexing block array");
...@@ -334,7 +325,7 @@ postfix_expression ...@@ -334,7 +325,7 @@ postfix_expression
$$ = $1; $$ = $1;
} }
| postfix_expression DOT FIELD_SELECTION { | postfix_expression DOT FIELD_SELECTION {
parseContext.variableErrorCheck($1); parseContext.variableCheck($1);
if ($1->isArray()) { if ($1->isArray()) {
// //
// It can only be a method (e.g., length), which can't be resolved until // It can only be a method (e.g., length), which can't be resolved until
...@@ -348,7 +339,6 @@ postfix_expression ...@@ -348,7 +339,6 @@ postfix_expression
$$ = parseContext.intermediate.addMethod($1, TType(EbtInt), $3.string, $2.line); $$ = parseContext.intermediate.addMethod($1, TType(EbtInt), $3.string, $2.line);
} else { } else {
parseContext.error($3.line, "only the length method is supported for array", $3.string->c_str(), ""); parseContext.error($3.line, "only the length method is supported for array", $3.string->c_str(), "");
parseContext.recover();
$$ = $1; $$ = $1;
} }
} else if ($1->isVector()) { } else if ($1->isVector()) {
...@@ -356,15 +346,12 @@ postfix_expression ...@@ -356,15 +346,12 @@ postfix_expression
if (! parseContext.parseVectorFields(*$3.string, $1->getVectorSize(), fields, $3.line)) { if (! parseContext.parseVectorFields(*$3.string, $1->getVectorSize(), fields, $3.line)) {
fields.num = 1; fields.num = 1;
fields.offsets[0] = 0; fields.offsets[0] = 0;
parseContext.recover();
} }
if ($1->getType().getQualifier().storage == EvqConst) { // constant folding for vector fields if ($1->getType().getQualifier().storage == EvqConst) { // constant folding for vector fields
$$ = parseContext.addConstVectorNode(fields, $1, $3.line); $$ = parseContext.addConstVectorNode(fields, $1, $3.line);
if ($$ == 0) { if ($$ == 0)
parseContext.recover();
$$ = $1; $$ = $1;
}
else else
$$->setType(TType($1->getBasicType(), EvqConst, (int) (*$3.string).size())); $$->setType(TType($1->getBasicType(), EvqConst, (int) (*$3.string).size()));
} else { } else {
...@@ -381,15 +368,13 @@ postfix_expression ...@@ -381,15 +368,13 @@ postfix_expression
$$->setType(TType($1->getBasicType(), EvqTemporary, $1->getType().getQualifier().precision, (int) vectorString.size())); $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getType().getQualifier().precision, (int) vectorString.size()));
} }
} }
} else if ($1->isMatrix()) { } else if ($1->isMatrix())
parseContext.error($2.line, "field selection not allowed on matrix", ".", ""); parseContext.error($2.line, "field selection not allowed on matrix", ".", "");
parseContext.recover(); else if ($1->getBasicType() == EbtStruct || $1->getBasicType() == EbtBlock) {
} else if ($1->getBasicType() == EbtStruct || $1->getBasicType() == EbtBlock) {
bool fieldFound = false; bool fieldFound = false;
TTypeList* fields = $1->getType().getStruct(); TTypeList* fields = $1->getType().getStruct();
if (fields == 0) { if (fields == 0) {
parseContext.error($2.line, "structure has no fields", "Internal Error", ""); parseContext.error($2.line, "structure has no fields", "Internal Error", "");
parseContext.recover();
$$ = $1; $$ = $1;
} else { } else {
unsigned int i; unsigned int i;
...@@ -402,10 +387,9 @@ postfix_expression ...@@ -402,10 +387,9 @@ postfix_expression
if (fieldFound) { if (fieldFound) {
if ($1->getType().getQualifier().storage == EvqConst) { if ($1->getType().getQualifier().storage == EvqConst) {
$$ = parseContext.addConstStruct(*$3.string, $1, $2.line); $$ = parseContext.addConstStruct(*$3.string, $1, $2.line);
if ($$ == 0) { if ($$ == 0)
parseContext.recover();
$$ = $1; $$ = $1;
} else { else {
$$->setType(*(*fields)[i].type); $$->setType(*(*fields)[i].type);
// change the qualifier of the return type, not of the structure field // change the qualifier of the return type, not of the structure field
// as the structure definition is shared between various structures. // as the structure definition is shared between various structures.
...@@ -420,36 +404,30 @@ postfix_expression ...@@ -420,36 +404,30 @@ postfix_expression
} }
} else { } else {
parseContext.error($2.line, " no such field in structure", $3.string->c_str(), ""); parseContext.error($2.line, " no such field in structure", $3.string->c_str(), "");
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
} else { } else {
parseContext.error($2.line, " dot operator requires structure, array, vector, or matrix on left hand side", $3.string->c_str(), ""); parseContext.error($2.line, " dot operator requires structure, array, vector, or matrix on left hand side", $3.string->c_str(), "");
parseContext.recover();
$$ = $1; $$ = $1;
} }
// don't delete $3.string, it's from the pool // don't delete $3.string, it's from the pool
} }
| postfix_expression INC_OP { | postfix_expression INC_OP {
parseContext.variableErrorCheck($1); parseContext.variableCheck($1);
if (parseContext.lValueErrorCheck($2.line, "++", $1)) parseContext.lValueErrorCheck($2.line, "++", $1);
parseContext.recover();
$$ = parseContext.intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line); $$ = parseContext.intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.unaryOpError($2.line, "++", $1->getCompleteString()); parseContext.unaryOpError($2.line, "++", $1->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
| postfix_expression DEC_OP { | postfix_expression DEC_OP {
parseContext.variableErrorCheck($1); parseContext.variableCheck($1);
if (parseContext.lValueErrorCheck($2.line, "--", $1)) parseContext.lValueErrorCheck($2.line, "--", $1);
parseContext.recover();
$$ = parseContext.intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line); $$ = parseContext.intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.unaryOpError($2.line, "--", $1->getCompleteString()); parseContext.unaryOpError($2.line, "--", $1->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -457,8 +435,7 @@ postfix_expression ...@@ -457,8 +435,7 @@ postfix_expression
integer_expression integer_expression
: expression { : expression {
if (parseContext.integerErrorCheck($1, "[]")) parseContext.integerCheck($1, "[]");
parseContext.recover();
$$ = $1; $$ = $1;
} }
; ;
...@@ -472,7 +449,6 @@ function_call ...@@ -472,7 +449,6 @@ function_call
int length; int length;
if ($1.intermNode->getAsTyped() == 0 || ! $1.intermNode->getAsTyped()->getType().isArray() || $1.intermNode->getAsTyped()->getType().getArraySize() == 0) { if ($1.intermNode->getAsTyped() == 0 || ! $1.intermNode->getAsTyped()->getType().isArray() || $1.intermNode->getAsTyped()->getType().getArraySize() == 0) {
parseContext.error($1.line, "", fnCall->getName().c_str(), "array must be declared with a size before using this method"); parseContext.error($1.line, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");
parseContext.recover();
length = 1; length = 1;
} else } else
length = $1.intermNode->getAsTyped()->getType().getArraySize(); length = $1.intermNode->getAsTyped()->getType().getArraySize();
...@@ -487,19 +463,19 @@ function_call ...@@ -487,19 +463,19 @@ function_call
// Their parameters will be verified algorithmically. // Their parameters will be verified algorithmically.
// //
TType type(EbtVoid); // use this to get the type back TType type(EbtVoid); // use this to get the type back
if (parseContext.constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) { if (parseContext.constructorError($1.line, $1.intermNode, *fnCall, op, &type)) {
$$ = 0; $$ = 0;
} else { } else {
// //
// It's a constructor, of type 'type'. // It's a constructor, of type 'type'.
// //
$$ = parseContext.addConstructor($1.intermNode, type, op, fnCall, $1.line); $$ = parseContext.addConstructor($1.intermNode, type, op, fnCall, $1.line);
if ($$ == 0)
parseContext.error($1.line, "cannot construct with these arguments", type.getCompleteString().c_str(), "");
} }
if ($$ == 0) { if ($$ == 0)
parseContext.recover();
$$ = parseContext.intermediate.setAggregateOperator(0, op, type, $1.line); $$ = parseContext.intermediate.setAggregateOperator(0, op, type, $1.line);
}
} else { } else {
// //
// Not a constructor. Find it in the symbol table. // Not a constructor. Find it in the symbol table.
...@@ -538,10 +514,8 @@ function_call ...@@ -538,10 +514,8 @@ function_call
for (int i = 0; i < fnCandidate->getParamCount(); ++i) { for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
qual = (*fnCandidate)[i].type->getQualifier().storage; qual = (*fnCandidate)[i].type->getQualifier().storage;
if (qual == EvqOut || qual == EvqInOut) { if (qual == EvqOut || qual == EvqInOut) {
if (parseContext.lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) { if (parseContext.lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped()))
parseContext.error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", ""); parseContext.error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
parseContext.recover();
}
} }
qualifierList.push_back(qual); qualifierList.push_back(qual);
} }
...@@ -557,7 +531,6 @@ function_call ...@@ -557,7 +531,6 @@ function_call
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setDConst(0.0); unionArray->setDConst(0.0);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
parseContext.recover();
} }
} }
delete fnCall; delete fnCall;
...@@ -743,7 +716,6 @@ function_identifier ...@@ -743,7 +716,6 @@ function_identifier
} }
if (op == EOpNull) { if (op == EOpNull) {
parseContext.error($1.line, "cannot construct this type", TType::getBasicString($1.basicType), ""); parseContext.error($1.line, "cannot construct this type", TType::getBasicString($1.basicType), "");
parseContext.recover();
$1.basicType = EbtFloat; $1.basicType = EbtFloat;
op = EOpConstructFloat; op = EOpConstructFloat;
} }
...@@ -765,21 +737,16 @@ function_identifier ...@@ -765,21 +737,16 @@ function_identifier
if (method->getObject()->isArray()) { if (method->getObject()->isArray()) {
$$.function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength); $$.function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength);
$$.intermNode = method->getObject(); $$.intermNode = method->getObject();
} else { } else
parseContext.error(method->getLine(), "only arrays have methods", "", ""); parseContext.error(method->getLine(), "only arrays have methods", "", "");
parseContext.recover();
}
} else { } else {
TIntermSymbol* symbol = $1->getAsSymbolNode(); TIntermSymbol* symbol = $1->getAsSymbolNode();
if (symbol) { if (symbol) {
if (parseContext.reservedErrorCheck(symbol->getLine(), symbol->getSymbol())) parseContext.reservedErrorCheck(symbol->getLine(), symbol->getSymbol());
parseContext.recover();
TFunction *function = new TFunction(&symbol->getSymbol(), TType(EbtVoid)); TFunction *function = new TFunction(&symbol->getSymbol(), TType(EbtVoid));
$$.function = function; $$.function = function;
} else { } else
parseContext.error($1->getLine(), "function call, method or subroutine call expected", "", ""); parseContext.error($1->getLine(), "function call, method or subroutine call expected", "", "");
parseContext.recover();
}
} }
if ($$.function == 0) { if ($$.function == 0) {
...@@ -792,26 +759,22 @@ function_identifier ...@@ -792,26 +759,22 @@ function_identifier
unary_expression unary_expression
: postfix_expression { : postfix_expression {
parseContext.variableErrorCheck($1); parseContext.variableCheck($1);
$$ = $1; $$ = $1;
} }
| INC_OP unary_expression { | INC_OP unary_expression {
if (parseContext.lValueErrorCheck($1.line, "++", $2)) parseContext.lValueErrorCheck($1.line, "++", $2);
parseContext.recover();
$$ = parseContext.intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line); $$ = parseContext.intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.unaryOpError($1.line, "++", $2->getCompleteString()); parseContext.unaryOpError($1.line, "++", $2->getCompleteString());
parseContext.recover();
$$ = $2; $$ = $2;
} }
} }
| DEC_OP unary_expression { | DEC_OP unary_expression {
if (parseContext.lValueErrorCheck($1.line, "--", $2)) parseContext.lValueErrorCheck($1.line, "--", $2);
parseContext.recover();
$$ = parseContext.intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line); $$ = parseContext.intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.unaryOpError($1.line, "--", $2->getCompleteString()); parseContext.unaryOpError($1.line, "--", $2->getCompleteString());
parseContext.recover();
$$ = $2; $$ = $2;
} }
} }
...@@ -827,7 +790,6 @@ unary_expression ...@@ -827,7 +790,6 @@ unary_expression
default: break; // some compilers want this default: break; // some compilers want this
} }
parseContext.unaryOpError($1.line, errorOp, $2->getCompleteString()); parseContext.unaryOpError($1.line, errorOp, $2->getCompleteString());
parseContext.recover();
$$ = $2; $$ = $2;
} }
} else } else
...@@ -850,7 +812,6 @@ multiplicative_expression ...@@ -850,7 +812,6 @@ multiplicative_expression
$$ = parseContext.intermediate.addBinaryMath(EOpMul, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpMul, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -858,7 +819,6 @@ multiplicative_expression ...@@ -858,7 +819,6 @@ multiplicative_expression
$$ = parseContext.intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -866,7 +826,6 @@ multiplicative_expression ...@@ -866,7 +826,6 @@ multiplicative_expression
$$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "%", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "%", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -878,7 +837,6 @@ additive_expression ...@@ -878,7 +837,6 @@ additive_expression
$$ = parseContext.intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -886,7 +844,6 @@ additive_expression ...@@ -886,7 +844,6 @@ additive_expression
$$ = parseContext.intermediate.addBinaryMath(EOpSub, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpSub, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -899,7 +856,6 @@ shift_expression ...@@ -899,7 +856,6 @@ shift_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "<<", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "<<", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -908,7 +864,6 @@ shift_expression ...@@ -908,7 +864,6 @@ shift_expression
$$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, ">>", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, ">>", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -920,7 +875,6 @@ relational_expression ...@@ -920,7 +875,6 @@ relational_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false); unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
...@@ -930,7 +884,6 @@ relational_expression ...@@ -930,7 +884,6 @@ relational_expression
$$ = parseContext.intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false); unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
...@@ -940,7 +893,6 @@ relational_expression ...@@ -940,7 +893,6 @@ relational_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false); unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
...@@ -950,7 +902,6 @@ relational_expression ...@@ -950,7 +902,6 @@ relational_expression
$$ = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false); unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
...@@ -964,7 +915,6 @@ equality_expression ...@@ -964,7 +915,6 @@ equality_expression
$$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false); unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
...@@ -975,7 +925,6 @@ equality_expression ...@@ -975,7 +925,6 @@ equality_expression
$$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false); unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
...@@ -991,7 +940,6 @@ and_expression ...@@ -991,7 +940,6 @@ and_expression
$$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "&", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "&", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -1004,7 +952,6 @@ exclusive_or_expression ...@@ -1004,7 +952,6 @@ exclusive_or_expression
$$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "^", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "^", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -1017,7 +964,6 @@ inclusive_or_expression ...@@ -1017,7 +964,6 @@ inclusive_or_expression
$$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "|", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "|", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} }
} }
...@@ -1029,7 +975,6 @@ logical_and_expression ...@@ -1029,7 +975,6 @@ logical_and_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false); unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
...@@ -1043,7 +988,6 @@ logical_xor_expression ...@@ -1043,7 +988,6 @@ logical_xor_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false); unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
...@@ -1057,7 +1001,6 @@ logical_or_expression ...@@ -1057,7 +1001,6 @@ logical_or_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line); $$ = parseContext.intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1]; constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false); unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line); $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
...@@ -1068,13 +1011,11 @@ logical_or_expression ...@@ -1068,13 +1011,11 @@ logical_or_expression
conditional_expression conditional_expression
: logical_or_expression { $$ = $1; } : logical_or_expression { $$ = $1; }
| logical_or_expression QUESTION expression COLON assignment_expression { | logical_or_expression QUESTION expression COLON assignment_expression {
if (parseContext.boolErrorCheck($2.line, $1)) parseContext.boolCheck($2.line, $1);
parseContext.recover();
$$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line); $$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString()); parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
parseContext.recover();
$$ = $5; $$ = $5;
} }
} }
...@@ -1083,12 +1024,10 @@ conditional_expression ...@@ -1083,12 +1024,10 @@ conditional_expression
assignment_expression assignment_expression
: conditional_expression { $$ = $1; } : conditional_expression { $$ = $1; }
| unary_expression assignment_operator assignment_expression { | unary_expression assignment_operator assignment_expression {
if (parseContext.lValueErrorCheck($2.line, "assign", $1)) parseContext.lValueErrorCheck($2.line, "assign", $1);
parseContext.recover();
$$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.line); $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString()); parseContext.assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1; $$ = $1;
} else if (($1->isArray() || $3->isArray())) } else if (($1->isArray() || $3->isArray()))
parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "="); parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "=");
...@@ -1132,7 +1071,6 @@ expression ...@@ -1132,7 +1071,6 @@ expression
$$ = parseContext.intermediate.addComma($1, $3, $2.line); $$ = parseContext.intermediate.addComma($1, $3, $2.line);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $3; $$ = $3;
} }
} }
...@@ -1140,8 +1078,7 @@ expression ...@@ -1140,8 +1078,7 @@ expression
constant_expression constant_expression
: conditional_expression { : conditional_expression {
if (parseContext.constErrorCheck($1)) parseContext.constCheck($1);
parseContext.recover();
$$ = $1; $$ = $1;
} }
; ;
...@@ -1224,14 +1161,10 @@ function_prototype ...@@ -1224,14 +1161,10 @@ function_prototype
if (prevDec) { if (prevDec) {
if (prevDec->getReturnType() != $1->getReturnType()) { if (prevDec->getReturnType() != $1->getReturnType()) {
parseContext.error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getCompleteTypeString().c_str(), ""); parseContext.error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getCompleteTypeString().c_str(), "");
parseContext.recover();
} }
for (int i = 0; i < prevDec->getParamCount(); ++i) { for (int i = 0; i < prevDec->getParamCount(); ++i) {
if ((*prevDec)[i].type->getQualifier().storage != (*$1)[i].type->getQualifier().storage) { if ((*prevDec)[i].type->getQualifier().storage != (*$1)[i].type->getQualifier().storage)
parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getStorageQualifierString(), "");
(*$1)[i].type->getStorageQualifierString(), "");
parseContext.recover();
}
} }
} }
...@@ -1243,10 +1176,8 @@ function_prototype ...@@ -1243,10 +1176,8 @@ function_prototype
$$.function = $1; $$.function = $1;
$$.line = $2.line; $$.line = $2.line;
if (! parseContext.symbolTable.insert(*$$.function)) { if (! parseContext.symbolTable.insert(*$$.function))
parseContext.error($2.line, "illegal redeclaration", $$.function->getName().c_str(), ""); parseContext.error($2.line, "illegal redeclaration", $$.function->getName().c_str(), "");
parseContext.recover();
}
} }
; ;
...@@ -1279,7 +1210,6 @@ function_header_with_parameters ...@@ -1279,7 +1210,6 @@ function_header_with_parameters
// This parameter > first is void // This parameter > first is void
// //
parseContext.error($2.line, "cannot be an argument type except for '(void)'", "void", ""); parseContext.error($2.line, "cannot be an argument type except for '(void)'", "void", "");
parseContext.recover();
delete $3.param.type; delete $3.param.type;
} else { } else {
// Add the parameter // Add the parameter
...@@ -1294,7 +1224,6 @@ function_header ...@@ -1294,7 +1224,6 @@ function_header
if ($1.qualifier.storage != EvqGlobal && $1.qualifier.storage != EvqTemporary) { if ($1.qualifier.storage != EvqGlobal && $1.qualifier.storage != EvqTemporary) {
parseContext.error($2.line, "no qualifiers allowed for function return", parseContext.error($2.line, "no qualifiers allowed for function return",
getStorageQualifierString($1.qualifier.storage), ""); getStorageQualifierString($1.qualifier.storage), "");
parseContext.recover();
} }
// Add the function as a prototype after parsing it (we do not support recursion) // Add the function as a prototype after parsing it (we do not support recursion)
...@@ -1314,10 +1243,8 @@ parameter_declarator ...@@ -1314,10 +1243,8 @@ parameter_declarator
} }
if ($1.basicType == EbtVoid) { if ($1.basicType == EbtVoid) {
parseContext.error($2.line, "illegal use of type 'void'", $2.string->c_str(), ""); parseContext.error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");
parseContext.recover();
} }
if (parseContext.reservedErrorCheck($2.line, *$2.string)) parseContext.reservedErrorCheck($2.line, *$2.string);
parseContext.recover();
TParameter param = {$2.string, new TType($1)}; TParameter param = {$2.string, new TType($1)};
$$.line = $2.line; $$.line = $2.line;
...@@ -1329,11 +1256,8 @@ parameter_declarator ...@@ -1329,11 +1256,8 @@ parameter_declarator
parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type"); parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");
} }
if (parseContext.arraySizeRequiredErrorCheck($3.line, $3.arraySizes->front())) parseContext.arraySizeRequiredCheck($3.line, $3.arraySizes->front());
parseContext.recover(); parseContext.reservedErrorCheck($2.line, *$2.string);
if (parseContext.reservedErrorCheck($2.line, *$2.string))
parseContext.recover();
$1.arraySizes = $3.arraySizes; $1.arraySizes = $3.arraySizes;
...@@ -1352,18 +1276,14 @@ parameter_declaration ...@@ -1352,18 +1276,14 @@ parameter_declaration
if ($1.qualifier.precision != EpqNone) if ($1.qualifier.precision != EpqNone)
$$.param.type->getQualifier().precision = $1.qualifier.precision; $$.param.type->getQualifier().precision = $1.qualifier.precision;
if (parseContext.parameterSamplerErrorCheck($2.line, $1.qualifier.storage, *$$.param.type)) parseContext.parameterSamplerCheck($2.line, $1.qualifier.storage, *$$.param.type);
parseContext.recover(); parseContext.paramCheck($1.line, $1.qualifier.storage, $$.param.type);
if (parseContext.paramErrorCheck($1.line, $1.qualifier.storage, $$.param.type))
parseContext.recover();
} }
| parameter_declarator { | parameter_declarator {
$$ = $1; $$ = $1;
if (parseContext.parameterSamplerErrorCheck($1.line, EvqIn, *$1.param.type)) parseContext.parameterSamplerCheck($1.line, EvqIn, *$1.param.type);
parseContext.recover(); parseContext.paramCheck($1.line, EvqTemporary, $$.param.type);
if (parseContext.paramErrorCheck($1.line, EvqTemporary, $$.param.type))
parseContext.recover();
} }
// //
// Without name // Without name
...@@ -1373,18 +1293,14 @@ parameter_declaration ...@@ -1373,18 +1293,14 @@ parameter_declaration
if ($1.qualifier.precision != EpqNone) if ($1.qualifier.precision != EpqNone)
$$.param.type->getQualifier().precision = $1.qualifier.precision; $$.param.type->getQualifier().precision = $1.qualifier.precision;
if (parseContext.parameterSamplerErrorCheck($2.line, $1.qualifier.storage, *$$.param.type)) parseContext.parameterSamplerCheck($2.line, $1.qualifier.storage, *$$.param.type);
parseContext.recover(); parseContext.paramCheck($1.line, $1.qualifier.storage, $$.param.type);
if (parseContext.paramErrorCheck($1.line, $1.qualifier.storage, $$.param.type))
parseContext.recover();
} }
| parameter_type_specifier { | parameter_type_specifier {
$$ = $1; $$ = $1;
if (parseContext.parameterSamplerErrorCheck($1.line, EvqIn, *$1.param.type)) parseContext.parameterSamplerCheck($1.line, EvqIn, *$1.param.type);
parseContext.recover(); parseContext.paramCheck($1.line, EvqTemporary, $$.param.type);
if (parseContext.paramErrorCheck($1.line, EvqTemporary, $$.param.type))
parseContext.recover();
} }
; ;
...@@ -1401,43 +1317,33 @@ init_declarator_list ...@@ -1401,43 +1317,33 @@ init_declarator_list
} }
| init_declarator_list COMMA IDENTIFIER { | init_declarator_list COMMA IDENTIFIER {
$$ = $1; $$ = $1;
if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $$.type)) parseContext.nonInitConstCheck($3.line, *$3.string, $$.type);
parseContext.recover(); parseContext.nonInitCheck($3.line, *$3.string, $$.type);
if (parseContext.nonInitErrorCheck($3.line, *$3.string, $$.type))
parseContext.recover();
} }
| init_declarator_list COMMA IDENTIFIER array_specifier { | init_declarator_list COMMA IDENTIFIER array_specifier {
if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type)) parseContext.nonInitConstCheck($3.line, *$3.string, $1.type);
parseContext.recover();
$$ = $1; $$ = $1;
if (parseContext.arrayQualifierErrorCheck($4.line, $1.type)) if (! parseContext.arrayQualifierError($4.line, $1.type)) {
parseContext.recover();
else {
$1.type.arraySizes = $4.arraySizes; $1.type.arraySizes = $4.arraySizes;
TVariable* variable; TVariable* variable;
if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable)) parseContext.arrayCheck($4.line, *$3.string, $1.type, variable);
parseContext.recover();
} }
} }
| init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer { | init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer {
$$ = $1; $$ = $1;
TVariable* variable = 0; TVariable* variable = 0;
if (parseContext.arrayQualifierErrorCheck($4.line, $1.type)) if (! parseContext.arrayQualifierError($4.line, $1.type)) {
parseContext.recover();
else {
$1.type.arraySizes = $4.arraySizes; $1.type.arraySizes = $4.arraySizes;
if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable)) parseContext.arrayCheck($4.line, *$3.string, $1.type, variable);
parseContext.recover();
} }
parseContext.profileRequires($5.line, ENoProfile, 120, "GL_3DL_array_objects", "initializer"); parseContext.profileRequires($5.line, ENoProfile, 120, "GL_3DL_array_objects", "initializer");
TIntermNode* intermNode; TIntermNode* intermNode;
if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $6, intermNode, variable)) { if (! parseContext.executeInitializerError($3.line, *$3.string, $1.type, $6, intermNode, variable)) {
// //
// build the intermediate representation // build the intermediate representation
// //
...@@ -1445,16 +1351,14 @@ init_declarator_list ...@@ -1445,16 +1351,14 @@ init_declarator_list
$$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $5.line); $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $5.line);
else else
$$.intermAggregate = $1.intermAggregate; $$.intermAggregate = $1.intermAggregate;
} else { } else
parseContext.recover();
$$.intermAggregate = 0; $$.intermAggregate = 0;
}
} }
| init_declarator_list COMMA IDENTIFIER EQUAL initializer { | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
$$ = $1; $$ = $1;
TIntermNode* intermNode; TIntermNode* intermNode;
if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) { if (!parseContext.executeInitializerError($3.line, *$3.string, $1.type, $5, intermNode)) {
// //
// build the intermediate representation // build the intermediate representation
// //
...@@ -1462,10 +1366,8 @@ init_declarator_list ...@@ -1462,10 +1366,8 @@ init_declarator_list
$$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $4.line); $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $4.line);
else else
$$.intermAggregate = $1.intermAggregate; $$.intermAggregate = $1.intermAggregate;
} else { } else
parseContext.recover();
$$.intermAggregate = 0; $$.intermAggregate = 0;
}
} }
; ;
...@@ -1479,28 +1381,21 @@ single_declaration ...@@ -1479,28 +1381,21 @@ single_declaration
$$.intermAggregate = 0; $$.intermAggregate = 0;
$$.type = $1; $$.type = $1;
if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $$.type)) parseContext.nonInitConstCheck($2.line, *$2.string, $$.type);
parseContext.recover(); parseContext.nonInitCheck($2.line, *$2.string, $$.type);
if (parseContext.nonInitErrorCheck($2.line, *$2.string, $$.type))
parseContext.recover();
parseContext.updateDefaults($2.line, $$.type, $2.string); parseContext.updateDefaults($2.line, $$.type, $2.string);
} }
| fully_specified_type IDENTIFIER array_specifier { | fully_specified_type IDENTIFIER array_specifier {
$$.intermAggregate = 0; $$.intermAggregate = 0;
if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1)) parseContext.nonInitConstCheck($2.line, *$2.string, $1);
parseContext.recover();
$$.type = $1; $$.type = $1;
if (parseContext.arrayQualifierErrorCheck($3.line, $1)) if (! parseContext.arrayQualifierError($3.line, $1)) {
parseContext.recover();
else {
$1.arraySizes = $3.arraySizes; $1.arraySizes = $3.arraySizes;
TVariable* variable; TVariable* variable;
if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable)) parseContext.arrayCheck($3.line, *$2.string, $1, variable);
parseContext.recover();
} }
parseContext.updateDefaults($2.line, $$.type, $2.string); parseContext.updateDefaults($2.line, $$.type, $2.string);
} }
...@@ -1509,18 +1404,15 @@ single_declaration ...@@ -1509,18 +1404,15 @@ single_declaration
$$.type = $1; $$.type = $1;
TVariable* variable = 0; TVariable* variable = 0;
if (parseContext.arrayQualifierErrorCheck($3.line, $1)) if (! parseContext.arrayQualifierError($3.line, $1)) {
parseContext.recover();
else {
$1.arraySizes = $3.arraySizes; $1.arraySizes = $3.arraySizes;
if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable)) parseContext.arrayCheck($3.line, *$2.string, $1, variable);
parseContext.recover();
} }
parseContext.profileRequires($4.line, ENoProfile, 120, "GL_3DL_array_objects", "initializer"); parseContext.profileRequires($4.line, ENoProfile, 120, "GL_3DL_array_objects", "initializer");
TIntermNode* intermNode; TIntermNode* intermNode;
if (!parseContext.executeInitializer($2.line, *$2.string, $1, $5, intermNode, variable)) { if (!parseContext.executeInitializerError($2.line, *$2.string, $1, $5, intermNode, variable)) {
// //
// Build intermediate representation // Build intermediate representation
// //
...@@ -1528,16 +1420,14 @@ single_declaration ...@@ -1528,16 +1420,14 @@ single_declaration
$$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $4.line); $$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $4.line);
else else
$$.intermAggregate = 0; $$.intermAggregate = 0;
} else { } else
parseContext.recover();
$$.intermAggregate = 0; $$.intermAggregate = 0;
}
} }
| fully_specified_type IDENTIFIER EQUAL initializer { | fully_specified_type IDENTIFIER EQUAL initializer {
$$.type = $1; $$.type = $1;
TIntermNode* intermNode; TIntermNode* intermNode;
if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode)) { if (!parseContext.executeInitializerError($2.line, *$2.string, $1, $4, intermNode)) {
// //
// Build intermediate representation // Build intermediate representation
// //
...@@ -1545,10 +1435,8 @@ single_declaration ...@@ -1545,10 +1435,8 @@ single_declaration
$$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $3.line); $$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $3.line);
else else
$$.intermAggregate = 0; $$.intermAggregate = 0;
} else { } else
parseContext.recover();
$$.intermAggregate = 0; $$.intermAggregate = 0;
}
} }
// Grammar Note: No 'enum', or 'typedef'. // Grammar Note: No 'enum', or 'typedef'.
...@@ -1563,21 +1451,17 @@ fully_specified_type ...@@ -1563,21 +1451,17 @@ fully_specified_type
} }
} }
| type_qualifier type_specifier { | type_qualifier type_specifier {
if (parseContext.globalQualifierFixAndErrorCheck($1.line, $1.qualifier, $2)) parseContext.globalQualifierFix($1.line, $1.qualifier, $2);
parseContext.recover();
if ($2.arraySizes) { if ($2.arraySizes) {
parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type"); parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
parseContext.profileRequires($2.line, EEsProfile, 300, 0, "arrayed type"); parseContext.profileRequires($2.line, EEsProfile, 300, 0, "arrayed type");
} }
if ($2.arraySizes && parseContext.arrayQualifierErrorCheck($2.line, $1)) { if ($2.arraySizes && parseContext.arrayQualifierError($2.line, $1))
parseContext.recover();
$2.arraySizes = 0; $2.arraySizes = 0;
}
if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true)) parseContext.mergeQualifiers($2.line, $2, $1, true);
parseContext.recover();
$$ = $2; $$ = $2;
...@@ -1596,24 +1480,21 @@ invariant_qualifier ...@@ -1596,24 +1480,21 @@ invariant_qualifier
interpolation_qualifier interpolation_qualifier
: SMOOTH { : SMOOTH {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "smooth")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "smooth");
parseContext.recover();
parseContext.profileRequires($1.line, ENoProfile, 130, 0, "smooth"); parseContext.profileRequires($1.line, ENoProfile, 130, 0, "smooth");
parseContext.profileRequires($1.line, EEsProfile, 300, 0, "smooth"); parseContext.profileRequires($1.line, EEsProfile, 300, 0, "smooth");
$$.init($1.line); $$.init($1.line);
$$.qualifier.smooth = true; $$.qualifier.smooth = true;
} }
| FLAT { | FLAT {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "flat")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "flat");
parseContext.recover();
parseContext.profileRequires($1.line, ENoProfile, 130, 0, "flat"); parseContext.profileRequires($1.line, ENoProfile, 130, 0, "flat");
parseContext.profileRequires($1.line, EEsProfile, 300, 0, "flat"); parseContext.profileRequires($1.line, EEsProfile, 300, 0, "flat");
$$.init($1.line); $$.init($1.line);
$$.qualifier.flat = true; $$.qualifier.flat = true;
} }
| NOPERSPECTIVE { | NOPERSPECTIVE {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "noperspective")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "noperspective");
parseContext.recover();
parseContext.requireProfile($1.line, static_cast<EProfileMask>(~EEsProfileMask), "noperspective"); parseContext.requireProfile($1.line, static_cast<EProfileMask>(~EEsProfileMask), "noperspective");
parseContext.profileRequires($1.line, ENoProfile, 130, 0, "noperspective"); parseContext.profileRequires($1.line, ENoProfile, 130, 0, "noperspective");
$$.init($1.line); $$.init($1.line);
...@@ -1667,8 +1548,7 @@ type_qualifier ...@@ -1667,8 +1548,7 @@ type_qualifier
if ($$.basicType == EbtVoid) if ($$.basicType == EbtVoid)
$$.basicType = $2.basicType; $$.basicType = $2.basicType;
if (parseContext.mergeQualifiersErrorCheck($$.line, $$, $2, false)) parseContext.mergeQualifiers($$.line, $$, $2, false);
parseContext.recover();
} }
; ;
...@@ -1708,8 +1588,7 @@ storage_qualifier ...@@ -1708,8 +1588,7 @@ storage_qualifier
parseContext.requireNotRemoved($1.line, ECoreProfile, 420, "attribute"); parseContext.requireNotRemoved($1.line, ECoreProfile, 420, "attribute");
parseContext.requireNotRemoved($1.line, EEsProfile, 300, "attribute"); parseContext.requireNotRemoved($1.line, EEsProfile, 300, "attribute");
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.storage = EvqVaryingIn; $$.qualifier.storage = EvqVaryingIn;
...@@ -1720,8 +1599,7 @@ storage_qualifier ...@@ -1720,8 +1599,7 @@ storage_qualifier
parseContext.requireNotRemoved($1.line, ECoreProfile, 420, "varying"); parseContext.requireNotRemoved($1.line, ECoreProfile, 420, "varying");
parseContext.requireNotRemoved($1.line, EEsProfile, 300, "varying"); parseContext.requireNotRemoved($1.line, EEsProfile, 300, "varying");
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
if (parseContext.language == EShLangVertex) if (parseContext.language == EShLangVertex)
...@@ -1730,52 +1608,44 @@ storage_qualifier ...@@ -1730,52 +1608,44 @@ storage_qualifier
$$.qualifier.storage = EvqVaryingIn; $$.qualifier.storage = EvqVaryingIn;
} }
| INOUT { | INOUT {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.storage = EvqInOut; $$.qualifier.storage = EvqInOut;
} }
| IN { | IN {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "in")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "in");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.storage = EvqIn; $$.qualifier.storage = EvqIn;
} }
| OUT { | OUT {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.storage = EvqOut; $$.qualifier.storage = EvqOut;
} }
| CENTROID { | CENTROID {
parseContext.profileRequires($1.line, ENoProfile, 120, 0, "centroid"); parseContext.profileRequires($1.line, ENoProfile, 120, 0, "centroid");
parseContext.profileRequires($1.line, EEsProfile, 300, 0, "centroid"); parseContext.profileRequires($1.line, EEsProfile, 300, 0, "centroid");
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "centroid")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "centroid");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.centroid = true; $$.qualifier.centroid = true;
} }
| PATCH { | PATCH {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "patch")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "patch");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.patch = true; $$.qualifier.patch = true;
} }
| SAMPLE { | SAMPLE {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "sample")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "sample");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.sample = true; $$.qualifier.sample = true;
} }
| UNIFORM { | UNIFORM {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "uniform")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "uniform");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.storage = EvqUniform; $$.qualifier.storage = EvqUniform;
} }
| BUFFER { | BUFFER {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "buffer")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "buffer");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.storage = EvqUniform; // TODO: 4.0 functionality: implement BUFFER $$.qualifier.storage = EvqUniform; // TODO: 4.0 functionality: implement BUFFER
} }
...@@ -1807,14 +1677,12 @@ storage_qualifier ...@@ -1807,14 +1677,12 @@ storage_qualifier
$$.qualifier.writeonly = true; $$.qualifier.writeonly = true;
} }
| SUBROUTINE { | SUBROUTINE {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.storage = EvqUniform; $$.qualifier.storage = EvqUniform;
} }
| SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN { | SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine")) parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine");
parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.storage = EvqUniform; $$.qualifier.storage = EvqUniform;
// TODO: 4.0 semantics: subroutines // TODO: 4.0 semantics: subroutines
...@@ -1854,8 +1722,7 @@ array_specifier ...@@ -1854,8 +1722,7 @@ array_specifier
$$.arraySizes = NewPoolTArraySizes(); $$.arraySizes = NewPoolTArraySizes();
int size; int size;
if (parseContext.arraySizeErrorCheck($2->getLine(), $2, size)) parseContext.arraySizeCheck($2->getLine(), $2, size);
parseContext.recover();
$$.arraySizes->push_back(size); $$.arraySizes->push_back(size);
} }
| array_specifier LEFT_BRACKET RIGHT_BRACKET { | array_specifier LEFT_BRACKET RIGHT_BRACKET {
...@@ -1866,8 +1733,7 @@ array_specifier ...@@ -1866,8 +1733,7 @@ array_specifier
$$ = $1; $$ = $1;
int size; int size;
if (parseContext.arraySizeErrorCheck($3->getLine(), $3, size)) parseContext.arraySizeCheck($3->getLine(), $3, size);
parseContext.recover();
$$.arraySizes->push_back(size); $$.arraySizes->push_back(size);
} }
; ;
...@@ -2504,10 +2370,8 @@ type_specifier_nonarray ...@@ -2504,10 +2370,8 @@ type_specifier_nonarray
$$.init($1.line, parseContext.symbolTable.atGlobalLevel()); $$.init($1.line, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtStruct; $$.basicType = EbtStruct;
$$.userDef = &structure; $$.userDef = &structure;
} else { } else
parseContext.error($1.line, "expected type name", $1.string->c_str(), ""); parseContext.error($1.line, "expected type name", $1.string->c_str(), "");
parseContext.recover();
}
} }
; ;
...@@ -2541,10 +2405,8 @@ struct_specifier ...@@ -2541,10 +2405,8 @@ struct_specifier
TType* structure = new TType($4, *$2.string); TType* structure = new TType($4, *$2.string);
TVariable* userTypeDef = new TVariable($2.string, *structure, true); TVariable* userTypeDef = new TVariable($2.string, *structure, true);
if (! parseContext.symbolTable.insert(*userTypeDef)) { if (! parseContext.symbolTable.insert(*userTypeDef))
parseContext.error($2.line, "redefinition", $2.string->c_str(), "struct"); parseContext.error($2.line, "redefinition", $2.string->c_str(), "struct");
parseContext.recover();
}
$$.init($1.line); $$.init($1.line);
$$.basicType = EbtStruct; $$.basicType = EbtStruct;
$$.userDef = structure; $$.userDef = structure;
...@@ -2565,10 +2427,8 @@ struct_declaration_list ...@@ -2565,10 +2427,8 @@ struct_declaration_list
$$ = $1; $$ = $1;
for (unsigned int i = 0; i < $2->size(); ++i) { for (unsigned int i = 0; i < $2->size(); ++i) {
for (unsigned int j = 0; j < $$->size(); ++j) { for (unsigned int j = 0; j < $$->size(); ++j) {
if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) { if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName())
parseContext.error((*$2)[i].line, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str()); parseContext.error((*$2)[i].line, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str());
parseContext.recover();
}
} }
$$->push_back((*$2)[i]); $$->push_back((*$2)[i]);
} }
...@@ -2584,9 +2444,8 @@ struct_declaration ...@@ -2584,9 +2444,8 @@ struct_declaration
$$ = $2; $$ = $2;
if (parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) { parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1);
parseContext.recover();
}
for (unsigned int i = 0; i < $$->size(); ++i) for (unsigned int i = 0; i < $$->size(); ++i)
(*$$)[i].type->mergeType($1); (*$$)[i].type->mergeType($1);
} }
...@@ -2598,10 +2457,9 @@ struct_declaration ...@@ -2598,10 +2457,9 @@ struct_declaration
$$ = $3; $$ = $3;
if (parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2)) parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2);
parseContext.recover(); parseContext.mergeQualifiers($2.line, $2, $1, true);
if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true))
parseContext.recover();
for (unsigned int i = 0; i < $$->size(); ++i) for (unsigned int i = 0; i < $$->size(); ++i)
(*$$)[i].type->mergeType($2); (*$$)[i].type->mergeType($2);
} }
...@@ -2728,8 +2586,7 @@ expression_statement ...@@ -2728,8 +2586,7 @@ expression_statement
selection_statement selection_statement
: IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
if (parseContext.boolErrorCheck($1.line, $3)) parseContext.boolCheck($1.line, $3);
parseContext.recover();
$$ = parseContext.intermediate.addSelection($3, $5, $1.line); $$ = parseContext.intermediate.addSelection($3, $5, $1.line);
} }
; ;
...@@ -2749,20 +2606,16 @@ condition ...@@ -2749,20 +2606,16 @@ condition
// In 1996 c++ draft, conditions can include single declarations // In 1996 c++ draft, conditions can include single declarations
: expression { : expression {
$$ = $1; $$ = $1;
if (parseContext.boolErrorCheck($1->getLine(), $1)) parseContext.boolCheck($1->getLine(), $1);
parseContext.recover();
} }
| fully_specified_type IDENTIFIER EQUAL initializer { | fully_specified_type IDENTIFIER EQUAL initializer {
TIntermNode* intermNode; TIntermNode* intermNode;
if (parseContext.boolErrorCheck($2.line, $1)) parseContext.boolCheck($2.line, $1);
parseContext.recover();
if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode)) if (parseContext.executeInitializerError($2.line, *$2.string, $1, $4, intermNode))
$$ = $4;
else {
parseContext.recover();
$$ = 0; $$ = 0;
} else
$$ = $4;
} }
; ;
...@@ -2807,8 +2660,7 @@ iteration_statement ...@@ -2807,8 +2660,7 @@ iteration_statement
--parseContext.loopNestingLevel; --parseContext.loopNestingLevel;
} }
| DO { ++parseContext.loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { | DO { ++parseContext.loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
if (parseContext.boolErrorCheck($8.line, $6)) parseContext.boolCheck($8.line, $6);
parseContext.recover();
$$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.line); $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.line);
--parseContext.loopNestingLevel; --parseContext.loopNestingLevel;
...@@ -2860,36 +2712,27 @@ for_rest_statement ...@@ -2860,36 +2712,27 @@ for_rest_statement
jump_statement jump_statement
: CONTINUE SEMICOLON { : CONTINUE SEMICOLON {
if (parseContext.loopNestingLevel <= 0) { if (parseContext.loopNestingLevel <= 0)
parseContext.error($1.line, "continue statement only allowed in loops", "", ""); parseContext.error($1.line, "continue statement only allowed in loops", "", "");
parseContext.recover();
}
$$ = parseContext.intermediate.addBranch(EOpContinue, $1.line); $$ = parseContext.intermediate.addBranch(EOpContinue, $1.line);
} }
| BREAK SEMICOLON { | BREAK SEMICOLON {
if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) { if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0)
parseContext.error($1.line, "break statement only allowed in switch and loops", "", ""); parseContext.error($1.line, "break statement only allowed in switch and loops", "", "");
parseContext.recover();
}
$$ = parseContext.intermediate.addBranch(EOpBreak, $1.line); $$ = parseContext.intermediate.addBranch(EOpBreak, $1.line);
} }
| RETURN SEMICOLON { | RETURN SEMICOLON {
$$ = parseContext.intermediate.addBranch(EOpReturn, $1.line); $$ = parseContext.intermediate.addBranch(EOpReturn, $1.line);
if (parseContext.currentFunctionType->getBasicType() != EbtVoid) { if (parseContext.currentFunctionType->getBasicType() != EbtVoid)
parseContext.error($1.line, "non-void function must return a value", "return", ""); parseContext.error($1.line, "non-void function must return a value", "return", "");
parseContext.recover();
}
} }
| RETURN expression SEMICOLON { | RETURN expression SEMICOLON {
$$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.line); $$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.line);
parseContext.functionReturnsValue = true; parseContext.functionReturnsValue = true;
if (parseContext.currentFunctionType->getBasicType() == EbtVoid) { if (parseContext.currentFunctionType->getBasicType() == EbtVoid)
parseContext.error($1.line, "void function cannot return a value", "return", ""); parseContext.error($1.line, "void function cannot return a value", "return", "");
parseContext.recover(); else if (*(parseContext.currentFunctionType) != $2->getType())
} else if (*(parseContext.currentFunctionType) != $2->getType()) {
parseContext.error($1.line, "function return is not matching type:", "return", ""); parseContext.error($1.line, "function return is not matching type:", "return", "");
parseContext.recover();
}
} }
| DISCARD SEMICOLON { | DISCARD SEMICOLON {
parseContext.requireStage($1.line, EShLangFragmentMask, "discard"); parseContext.requireStage($1.line, EShLangFragmentMask, "discard");
...@@ -2925,10 +2768,8 @@ function_definition ...@@ -2925,10 +2768,8 @@ function_definition
TSymbol* symbol = parseContext.symbolTable.find(function.getMangledName()); TSymbol* symbol = parseContext.symbolTable.find(function.getMangledName());
TFunction* prevDec = symbol ? symbol->getAsFunction() : 0; TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
if (! prevDec) { if (! prevDec)
parseContext.error($1.line, "can't find function name", function.getName().c_str(), ""); parseContext.error($1.line, "can't find function name", function.getName().c_str(), "");
parseContext.recover();
}
// //
// Note: 'prevDec' could be 'function' if this is the first time we've seen function // Note: 'prevDec' could be 'function' if this is the first time we've seen function
...@@ -2940,7 +2781,6 @@ function_definition ...@@ -2940,7 +2781,6 @@ function_definition
// Then this function already has a body. // Then this function already has a body.
// //
parseContext.error($1.line, "function already has a body", function.getName().c_str(), ""); parseContext.error($1.line, "function already has a body", function.getName().c_str(), "");
parseContext.recover();
} }
if (prevDec) { if (prevDec) {
prevDec->setDefined(); prevDec->setDefined();
...@@ -2956,14 +2796,10 @@ function_definition ...@@ -2956,14 +2796,10 @@ function_definition
// Raise error message if main function takes any parameters or return anything other than void // Raise error message if main function takes any parameters or return anything other than void
// //
if (function.getName() == "main") { if (function.getName() == "main") {
if (function.getParamCount() > 0) { if (function.getParamCount() > 0)
parseContext.error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), ""); parseContext.error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), "");
parseContext.recover(); if (function.getReturnType().getBasicType() != EbtVoid)
}
if (function.getReturnType().getBasicType() != EbtVoid) {
parseContext.error($1.line, "", function.getReturnType().getCompleteTypeString().c_str(), "main function cannot return a value"); parseContext.error($1.line, "", function.getReturnType().getCompleteTypeString().c_str(), "main function cannot return a value");
parseContext.recover();
}
} }
// //
...@@ -2989,7 +2825,6 @@ function_definition ...@@ -2989,7 +2825,6 @@ function_definition
// //
if (! parseContext.symbolTable.insert(*variable)) { if (! parseContext.symbolTable.insert(*variable)) {
parseContext.error($1.line, "redefinition", variable->getName().c_str(), ""); parseContext.error($1.line, "redefinition", variable->getName().c_str(), "");
parseContext.recover();
delete variable; delete variable;
} }
// //
...@@ -3016,10 +2851,8 @@ function_definition ...@@ -3016,10 +2851,8 @@ function_definition
} }
compound_statement_no_new_scope { compound_statement_no_new_scope {
// May be best done as post process phase on intermediate code // May be best done as post process phase on intermediate code
if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) { if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue)
parseContext.error($1.line, "function does not return a value:", "", $1.function->getName().c_str()); parseContext.error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
parseContext.recover();
}
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
$$ = parseContext.intermediate.growAggregate($1.intermAggregate, $3, 0); $$ = parseContext.intermediate.growAggregate($1.intermAggregate, $3, 0);
parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getReturnType(), $1.line); parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getReturnType(), $1.line);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment