Remove most of the remaining logic from glslang.y

Move most of the logic in glslang.y to ParseContext. This will make it
easier to change the code in the future.

Only a few specific bits of logic are kept in glslang.y:

* Disabling a parsing rule when a given shading language version is
  being parsed. This makes it easier to check the grammar against the
  grammar in the GLSL ES specs.
* Scoping calls that need to be paired with another call. It's much
  easier to check these for correctness when the paired calls are next
  to each other.

BUG=angleproject:911
TEST=angle_unittests

Change-Id: I52f42a1fc0f28463ca4b237dc6e88345e5173064
Reviewed-on: https://chromium-review.googlesource.com/539640
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index e1deb4f..0d9f415 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -738,7 +738,7 @@
 }
 
 //
-// This is just for debug print out, carried along with the definitions above.
+// This is just for debug and error message print out, carried along with the definitions above.
 //
 inline const char *getQualifierString(TQualifier q)
 {
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 909bb96..80755af 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -569,24 +569,18 @@
     symbolTable.push();  // ESSL3_BUILTINS
     symbolTable.push();  // ESSL3_1_BUILTINS
 
-    TPublicType integer;
-    integer.initializeBasicType(EbtInt);
-
-    TPublicType floatingPoint;
-    floatingPoint.initializeBasicType(EbtFloat);
-
     switch (shaderType)
     {
         case GL_FRAGMENT_SHADER:
-            symbolTable.setDefaultPrecision(integer, EbpMedium);
+            symbolTable.setDefaultPrecision(EbtInt, EbpMedium);
             break;
         case GL_VERTEX_SHADER:
-            symbolTable.setDefaultPrecision(integer, EbpHigh);
-            symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
+            symbolTable.setDefaultPrecision(EbtInt, EbpHigh);
+            symbolTable.setDefaultPrecision(EbtFloat, EbpHigh);
             break;
         case GL_COMPUTE_SHADER:
-            symbolTable.setDefaultPrecision(integer, EbpHigh);
-            symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
+            symbolTable.setDefaultPrecision(EbtInt, EbpHigh);
+            symbolTable.setDefaultPrecision(EbtFloat, EbpHigh);
             break;
         default:
             assert(false && "Language not supported");
@@ -603,9 +597,7 @@
     // It isn't specified whether Sampler2DRect has default precision.
     initSamplerDefaultPrecision(EbtSampler2DRect);
 
-    TPublicType atomicCounter;
-    atomicCounter.initializeBasicType(EbtAtomicCounter);
-    symbolTable.setDefaultPrecision(atomicCounter, EbpHigh);
+    symbolTable.setDefaultPrecision(EbtAtomicCounter, EbpHigh);
 
     InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
 
@@ -617,9 +609,7 @@
 void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
 {
     ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
-    TPublicType sampler;
-    sampler.initializeBasicType(samplerType);
-    symbolTable.setDefaultPrecision(sampler, EbpLow);
+    symbolTable.setDefaultPrecision(samplerType, EbpLow);
 }
 
 void TCompiler::setResourceString()
diff --git a/src/compiler/translator/Intermediate.cpp b/src/compiler/translator/Intermediate.cpp
index c607ecb..ada090a 100644
--- a/src/compiler/translator/Intermediate.cpp
+++ b/src/compiler/translator/Intermediate.cpp
@@ -84,36 +84,6 @@
     return blockNode;
 }
 
-// For "if" test nodes.  There are three children; a condition,
-// a true path, and a false path.  The two paths are in the
-// nodePair.
-//
-// Returns the node created.
-TIntermNode *TIntermediate::addIfElse(TIntermTyped *cond,
-                                      TIntermNodePair nodePair,
-                                      const TSourceLoc &line)
-{
-    // For compile time constant conditions, prune the code now.
-
-    if (cond->getAsConstantUnion())
-    {
-        if (cond->getAsConstantUnion()->getBConst(0) == true)
-        {
-            return EnsureBlock(nodePair.node1);
-        }
-        else
-        {
-            return EnsureBlock(nodePair.node2);
-        }
-    }
-
-    TIntermIfElse *node =
-        new TIntermIfElse(cond, EnsureBlock(nodePair.node1), EnsureBlock(nodePair.node2));
-    node->setLine(line);
-
-    return node;
-}
-
 TIntermTyped *TIntermediate::AddComma(TIntermTyped *left,
                                       TIntermTyped *right,
                                       const TSourceLoc &line,
@@ -225,24 +195,6 @@
     return node;
 }
 
-//
-// Add branches.
-//
-TIntermBranch *TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
-{
-    return addBranch(branchOp, 0, line);
-}
-
-TIntermBranch *TIntermediate::addBranch(TOperator branchOp,
-                                        TIntermTyped *expression,
-                                        const TSourceLoc &line)
-{
-    TIntermBranch *node = new TIntermBranch(branchOp, expression);
-    node->setLine(line);
-
-    return node;
-}
-
 TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
                                                   TDiagnostics *diagnostics)
 {
diff --git a/src/compiler/translator/Intermediate.h b/src/compiler/translator/Intermediate.h
index f996d76..0496100 100644
--- a/src/compiler/translator/Intermediate.h
+++ b/src/compiler/translator/Intermediate.h
@@ -34,7 +34,6 @@
                            const TSourceLoc &line,
                            TDiagnostics *diagnostics);
     static TIntermBlock *EnsureBlock(TIntermNode *node);
-    TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &line);
     static TIntermTyped *AddTernarySelection(TIntermTyped *cond,
                                              TIntermTyped *trueExpression,
                                              TIntermTyped *falseExpression,
@@ -51,8 +50,6 @@
                                            const TType &type,
                                            const TSourceLoc &line);
 
-    TIntermBranch *addBranch(TOperator, const TSourceLoc &);
-    TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
     static TIntermTyped *AddSwizzle(TIntermTyped *baseExpression,
                                     const TVectorFields &fields,
                                     const TSourceLoc &dotLocation);
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 73994f6..975fade 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -67,6 +67,25 @@
     return "image";
 }
 
+bool CanSetDefaultPrecisionOnType(const TPublicType &type)
+{
+    if (!SupportsPrecision(type.getBasicType()))
+    {
+        return false;
+    }
+    if (type.getBasicType() == EbtUInt)
+    {
+        // ESSL 3.00.4 section 4.5.4
+        return false;
+    }
+    if (type.isAggregate())
+    {
+        // Not allowed to set for aggregate types
+        return false;
+    }
+    return true;
+}
+
 }  // namespace
 
 // This tracks each binding point's current default offset for inheritance of subsequent
@@ -1030,6 +1049,7 @@
     const TTypeQualifierBuilder &typeQualifierBuilder,
     TType *type)
 {
+    // The only parameter qualifiers a parameter can have are in, out, inout or const.
     TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
 
     if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
@@ -1839,11 +1859,22 @@
     }
     if (cond == nullptr || typedCond)
     {
+        if (type == ELoopDoWhile)
+        {
+            checkIsScalarBool(line, typedCond);
+        }
+        // In the case of other loops, it was checked before that the condition is a scalar boolean.
+        ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr ||
+               (typedCond->getBasicType() == EbtBool && !typedCond->isArray() &&
+                !typedCond->isVector()));
+
         node = new TIntermLoop(type, init, typedCond, expr, TIntermediate::EnsureBlock(body));
         node->setLine(line);
         return node;
     }
 
+    ASSERT(type != ELoopDoWhile);
+
     TIntermDeclaration *declaration = cond->getAsDeclarationNode();
     ASSERT(declaration);
     TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode();
@@ -1868,6 +1899,32 @@
     return block;
 }
 
+TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
+                                      TIntermNodePair code,
+                                      const TSourceLoc &loc)
+{
+    checkIsScalarBool(loc, cond);
+
+    // For compile time constant conditions, prune the code now.
+    if (cond->getAsConstantUnion())
+    {
+        if (cond->getAsConstantUnion()->getBConst(0) == true)
+        {
+            return TIntermediate::EnsureBlock(code.node1);
+        }
+        else
+        {
+            return TIntermediate::EnsureBlock(code.node2);
+        }
+    }
+
+    TIntermIfElse *node = new TIntermIfElse(cond, TIntermediate::EnsureBlock(code.node1),
+                                            TIntermediate::EnsureBlock(code.node2));
+    node->setLine(loc);
+
+    return node;
+}
+
 void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
 {
     checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
@@ -2514,6 +2571,25 @@
     mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
 }
 
+void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision,
+                                                   const TPublicType &type,
+                                                   const TSourceLoc &loc)
+{
+    if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) &&
+        !getFragmentPrecisionHigh())
+    {
+        error(loc, "precision is not supported in fragment shader", "highp");
+    }
+
+    if (!CanSetDefaultPrecisionOnType(type))
+    {
+        error(loc, "illegal type argument for default precision qualifier",
+              getBasicString(type.getBasicType()));
+        return;
+    }
+    symbolTable.setDefaultPrecision(type.getBasicType(), precision);
+}
+
 void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
 {
     TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
@@ -2919,8 +2995,20 @@
     return new TFunction(name, new TType(type));
 }
 
+TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc)
+{
+    checkIsNotReserved(loc, *name);
+    const TType *returnType = TCache::getType(EbtVoid, EbpUndefined);
+    return new TFunction(name, returnType);
+}
+
 TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
 {
+    if (mShaderVersion < 300 && publicType.array)
+    {
+        error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only",
+              "[]");
+    }
     if (publicType.isStructSpecifier())
     {
         error(publicType.getLine(), "constructor can't be a structure definition",
@@ -2938,6 +3026,32 @@
     return new TFunction(nullptr, type, EOpConstruct);
 }
 
+TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType,
+                                                   const TString *name,
+                                                   const TSourceLoc &nameLoc)
+{
+    if (publicType.getBasicType() == EbtVoid)
+    {
+        error(nameLoc, "illegal use of type 'void'", name->c_str());
+    }
+    checkIsNotReserved(nameLoc, *name);
+    TType *type      = new TType(publicType);
+    TParameter param = {name, type};
+    return param;
+}
+
+TParameter TParseContext::parseParameterArrayDeclarator(const TString *identifier,
+                                                        const TSourceLoc &identifierLoc,
+                                                        TIntermTyped *arraySize,
+                                                        const TSourceLoc &arrayLoc,
+                                                        TPublicType *type)
+{
+    checkIsValidTypeForArray(arrayLoc, *type);
+    unsigned int size = checkIsValidArraySize(arrayLoc, arraySize);
+    type->setArraySize(size);
+    return parseParameterDeclarator(*type, identifier, identifierLoc);
+}
+
 // This function is used to test for the correctness of the parameters passed to various constructor
 // functions and also convert them to the right datatype if it is allowed and required.
 //
@@ -3695,6 +3809,77 @@
         mShaderVersion);
 }
 
+TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier,
+                                                                     const TSourceLoc &loc)
+{
+    checkIsAtGlobalLevel(loc, getQualifierString(qualifier));
+    return new TStorageQualifierWrapper(qualifier, loc);
+}
+
+TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc)
+{
+    if (getShaderType() == GL_VERTEX_SHADER)
+    {
+        return parseGlobalStorageQualifier(EvqVaryingOut, loc);
+    }
+    return parseGlobalStorageQualifier(EvqVaryingIn, loc);
+}
+
+TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc)
+{
+    if (declaringFunction())
+    {
+        return new TStorageQualifierWrapper(EvqIn, loc);
+    }
+    if (getShaderType() == GL_FRAGMENT_SHADER)
+    {
+        if (mShaderVersion < 300)
+        {
+            error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
+        }
+        return new TStorageQualifierWrapper(EvqFragmentIn, loc);
+    }
+    if (getShaderType() == GL_VERTEX_SHADER)
+    {
+        if (mShaderVersion < 300 && !isMultiviewExtensionEnabled())
+        {
+            error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
+        }
+        return new TStorageQualifierWrapper(EvqVertexIn, loc);
+    }
+    return new TStorageQualifierWrapper(EvqComputeIn, loc);
+}
+
+TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc)
+{
+    if (declaringFunction())
+    {
+        return new TStorageQualifierWrapper(EvqOut, loc);
+    }
+    if (mShaderVersion < 300)
+    {
+        error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
+    }
+    if (getShaderType() != GL_VERTEX_SHADER && getShaderType() != GL_FRAGMENT_SHADER)
+    {
+        error(loc, "storage qualifier supported in vertex and fragment shaders only", "out");
+    }
+    if (getShaderType() == GL_VERTEX_SHADER)
+    {
+        return new TStorageQualifierWrapper(EvqVertexOut, loc);
+    }
+    return new TStorageQualifierWrapper(EvqFragmentOut, loc);
+}
+
+TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc)
+{
+    if (!declaringFunction())
+    {
+        error(loc, "invalid qualifier: can be only used with function parameters", "inout");
+    }
+    return new TStorageQualifierWrapper(EvqInOut, loc);
+}
+
 TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
                                                      TLayoutQualifier rightQualifier,
                                                      const TSourceLoc &rightQualifierLocation)
@@ -3703,6 +3888,27 @@
                                     mDiagnostics);
 }
 
+TField *TParseContext::parseStructDeclarator(TString *identifier, const TSourceLoc &loc)
+{
+    checkIsNotReserved(loc, *identifier);
+    TType *type = new TType(EbtVoid, EbpUndefined);
+    return new TField(type, identifier, loc);
+}
+
+TField *TParseContext::parseStructArrayDeclarator(TString *identifier,
+                                                  const TSourceLoc &loc,
+                                                  TIntermTyped *arraySize,
+                                                  const TSourceLoc &arraySizeLoc)
+{
+    checkIsNotReserved(loc, *identifier);
+
+    TType *type       = new TType(EbtVoid, EbpUndefined);
+    unsigned int size = checkIsValidArraySize(arraySizeLoc, arraySize);
+    type->setArraySize(size);
+
+    return new TField(type, identifier, loc);
+}
+
 TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
                                                    const TFieldList *newlyAddedFields,
                                                    const TSourceLoc &location)
@@ -3837,9 +4043,7 @@
     }
 
     TTypeSpecifierNonArray typeSpecifierNonArray;
-    typeSpecifierNonArray.initialize(EbtStruct, structLine);
-    typeSpecifierNonArray.userDef           = structureType;
-    typeSpecifierNonArray.isStructSpecifier = true;
+    typeSpecifierNonArray.initializeStruct(structureType, true, structLine);
     exitStructDeclaration();
 
     return typeSpecifierNonArray;
@@ -3979,6 +4183,7 @@
 
 TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
 {
+    ASSERT(op != EOpNull);
     TIntermTyped *node = createUnaryMath(op, child, loc);
     if (node == nullptr)
     {
@@ -4397,6 +4602,7 @@
                                        TIntermTyped *right,
                                        const TSourceLoc &loc)
 {
+    checkCanBeLValue(loc, "assign", left);
     TIntermTyped *node = createAssign(op, left, right, loc);
     if (node == nullptr)
     {
@@ -4447,28 +4653,39 @@
                 error(loc, "non-void function must return a value", "return");
             }
             break;
+        case EOpKill:
+            if (mShaderType != GL_FRAGMENT_SHADER)
+            {
+                error(loc, "discard supported in fragment shaders only", "discard");
+            }
+            break;
         default:
-            // No checks for discard
+            UNREACHABLE();
             break;
     }
-    return intermediate.addBranch(op, loc);
+    return addBranch(op, nullptr, loc);
 }
 
 TIntermBranch *TParseContext::addBranch(TOperator op,
-                                        TIntermTyped *returnValue,
+                                        TIntermTyped *expression,
                                         const TSourceLoc &loc)
 {
-    ASSERT(op == EOpReturn);
-    mFunctionReturnsValue = true;
-    if (mCurrentFunctionType->getBasicType() == EbtVoid)
+    if (expression != nullptr)
     {
-        error(loc, "void function cannot return a value", "return");
+        ASSERT(op == EOpReturn);
+        mFunctionReturnsValue = true;
+        if (mCurrentFunctionType->getBasicType() == EbtVoid)
+        {
+            error(loc, "void function cannot return a value", "return");
+        }
+        else if (*mCurrentFunctionType != expression->getType())
+        {
+            error(loc, "function return is not matching type:", "return");
+        }
     }
-    else if (*mCurrentFunctionType != returnValue->getType())
-    {
-        error(loc, "function return is not matching type:", "return");
-    }
-    return intermediate.addBranch(op, returnValue, loc);
+    TIntermBranch *node = new TIntermBranch(op, expression);
+    node->setLine(loc);
+    return node;
 }
 
 void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index d0d7ed5..a7fe95d 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -193,6 +193,10 @@
                          TIntermNode *body,
                          const TSourceLoc &loc);
 
+    // For "if" test nodes. There are three children: a condition, a true path, and a false path.
+    // The two paths are in TIntermNodePair code.
+    TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &loc);
+
     void addFullySpecifiedType(TPublicType *typeSpecifier);
     TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
                                       const TPublicType &typeSpecifier);
@@ -254,7 +258,11 @@
                                   TIntermTyped *initializer,
                                   TIntermDeclaration *declarationOut);
 
+    void parseDefaultPrecisionQualifier(const TPrecision precision,
+                                        const TPublicType &type,
+                                        const TSourceLoc &loc);
     void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder);
+
     TIntermFunctionPrototype *addFunctionPrototypeDeclaration(const TFunction &parsedFunction,
                                                               const TSourceLoc &location);
     TIntermFunctionDefinition *addFunctionDefinition(TIntermFunctionPrototype *functionPrototype,
@@ -267,7 +275,16 @@
     TFunction *parseFunctionHeader(const TPublicType &type,
                                    const TString *name,
                                    const TSourceLoc &location);
+    TFunction *addNonConstructorFunc(const TString *name, const TSourceLoc &loc);
     TFunction *addConstructorFunc(const TPublicType &publicType);
+    TParameter parseParameterDeclarator(const TPublicType &publicType,
+                                        const TString *name,
+                                        const TSourceLoc &nameLoc);
+    TParameter parseParameterArrayDeclarator(const TString *identifier,
+                                             const TSourceLoc &identifierLoc,
+                                             TIntermTyped *arraySize,
+                                             const TSourceLoc &arrayLoc,
+                                             TPublicType *type);
 
     TIntermTyped *addIndexExpression(TIntermTyped *baseExpression,
                                      const TSourceLoc &location,
@@ -277,6 +294,13 @@
                                               const TString &fieldString,
                                               const TSourceLoc &fieldLocation);
 
+    // Parse declarator for a single field
+    TField *parseStructDeclarator(TString *identifier, const TSourceLoc &loc);
+    TField *parseStructArrayDeclarator(TString *identifier,
+                                       const TSourceLoc &loc,
+                                       TIntermTyped *arraySize,
+                                       const TSourceLoc &arraySizeLoc);
+
     TFieldList *combineStructFieldLists(TFieldList *processedFields,
                                         const TFieldList *newlyAddedFields,
                                         const TSourceLoc &location);
@@ -317,6 +341,12 @@
                                           int intValue,
                                           const TSourceLoc &intValueLine);
     TTypeQualifierBuilder *createTypeQualifierBuilder(const TSourceLoc &loc);
+    TStorageQualifierWrapper *parseGlobalStorageQualifier(TQualifier qualifier,
+                                                          const TSourceLoc &loc);
+    TStorageQualifierWrapper *parseVaryingQualifier(const TSourceLoc &loc);
+    TStorageQualifierWrapper *parseInQualifier(const TSourceLoc &loc);
+    TStorageQualifierWrapper *parseOutQualifier(const TSourceLoc &loc);
+    TStorageQualifierWrapper *parseInOutQualifier(const TSourceLoc &loc);
     TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier,
                                           TLayoutQualifier rightQualifier,
                                           const TSourceLoc &rightQualifierLocation);
@@ -351,7 +381,7 @@
     TIntermTyped *addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
 
     TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
-    TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
+    TIntermBranch *addBranch(TOperator op, TIntermTyped *expression, const TSourceLoc &loc);
 
     void checkTextureOffsetConst(TIntermAggregate *functionCall);
     void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall);
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index e76768f..48c2dfe 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -130,8 +130,8 @@
     TConstParameter(const TString *n, TType *t) = delete;
     TConstParameter(TString *n, const TType *t) = delete;
 
-    const TString *name;
-    const TType *type;
+    const TString *const name;
+    const TType *const type;
 };
 
 // The function sub-class of symbols and the parser will need to
@@ -150,7 +150,7 @@
         return TConstParameter(constName, constType);
     }
 
-    TString *name;
+    const TString *name;
     TType *type;
 };
 
@@ -446,18 +446,11 @@
 
     void dump(TInfoSink &infoSink) const;
 
-    bool setDefaultPrecision(const TPublicType &type, TPrecision prec)
+    void setDefaultPrecision(TBasicType type, TPrecision prec)
     {
-        if (!SupportsPrecision(type.getBasicType()))
-            return false;
-        if (type.getBasicType() == EbtUInt)
-            return false;  // ESSL 3.00.4 section 4.5.4
-        if (type.isAggregate())
-            return false;  // Not allowed to set for aggregate types
         int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
         // Uses map operator [], overwrites the current value
-        (*precisionStack[indexOfLastElement])[type.getBasicType()] = prec;
-        return true;
+        (*precisionStack[indexOfLastElement])[type] = prec;
     }
 
     // Searches down the precisionStack for a precision qualifier
diff --git a/src/compiler/translator/Types.h b/src/compiler/translator/Types.h
index 6a1471f..12da0ca 100644
--- a/src/compiler/translator/Types.h
+++ b/src/compiler/translator/Types.h
@@ -242,9 +242,9 @@
     {
     }
     explicit TType(const TPublicType &p);
-    explicit TType(TStructure *userDef, TPrecision p = EbpUndefined)
+    explicit TType(TStructure *userDef)
         : type(EbtStruct),
-          precision(p),
+          precision(EbpUndefined),
           qualifier(EvqTemporary),
           invariant(false),
           memoryQualifier(TMemoryQualifier::create()),
@@ -525,16 +525,27 @@
     // true if the type was defined by a struct specifier rather than a reference to a type name.
     bool isStructSpecifier;
 
-    void initialize(TBasicType bt, const TSourceLoc &ln)
+    void initialize(TBasicType aType, const TSourceLoc &aLine)
     {
-        type              = bt;
+        ASSERT(aType != EbtStruct);
+        type              = aType;
         primarySize       = 1;
         secondarySize     = 1;
         userDef           = nullptr;
-        line              = ln;
+        line              = aLine;
         isStructSpecifier = false;
     }
 
+    void initializeStruct(TType *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine)
+    {
+        type              = EbtStruct;
+        primarySize       = 1;
+        secondarySize     = 1;
+        userDef           = aUserDef;
+        line              = aLine;
+        isStructSpecifier = aIsStructSpecifier;
+    }
+
     void setAggregate(unsigned char size) { primarySize = size; }
 
     void setMatrix(unsigned char columns, unsigned char rows)
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index 4be7673..2e48f4a 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -123,49 +123,37 @@
 
 #define VERTEX_ONLY(S, L) {  \
     if (context->getShaderType() != GL_VERTEX_SHADER) {  \
-        context->error(L, " supported in vertex shaders only ", S);  \
-    }  \
-}
-
-#define FRAG_ONLY(S, L) {  \
-    if (context->getShaderType() != GL_FRAGMENT_SHADER) {  \
-        context->error(L, " supported in fragment shaders only ", S);  \
+        context->error(L, " supported in vertex shaders only", S);  \
     }  \
 }
 
 #define COMPUTE_ONLY(S, L) {  \
     if (context->getShaderType() != GL_COMPUTE_SHADER) {  \
-        context->error(L, " supported in compute shaders only ", S);  \
-    }  \
-}
-
-#define NON_COMPUTE_ONLY(S, L) {  \
-    if (context->getShaderType() != GL_VERTEX_SHADER && context->getShaderType() != GL_FRAGMENT_SHADER) {  \
-        context->error(L, " supported in vertex and fragment shaders only ", S);  \
+        context->error(L, " supported in compute shaders only", S);  \
     }  \
 }
 
 #define ES2_ONLY(S, L) {  \
     if (context->getShaderVersion() != 100) {  \
-        context->error(L, " supported in GLSL ES 1.00 only ", S);  \
+        context->error(L, " supported in GLSL ES 1.00 only", S);  \
     }  \
 }
 
 #define ES3_OR_NEWER(TOKEN, LINE, REASON) {  \
     if (context->getShaderVersion() < 300) {  \
-        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only ", TOKEN);  \
+        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN);  \
     }  \
 }
 
 #define ES3_OR_NEWER_OR_MULTIVIEW(TOKEN, LINE, REASON) {  \
     if (context->getShaderVersion() < 300 && !context->isMultiviewExtensionEnabled()) {  \
-        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only ", TOKEN);  \
+        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN);  \
     }  \
 }
 
 #define ES3_1_ONLY(TOKEN, LINE, REASON) {  \
     if (context->getShaderVersion() != 310) {  \
-        context->error(LINE, REASON " supported in GLSL ES 3.10 only ", TOKEN);  \
+        context->error(LINE, REASON " supported in GLSL ES 3.10 only", TOKEN);  \
     }  \
 }
 %}
@@ -204,7 +192,7 @@
 %token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
 
 %type <lex> identifier
-%type <interm> assignment_operator unary_operator
+%type <interm.op> assignment_operator unary_operator
 %type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
 %type <interm.intermTypedNode> expression integer_expression assignment_expression
 %type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
@@ -227,7 +215,7 @@
 %type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
 %type <interm> single_declaration init_declarator_list
 
-%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+%type <interm.param> parameter_declaration parameter_declarator parameter_type_specifier
 %type <interm.layoutQualifier> layout_qualifier_id_list layout_qualifier_id
 
 %type <interm.type> fully_specified_type type_specifier
@@ -391,22 +379,13 @@
 
 function_identifier
     : type_specifier_no_prec {
-        if ($1.array) {
-            ES3_OR_NEWER("[]", @1, "array constructor");
-        }
         $$ = context->addConstructorFunc($1);
     }
     | IDENTIFIER {
-        context->checkIsNotReserved(@1, *$1.string);
-        const TType *type = TCache::getType(EbtVoid, EbpUndefined);
-        TFunction *function = new TFunction($1.string, type);
-        $$ = function;
+        $$ = context->addNonConstructorFunc($1.string, @1);
     }
     | FIELD_SELECTION {
-        context->checkIsNotReserved(@1, *$1.string);
-        const TType *type = TCache::getType(EbtVoid, EbpUndefined);
-        TFunction *function = new TFunction($1.string, type);
-        $$ = function;
+        $$ = context->addNonConstructorFunc($1.string, @1);
     }
     ;
 
@@ -421,21 +400,18 @@
         $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1);
     }
     | unary_operator unary_expression {
-        if ($1.op != EOpNull) {
-            $$ = context->addUnaryMath($1.op, $2, @1);
-        } else
-            $$ = $2;
+        $$ = context->addUnaryMath($1, $2, @1);
     }
     ;
 // Grammar Note:  No traditional style type casts.
 
 unary_operator
-    : PLUS  { $$.op = EOpPositive; }
-    | DASH  { $$.op = EOpNegative; }
-    | BANG  { $$.op = EOpLogicalNot; }
+    : PLUS  { $$ = EOpPositive; }
+    | DASH  { $$ = EOpNegative; }
+    | BANG  { $$ = EOpLogicalNot; }
     | TILDE {
         ES3_OR_NEWER("~", @$, "bit-wise operator");
-        $$.op = EOpBitwiseNot;
+        $$ = EOpBitwiseNot;
     }
     ;
 // Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
@@ -557,40 +533,39 @@
 assignment_expression
     : conditional_expression { $$ = $1; }
     | unary_expression assignment_operator assignment_expression {
-        context->checkCanBeLValue(@2, "assign", $1);
-        $$ = context->addAssign($2.op, $1, $3, @2);
+        $$ = context->addAssign($2, $1, $3, @2);
     }
     ;
 
 assignment_operator
-    : EQUAL        { $$.op = EOpAssign; }
-    | MUL_ASSIGN   { $$.op = EOpMulAssign; }
-    | DIV_ASSIGN   { $$.op = EOpDivAssign; }
+    : EQUAL        { $$ = EOpAssign; }
+    | MUL_ASSIGN   { $$ = EOpMulAssign; }
+    | DIV_ASSIGN   { $$ = EOpDivAssign; }
     | MOD_ASSIGN   {
         ES3_OR_NEWER("%=", @$, "integer modulus operator");
-        $$.op = EOpIModAssign;
+        $$ = EOpIModAssign;
     }
-    | ADD_ASSIGN   { $$.op = EOpAddAssign; }
-    | SUB_ASSIGN   { $$.op = EOpSubAssign; }
+    | ADD_ASSIGN   { $$ = EOpAddAssign; }
+    | SUB_ASSIGN   { $$ = EOpSubAssign; }
     | LEFT_ASSIGN {
         ES3_OR_NEWER("<<=", @$, "bit-wise operator");
-        $$.op = EOpBitShiftLeftAssign;
+        $$ = EOpBitShiftLeftAssign;
     }
     | RIGHT_ASSIGN {
         ES3_OR_NEWER(">>=", @$, "bit-wise operator");
-        $$.op = EOpBitShiftRightAssign;
+        $$ = EOpBitShiftRightAssign;
     }
     | AND_ASSIGN {
         ES3_OR_NEWER("&=", @$, "bit-wise operator");
-        $$.op = EOpBitwiseAndAssign;
+        $$ = EOpBitwiseAndAssign;
     }
     | XOR_ASSIGN {
         ES3_OR_NEWER("^=", @$, "bit-wise operator");
-        $$.op = EOpBitwiseXorAssign;
+        $$ = EOpBitwiseXorAssign;
     }
     | OR_ASSIGN {
         ES3_OR_NEWER("|=", @$, "bit-wise operator");
-        $$.op = EOpBitwiseOrAssign;
+        $$ = EOpBitwiseOrAssign;
     }
     ;
 
@@ -625,13 +600,8 @@
         $$ = $1.intermDeclaration;
     }
     | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
-        if (($2 == EbpHigh) && (context->getShaderType() == GL_FRAGMENT_SHADER) && !context->getFragmentPrecisionHigh()) {
-            context->error(@1, "precision is not supported in fragment shader", "highp");
-        }
-        if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
-            context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.getBasicType()));
-        }
-        $$ = 0;
+        context->parseDefaultPrecisionQualifier($2, $3, @1);
+        $$ = nullptr;
     }
     | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON {
         ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
@@ -647,7 +617,7 @@
     }
     | type_qualifier SEMICOLON {
         context->parseGlobalLayoutQualifier(*$1);
-        $$ = 0;
+        $$ = nullptr;
     }
     | type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant
     {
@@ -676,26 +646,23 @@
     : function_header parameter_declaration {
         // Add the parameter
         $$ = $1;
-        if ($2.param.type->getBasicType() != EbtVoid)
-            $1->addParameter($2.param.turnToConst());
-        else
-            delete $2.param.type;
+        if ($2.type->getBasicType() != EbtVoid)
+        {
+            $1->addParameter($2.turnToConst());
+        }
     }
     | function_header_with_parameters COMMA parameter_declaration {
-        //
+        $$ = $1;
         // Only first parameter of one-parameter functions can be void
         // The check for named parameters not being void is done in parameter_declarator
-        //
-        if ($3.param.type->getBasicType() == EbtVoid) {
-            //
+        if ($3.type->getBasicType() == EbtVoid)
+        {
             // This parameter > first is void
-            //
-            context->error(@2, "cannot be an argument type except for '(void)'", "void");
-            delete $3.param.type;
-        } else {
-            // Add the parameter
-            $$ = $1;
-            $1->addParameter($3.param.turnToConst());
+            context->error(@2, "cannot be a parameter type except for '(void)'", "void");
+        }
+        else
+        {
+            $1->addParameter($3.turnToConst());
         }
     }
     ;
@@ -712,60 +679,36 @@
 parameter_declarator
     // Type + name
     : type_specifier identifier {
-        if ($1.getBasicType() == EbtVoid) {
-            context->error(@2, "illegal use of type 'void'", $2.string->c_str());
-        }
-        context->checkIsNotReserved(@2, *$2.string);
-        TParameter param = {$2.string, new TType($1)};
-        $$.param = param;
+        $$ = context->parseParameterDeclarator($1, $2.string, @2);
     }
     | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
-        // Check that we can make an array out of this type
-        context->checkIsValidTypeForArray(@3, $1);
-
-        context->checkIsNotReserved(@2, *$2.string);
-
-        unsigned int size = context->checkIsValidArraySize(@3, $4);
-
-        $1.setArraySize(size);
-
-        TType* type = new TType($1);
-        TParameter param = { $2.string, type };
-        $$.param = param;
+        $$ = context->parseParameterArrayDeclarator($2.string, @2, $4, @3, &$1);
     }
     ;
 
 parameter_declaration
-    //
-    // The only parameter qualifier a parameter can have are
-    // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
-    //
-
-    //
-    // Type + name
-    //
     : type_qualifier parameter_declarator {
         $$ = $2;
-        context->checkIsParameterQualifierValid(@2, *$1, $2.param.type);
+        context->checkIsParameterQualifierValid(@2, *$1, $2.type);
     }
     | parameter_declarator {
         $$ = $1;
-        $$.param.type->setQualifier(EvqIn);
+        $$.type->setQualifier(EvqIn);
     }
     | type_qualifier parameter_type_specifier {
         $$ = $2;
-        context->checkIsParameterQualifierValid(@2, *$1, $2.param.type);
+        context->checkIsParameterQualifierValid(@2, *$1, $2.type);
     }
     | parameter_type_specifier {
         $$ = $1;
-        $$.param.type->setQualifier(EvqIn);
+        $$.type->setQualifier(EvqIn);
     }
     ;
 
 parameter_type_specifier
     : type_specifier {
         TParameter param = { 0, new TType($1) };
-        $$.param = param;
+        $$ = param;
     }
     ;
 
@@ -889,73 +832,30 @@
     ATTRIBUTE {
         VERTEX_ONLY("attribute", @1);
         ES2_ONLY("attribute", @1);
-        context->checkIsAtGlobalLevel(@1, "attribute");
-        $$ = new TStorageQualifierWrapper(EvqAttribute, @1);
+        $$ = context->parseGlobalStorageQualifier(EvqAttribute, @1);
     }
     | VARYING {
         ES2_ONLY("varying", @1);
-        context->checkIsAtGlobalLevel(@1, "varying");
-        if (context->getShaderType() == GL_VERTEX_SHADER)
-            $$ = new TStorageQualifierWrapper(EvqVaryingOut, @1);
-        else
-            $$ = new TStorageQualifierWrapper(EvqVaryingIn, @1);
+        $$ = context->parseVaryingQualifier(@1);
     }
     | CONST_QUAL {
         $$ = new TStorageQualifierWrapper(EvqConst, @1);
     }
     | IN_QUAL {
-        if (context->declaringFunction())
-        {
-            $$ = new TStorageQualifierWrapper(EvqIn, @1);
-        }
-        else if (context->getShaderType() == GL_FRAGMENT_SHADER)
-        {
-            ES3_OR_NEWER("in", @1, "storage qualifier");
-            $$ = new TStorageQualifierWrapper(EvqFragmentIn, @1);
-        }
-        else if (context->getShaderType() == GL_VERTEX_SHADER)
-        {
-            ES3_OR_NEWER_OR_MULTIVIEW("in", @1, "storage qualifier");
-            $$ = new TStorageQualifierWrapper(EvqVertexIn, @1);
-        }
-        else
-        {
-            $$ = new TStorageQualifierWrapper(EvqComputeIn, @1);
-        }
+        $$ = context->parseInQualifier(@1);
     }
     | OUT_QUAL {
-        if (context->declaringFunction())
-        {
-            $$ = new TStorageQualifierWrapper(EvqOut, @1);
-        }
-        else
-        {
-            ES3_OR_NEWER("out", @1, "storage qualifier");
-            NON_COMPUTE_ONLY("out", @1);
-            if (context->getShaderType() == GL_FRAGMENT_SHADER)
-            {
-                $$ = new TStorageQualifierWrapper(EvqFragmentOut, @1);
-            }
-            else
-            {
-                $$ = new TStorageQualifierWrapper(EvqVertexOut, @1);
-            }
-        }
+        $$ = context->parseOutQualifier(@1);
     }
     | INOUT_QUAL {
-        if (!context->declaringFunction())
-        {
-            context->error(@1, "invalid qualifier: can be only used with function parameters", "inout");
-        }
-        $$ = new TStorageQualifierWrapper(EvqInOut, @1);
+        $$ = context->parseInOutQualifier(@1);
     }
     | CENTROID {
         ES3_OR_NEWER("centroid", @1, "storage qualifier");
         $$ = new TStorageQualifierWrapper(EvqCentroid, @1);
     }
     | UNIFORM {
-        context->checkIsAtGlobalLevel(@1, "uniform");
-        $$ = new TStorageQualifierWrapper(EvqUniform, @1);
+        $$ = context->parseGlobalStorageQualifier(EvqUniform, @1);
     }
     | READONLY {
         $$ = new TMemoryQualifierWrapper(EvqReadOnly, @1);
@@ -973,9 +873,8 @@
         $$ = new TMemoryQualifierWrapper(EvqVolatile, @1);
     }
     | SHARED {
-        context->checkIsAtGlobalLevel(@1, "shared");
         COMPUTE_ONLY("shared", @1);
-        $$ = new TStorageQualifierWrapper(EvqShared, @1);
+        $$ = context->parseGlobalStorageQualifier(EvqShared, @1);
     }
     ;
 
@@ -1270,13 +1169,9 @@
         $$.initialize(EbtAtomicCounter, @1);
     }
     | TYPE_NAME {
-        //
-        // This is for user defined type names.  The lexical phase looked up the
-        // type.
-        //
+        // This is for user defined type names. The lexical phase looked up the type.
         TType& structure = static_cast<TVariable*>($1.symbol)->getType();
-        $$.initialize(EbtStruct, @1);
-        $$.userDef = &structure;
+        $$.initializeStruct(&structure, false, @1);
     }
     ;
 
@@ -1320,19 +1215,10 @@
 
 struct_declarator
     : identifier {
-        context->checkIsNotReserved(@1, *$1.string);
-
-        TType* type = new TType(EbtVoid, EbpUndefined);
-        $$ = new TField(type, $1.string, @1);
+        $$ = context->parseStructDeclarator($1.string, @1);
     }
     | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
-        context->checkIsNotReserved(@1, *$1.string);
-
-        TType* type = new TType(EbtVoid, EbpUndefined);
-        unsigned int size = context->checkIsValidArraySize(@3, $3);
-        type->setArraySize(size);
-
-        $$ = new TField(type, $1.string, @1);
+        $$ = context->parseStructArrayDeclarator($1.string, @1, $3, @3);
     }
     ;
 
@@ -1364,9 +1250,7 @@
 compound_statement
     : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
     | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
-        if ($3 != 0) {
-            $3->setLine(@$);
-        }
+        $3->setLine(@$);
         $$ = $3;
     }
     ;
@@ -1384,12 +1268,10 @@
 compound_statement_no_new_scope
     // Statement that doesn't create a new scope, for selection_statement, iteration_statement
     : LEFT_BRACE RIGHT_BRACE {
-        $$ = 0;
+        $$ = nullptr;
     }
     | LEFT_BRACE statement_list RIGHT_BRACE {
-        if ($2) {
-            $2->setLine(@$);
-        }
+        $2->setLine(@$);
         $$ = $2;
     }
     ;
@@ -1397,7 +1279,6 @@
 statement_list
     : statement {
         $$ = new TIntermBlock();
-        $$->setLine(@$);
         $$->appendStatement($1);
     }
     | statement_list statement {
@@ -1408,13 +1289,12 @@
 
 expression_statement
     : SEMICOLON  { $$ = 0; }
-    | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
+    | expression SEMICOLON  { $$ = $1; }
     ;
 
 selection_statement
     : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
-        context->checkIsScalarBool(@1, $3);
-        $$ = context->intermediate.addIfElse($3, $5, @1);
+        $$ = context->addIfElse($3, $5, @1);
     }
     ;
 
@@ -1425,7 +1305,7 @@
     }
     | statement_with_scope {
         $$.node1 = $1;
-        $$.node2 = 0;
+        $$.node2 = nullptr;
     }
     ;
 
@@ -1446,7 +1326,6 @@
     ;
 
 condition
-    // In 1996 c++ draft, conditions can include single declarations
     : expression {
         $$ = $1;
         context->checkIsScalarBool($1->getLine(), $1);
@@ -1463,8 +1342,6 @@
         context->decrLoopNestingLevel();
     }
     | DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
-        context->checkIsScalarBool(@8, $6);
-
         $$ = context->addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
         context->decrLoopNestingLevel();
     }
@@ -1518,7 +1395,6 @@
         $$ = context->addBranch(EOpReturn, $2, @1);
     }
     | DISCARD SEMICOLON {
-        FRAG_ONLY("discard", @1);
         $$ = context->addBranch(EOpKill, @1);
     }
     ;
diff --git a/src/compiler/translator/glslang_tab.cpp b/src/compiler/translator/glslang_tab.cpp
index 1eef14c..e773a61 100644
--- a/src/compiler/translator/glslang_tab.cpp
+++ b/src/compiler/translator/glslang_tab.cpp
@@ -392,49 +392,37 @@
 
 #define VERTEX_ONLY(S, L) {  \
     if (context->getShaderType() != GL_VERTEX_SHADER) {  \
-        context->error(L, " supported in vertex shaders only ", S);  \
-    }  \
-}
-
-#define FRAG_ONLY(S, L) {  \
-    if (context->getShaderType() != GL_FRAGMENT_SHADER) {  \
-        context->error(L, " supported in fragment shaders only ", S);  \
+        context->error(L, " supported in vertex shaders only", S);  \
     }  \
 }
 
 #define COMPUTE_ONLY(S, L) {  \
     if (context->getShaderType() != GL_COMPUTE_SHADER) {  \
-        context->error(L, " supported in compute shaders only ", S);  \
-    }  \
-}
-
-#define NON_COMPUTE_ONLY(S, L) {  \
-    if (context->getShaderType() != GL_VERTEX_SHADER && context->getShaderType() != GL_FRAGMENT_SHADER) {  \
-        context->error(L, " supported in vertex and fragment shaders only ", S);  \
+        context->error(L, " supported in compute shaders only", S);  \
     }  \
 }
 
 #define ES2_ONLY(S, L) {  \
     if (context->getShaderVersion() != 100) {  \
-        context->error(L, " supported in GLSL ES 1.00 only ", S);  \
+        context->error(L, " supported in GLSL ES 1.00 only", S);  \
     }  \
 }
 
 #define ES3_OR_NEWER(TOKEN, LINE, REASON) {  \
     if (context->getShaderVersion() < 300) {  \
-        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only ", TOKEN);  \
+        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN);  \
     }  \
 }
 
 #define ES3_OR_NEWER_OR_MULTIVIEW(TOKEN, LINE, REASON) {  \
     if (context->getShaderVersion() < 300 && !context->isMultiviewExtensionEnabled()) {  \
-        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only ", TOKEN);  \
+        context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN);  \
     }  \
 }
 
 #define ES3_1_ONLY(TOKEN, LINE, REASON) {  \
     if (context->getShaderVersion() != 310) {  \
-        context->error(LINE, REASON " supported in GLSL ES 3.10 only ", TOKEN);  \
+        context->error(LINE, REASON " supported in GLSL ES 3.10 only", TOKEN);  \
     }  \
 }
 
@@ -752,36 +740,36 @@
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   256,   256,   257,   260,   270,   273,   278,   283,   288,
-     293,   301,   307,   310,   313,   316,   319,   322,   328,   335,
-     341,   345,   353,   356,   362,   366,   373,   378,   385,   393,
-     399,   405,   414,   417,   420,   423,   433,   434,   435,   436,
-     444,   445,   448,   451,   458,   459,   462,   468,   469,   473,
-     480,   481,   484,   487,   490,   496,   497,   500,   506,   507,
-     514,   515,   522,   523,   530,   531,   537,   538,   544,   545,
-     551,   552,   558,   559,   566,   567,   568,   569,   573,   574,
-     575,   579,   583,   587,   591,   598,   601,   607,   614,   621,
-     624,   627,   636,   640,   644,   648,   652,   659,   666,   669,
-     676,   684,   704,   714,   722,   747,   751,   755,   759,   766,
-     773,   776,   780,   784,   789,   794,   801,   805,   809,   813,
-     818,   823,   830,   834,   840,   843,   849,   853,   860,   866,
-     870,   874,   877,   880,   889,   895,   903,   906,   926,   945,
-     952,   956,   960,   963,   966,   969,   972,   975,   983,   990,
-     993,   996,  1002,  1009,  1012,  1018,  1021,  1024,  1027,  1033,
-    1036,  1041,  1052,  1055,  1058,  1061,  1064,  1067,  1071,  1075,
-    1079,  1083,  1087,  1091,  1095,  1099,  1103,  1107,  1111,  1115,
-    1119,  1123,  1127,  1131,  1135,  1139,  1143,  1147,  1151,  1157,
-    1160,  1163,  1166,  1169,  1172,  1175,  1178,  1181,  1184,  1187,
-    1190,  1193,  1196,  1199,  1202,  1205,  1208,  1211,  1218,  1224,
-    1230,  1233,  1236,  1239,  1242,  1245,  1248,  1251,  1254,  1257,
-    1260,  1263,  1266,  1269,  1272,  1284,  1284,  1287,  1287,  1293,
-    1296,  1302,  1305,  1312,  1316,  1322,  1328,  1340,  1344,  1348,
-    1349,  1355,  1356,  1357,  1358,  1359,  1360,  1361,  1365,  1366,
-    1366,  1366,  1375,  1376,  1380,  1380,  1381,  1381,  1386,  1389,
-    1398,  1403,  1410,  1411,  1415,  1422,  1426,  1433,  1433,  1440,
-    1443,  1450,  1454,  1460,  1460,  1465,  1465,  1471,  1471,  1479,
-    1482,  1488,  1491,  1497,  1501,  1508,  1511,  1514,  1517,  1520,
-    1529,  1535,  1541,  1544,  1550,  1550
+       0,   244,   244,   245,   248,   258,   261,   266,   271,   276,
+     281,   289,   295,   298,   301,   304,   307,   310,   316,   323,
+     329,   333,   341,   344,   350,   354,   361,   366,   373,   381,
+     384,   387,   393,   396,   399,   402,   409,   410,   411,   412,
+     420,   421,   424,   427,   434,   435,   438,   444,   445,   449,
+     456,   457,   460,   463,   466,   472,   473,   476,   482,   483,
+     490,   491,   498,   499,   506,   507,   513,   514,   520,   521,
+     527,   528,   534,   535,   541,   542,   543,   544,   548,   549,
+     550,   554,   558,   562,   566,   573,   576,   582,   589,   596,
+     599,   602,   606,   610,   614,   618,   622,   629,   636,   639,
+     646,   654,   671,   681,   684,   690,   694,   698,   702,   709,
+     716,   719,   723,   727,   732,   737,   744,   748,   752,   756,
+     761,   766,   773,   777,   783,   786,   792,   796,   803,   809,
+     813,   817,   820,   823,   832,   837,   841,   844,   847,   850,
+     853,   857,   860,   863,   866,   869,   872,   875,   882,   889,
+     892,   895,   901,   908,   911,   917,   920,   923,   926,   932,
+     935,   940,   951,   954,   957,   960,   963,   966,   970,   974,
+     978,   982,   986,   990,   994,   998,  1002,  1006,  1010,  1014,
+    1018,  1022,  1026,  1030,  1034,  1038,  1042,  1046,  1050,  1056,
+    1059,  1062,  1065,  1068,  1071,  1074,  1077,  1080,  1083,  1086,
+    1089,  1092,  1095,  1098,  1101,  1104,  1107,  1110,  1117,  1123,
+    1129,  1132,  1135,  1138,  1141,  1144,  1147,  1150,  1153,  1156,
+    1159,  1162,  1165,  1168,  1171,  1179,  1179,  1182,  1182,  1188,
+    1191,  1197,  1200,  1207,  1211,  1217,  1220,  1226,  1230,  1234,
+    1235,  1241,  1242,  1243,  1244,  1245,  1246,  1247,  1251,  1252,
+    1252,  1252,  1259,  1260,  1264,  1264,  1265,  1265,  1270,  1273,
+    1280,  1284,  1291,  1292,  1296,  1302,  1306,  1313,  1313,  1320,
+    1323,  1329,  1333,  1339,  1339,  1344,  1344,  1348,  1348,  1356,
+    1359,  1365,  1368,  1374,  1378,  1385,  1388,  1391,  1394,  1397,
+    1405,  1411,  1417,  1420,  1426,  1426
 };
 #endif
 
@@ -2759,9 +2747,6 @@
   case 29:
 
     {
-        if ((yyvsp[0].interm.type).array) {
-            ES3_OR_NEWER("[]", (yylsp[0]), "array constructor");
-        }
         (yyval.interm.function) = context->addConstructorFunc((yyvsp[0].interm.type));
     }
 
@@ -2770,10 +2755,7 @@
   case 30:
 
     {
-        context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
-        const TType *type = TCache::getType(EbtVoid, EbpUndefined);
-        TFunction *function = new TFunction((yyvsp[0].lex).string, type);
-        (yyval.interm.function) = function;
+        (yyval.interm.function) = context->addNonConstructorFunc((yyvsp[0].lex).string, (yylsp[0]));
     }
 
     break;
@@ -2781,10 +2763,7 @@
   case 31:
 
     {
-        context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
-        const TType *type = TCache::getType(EbtVoid, EbpUndefined);
-        TFunction *function = new TFunction((yyvsp[0].lex).string, type);
-        (yyval.interm.function) = function;
+        (yyval.interm.function) = context->addNonConstructorFunc((yyvsp[0].lex).string, (yylsp[0]));
     }
 
     break;
@@ -2816,29 +2795,26 @@
   case 35:
 
     {
-        if ((yyvsp[-1].interm).op != EOpNull) {
-            (yyval.interm.intermTypedNode) = context->addUnaryMath((yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        } else
-            (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
+        (yyval.interm.intermTypedNode) = context->addUnaryMath((yyvsp[-1].interm.op), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
 
   case 36:
 
-    { (yyval.interm).op = EOpPositive; }
+    { (yyval.interm.op) = EOpPositive; }
 
     break;
 
   case 37:
 
-    { (yyval.interm).op = EOpNegative; }
+    { (yyval.interm.op) = EOpNegative; }
 
     break;
 
   case 38:
 
-    { (yyval.interm).op = EOpLogicalNot; }
+    { (yyval.interm.op) = EOpLogicalNot; }
 
     break;
 
@@ -2846,7 +2822,7 @@
 
     {
         ES3_OR_NEWER("~", (yyloc), "bit-wise operator");
-        (yyval.interm).op = EOpBitwiseNot;
+        (yyval.interm.op) = EOpBitwiseNot;
     }
 
     break;
@@ -3098,27 +3074,26 @@
   case 73:
 
     {
-        context->checkCanBeLValue((yylsp[-1]), "assign", (yyvsp[-2].interm.intermTypedNode));
-        (yyval.interm.intermTypedNode) = context->addAssign((yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
+        (yyval.interm.intermTypedNode) = context->addAssign((yyvsp[-1].interm.op), (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
 
   case 74:
 
-    { (yyval.interm).op = EOpAssign; }
+    { (yyval.interm.op) = EOpAssign; }
 
     break;
 
   case 75:
 
-    { (yyval.interm).op = EOpMulAssign; }
+    { (yyval.interm.op) = EOpMulAssign; }
 
     break;
 
   case 76:
 
-    { (yyval.interm).op = EOpDivAssign; }
+    { (yyval.interm.op) = EOpDivAssign; }
 
     break;
 
@@ -3126,20 +3101,20 @@
 
     {
         ES3_OR_NEWER("%=", (yyloc), "integer modulus operator");
-        (yyval.interm).op = EOpIModAssign;
+        (yyval.interm.op) = EOpIModAssign;
     }
 
     break;
 
   case 78:
 
-    { (yyval.interm).op = EOpAddAssign; }
+    { (yyval.interm.op) = EOpAddAssign; }
 
     break;
 
   case 79:
 
-    { (yyval.interm).op = EOpSubAssign; }
+    { (yyval.interm.op) = EOpSubAssign; }
 
     break;
 
@@ -3147,7 +3122,7 @@
 
     {
         ES3_OR_NEWER("<<=", (yyloc), "bit-wise operator");
-        (yyval.interm).op = EOpBitShiftLeftAssign;
+        (yyval.interm.op) = EOpBitShiftLeftAssign;
     }
 
     break;
@@ -3156,7 +3131,7 @@
 
     {
         ES3_OR_NEWER(">>=", (yyloc), "bit-wise operator");
-        (yyval.interm).op = EOpBitShiftRightAssign;
+        (yyval.interm.op) = EOpBitShiftRightAssign;
     }
 
     break;
@@ -3165,7 +3140,7 @@
 
     {
         ES3_OR_NEWER("&=", (yyloc), "bit-wise operator");
-        (yyval.interm).op = EOpBitwiseAndAssign;
+        (yyval.interm.op) = EOpBitwiseAndAssign;
     }
 
     break;
@@ -3174,7 +3149,7 @@
 
     {
         ES3_OR_NEWER("^=", (yyloc), "bit-wise operator");
-        (yyval.interm).op = EOpBitwiseXorAssign;
+        (yyval.interm.op) = EOpBitwiseXorAssign;
     }
 
     break;
@@ -3183,7 +3158,7 @@
 
     {
         ES3_OR_NEWER("|=", (yyloc), "bit-wise operator");
-        (yyval.interm).op = EOpBitwiseOrAssign;
+        (yyval.interm.op) = EOpBitwiseOrAssign;
     }
 
     break;
@@ -3241,13 +3216,8 @@
   case 91:
 
     {
-        if (((yyvsp[-2].interm.precision) == EbpHigh) && (context->getShaderType() == GL_FRAGMENT_SHADER) && !context->getFragmentPrecisionHigh()) {
-            context->error((yylsp[-3]), "precision is not supported in fragment shader", "highp");
-        }
-        if (!context->symbolTable.setDefaultPrecision( (yyvsp[-1].interm.type), (yyvsp[-2].interm.precision) )) {
-            context->error((yylsp[-3]), "illegal type argument for default precision qualifier", getBasicString((yyvsp[-1].interm.type).getBasicType()));
-        }
-        (yyval.interm.intermNode) = 0;
+        context->parseDefaultPrecisionQualifier((yyvsp[-2].interm.precision), (yyvsp[-1].interm.type), (yylsp[-3]));
+        (yyval.interm.intermNode) = nullptr;
     }
 
     break;
@@ -3283,7 +3253,7 @@
 
     {
         context->parseGlobalLayoutQualifier(*(yyvsp[-1].interm.typeQualifierBuilder));
-        (yyval.interm.intermNode) = 0;
+        (yyval.interm.intermNode) = nullptr;
     }
 
     break;
@@ -3326,10 +3296,10 @@
     {
         // Add the parameter
         (yyval.interm.function) = (yyvsp[-1].interm.function);
-        if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid)
-            (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param.turnToConst());
-        else
-            delete (yyvsp[0].interm).param.type;
+        if ((yyvsp[0].interm.param).type->getBasicType() != EbtVoid)
+        {
+            (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm.param).turnToConst());
+        }
     }
 
     break;
@@ -3337,20 +3307,17 @@
   case 101:
 
     {
-        //
+        (yyval.interm.function) = (yyvsp[-2].interm.function);
         // Only first parameter of one-parameter functions can be void
         // The check for named parameters not being void is done in parameter_declarator
-        //
-        if ((yyvsp[0].interm).param.type->getBasicType() == EbtVoid) {
-            //
+        if ((yyvsp[0].interm.param).type->getBasicType() == EbtVoid)
+        {
             // This parameter > first is void
-            //
-            context->error((yylsp[-1]), "cannot be an argument type except for '(void)'", "void");
-            delete (yyvsp[0].interm).param.type;
-        } else {
-            // Add the parameter
-            (yyval.interm.function) = (yyvsp[-2].interm.function);
-            (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param.turnToConst());
+            context->error((yylsp[-1]), "cannot be a parameter type except for '(void)'", "void");
+        }
+        else
+        {
+            (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm.param).turnToConst());
         }
     }
 
@@ -3370,12 +3337,7 @@
   case 103:
 
     {
-        if ((yyvsp[-1].interm.type).getBasicType() == EbtVoid) {
-            context->error((yylsp[0]), "illegal use of type 'void'", (yyvsp[0].lex).string->c_str());
-        }
-        context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
-        TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))};
-        (yyval.interm).param = param;
+        (yyval.interm.param) = context->parseParameterDeclarator((yyvsp[-1].interm.type), (yyvsp[0].lex).string, (yylsp[0]));
     }
 
     break;
@@ -3383,18 +3345,7 @@
   case 104:
 
     {
-        // Check that we can make an array out of this type
-        context->checkIsValidTypeForArray((yylsp[-2]), (yyvsp[-4].interm.type));
-
-        context->checkIsNotReserved((yylsp[-3]), *(yyvsp[-3].lex).string);
-
-        unsigned int size = context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode));
-
-        (yyvsp[-4].interm.type).setArraySize(size);
-
-        TType* type = new TType((yyvsp[-4].interm.type));
-        TParameter param = { (yyvsp[-3].lex).string, type };
-        (yyval.interm).param = param;
+        (yyval.interm.param) = context->parseParameterArrayDeclarator((yyvsp[-3].lex).string, (yylsp[-3]), (yyvsp[-1].interm.intermTypedNode), (yylsp[-2]), &(yyvsp[-4].interm.type));
     }
 
     break;
@@ -3402,8 +3353,8 @@
   case 105:
 
     {
-        (yyval.interm) = (yyvsp[0].interm);
-        context->checkIsParameterQualifierValid((yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm).param.type);
+        (yyval.interm.param) = (yyvsp[0].interm.param);
+        context->checkIsParameterQualifierValid((yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm.param).type);
     }
 
     break;
@@ -3411,8 +3362,8 @@
   case 106:
 
     {
-        (yyval.interm) = (yyvsp[0].interm);
-        (yyval.interm).param.type->setQualifier(EvqIn);
+        (yyval.interm.param) = (yyvsp[0].interm.param);
+        (yyval.interm.param).type->setQualifier(EvqIn);
     }
 
     break;
@@ -3420,8 +3371,8 @@
   case 107:
 
     {
-        (yyval.interm) = (yyvsp[0].interm);
-        context->checkIsParameterQualifierValid((yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm).param.type);
+        (yyval.interm.param) = (yyvsp[0].interm.param);
+        context->checkIsParameterQualifierValid((yylsp[0]), *(yyvsp[-1].interm.typeQualifierBuilder), (yyvsp[0].interm.param).type);
     }
 
     break;
@@ -3429,8 +3380,8 @@
   case 108:
 
     {
-        (yyval.interm) = (yyvsp[0].interm);
-        (yyval.interm).param.type->setQualifier(EvqIn);
+        (yyval.interm.param) = (yyvsp[0].interm.param);
+        (yyval.interm.param).type->setQualifier(EvqIn);
     }
 
     break;
@@ -3439,7 +3390,7 @@
 
     {
         TParameter param = { 0, new TType((yyvsp[0].interm.type)) };
-        (yyval.interm).param = param;
+        (yyval.interm.param) = param;
     }
 
     break;
@@ -3662,8 +3613,7 @@
     {
         VERTEX_ONLY("attribute", (yylsp[0]));
         ES2_ONLY("attribute", (yylsp[0]));
-        context->checkIsAtGlobalLevel((yylsp[0]), "attribute");
-        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqAttribute, (yylsp[0]));
+        (yyval.interm.qualifierWrapper) = context->parseGlobalStorageQualifier(EvqAttribute, (yylsp[0]));
     }
 
     break;
@@ -3672,11 +3622,7 @@
 
     {
         ES2_ONLY("varying", (yylsp[0]));
-        context->checkIsAtGlobalLevel((yylsp[0]), "varying");
-        if (context->getShaderType() == GL_VERTEX_SHADER)
-            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVaryingOut, (yylsp[0]));
-        else
-            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVaryingIn, (yylsp[0]));
+        (yyval.interm.qualifierWrapper) = context->parseVaryingQualifier((yylsp[0]));
     }
 
     break;
@@ -3692,24 +3638,7 @@
   case 137:
 
     {
-        if (context->declaringFunction())
-        {
-            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqIn, (yylsp[0]));
-        }
-        else if (context->getShaderType() == GL_FRAGMENT_SHADER)
-        {
-            ES3_OR_NEWER("in", (yylsp[0]), "storage qualifier");
-            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqFragmentIn, (yylsp[0]));
-        }
-        else if (context->getShaderType() == GL_VERTEX_SHADER)
-        {
-            ES3_OR_NEWER_OR_MULTIVIEW("in", (yylsp[0]), "storage qualifier");
-            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVertexIn, (yylsp[0]));
-        }
-        else
-        {
-            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqComputeIn, (yylsp[0]));
-        }
+        (yyval.interm.qualifierWrapper) = context->parseInQualifier((yylsp[0]));
     }
 
     break;
@@ -3717,23 +3646,7 @@
   case 138:
 
     {
-        if (context->declaringFunction())
-        {
-            (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqOut, (yylsp[0]));
-        }
-        else
-        {
-            ES3_OR_NEWER("out", (yylsp[0]), "storage qualifier");
-            NON_COMPUTE_ONLY("out", (yylsp[0]));
-            if (context->getShaderType() == GL_FRAGMENT_SHADER)
-            {
-                (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqFragmentOut, (yylsp[0]));
-            }
-            else
-            {
-                (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqVertexOut, (yylsp[0]));
-            }
-        }
+        (yyval.interm.qualifierWrapper) = context->parseOutQualifier((yylsp[0]));
     }
 
     break;
@@ -3741,11 +3654,7 @@
   case 139:
 
     {
-        if (!context->declaringFunction())
-        {
-            context->error((yylsp[0]), "invalid qualifier: can be only used with function parameters", "inout");
-        }
-        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqInOut, (yylsp[0]));
+        (yyval.interm.qualifierWrapper) = context->parseInOutQualifier((yylsp[0]));
     }
 
     break;
@@ -3762,8 +3671,7 @@
   case 141:
 
     {
-        context->checkIsAtGlobalLevel((yylsp[0]), "uniform");
-        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqUniform, (yylsp[0]));
+        (yyval.interm.qualifierWrapper) = context->parseGlobalStorageQualifier(EvqUniform, (yylsp[0]));
     }
 
     break;
@@ -3811,9 +3719,8 @@
   case 147:
 
     {
-        context->checkIsAtGlobalLevel((yylsp[0]), "shared");
         COMPUTE_ONLY("shared", (yylsp[0]));
-        (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqShared, (yylsp[0]));
+        (yyval.interm.qualifierWrapper) = context->parseGlobalStorageQualifier(EvqShared, (yylsp[0]));
     }
 
     break;
@@ -4472,13 +4379,9 @@
   case 224:
 
     {
-        //
-        // This is for user defined type names.  The lexical phase looked up the
-        // type.
-        //
+        // This is for user defined type names. The lexical phase looked up the type.
         TType& structure = static_cast<TVariable*>((yyvsp[0].lex).symbol)->getType();
-        (yyval.interm.typeSpecifierNonArray).initialize(EbtStruct, (yylsp[0]));
-        (yyval.interm.typeSpecifierNonArray).userDef = &structure;
+        (yyval.interm.typeSpecifierNonArray).initializeStruct(&structure, false, (yylsp[0]));
     }
 
     break;
@@ -4564,10 +4467,7 @@
   case 235:
 
     {
-        context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
-
-        TType* type = new TType(EbtVoid, EbpUndefined);
-        (yyval.interm.field) = new TField(type, (yyvsp[0].lex).string, (yylsp[0]));
+        (yyval.interm.field) = context->parseStructDeclarator((yyvsp[0].lex).string, (yylsp[0]));
     }
 
     break;
@@ -4575,13 +4475,7 @@
   case 236:
 
     {
-        context->checkIsNotReserved((yylsp[-3]), *(yyvsp[-3].lex).string);
-
-        TType* type = new TType(EbtVoid, EbpUndefined);
-        unsigned int size = context->checkIsValidArraySize((yylsp[-1]), (yyvsp[-1].interm.intermTypedNode));
-        type->setArraySize(size);
-
-        (yyval.interm.field) = new TField(type, (yyvsp[-3].lex).string, (yylsp[-3]));
+        (yyval.interm.field) = context->parseStructArrayDeclarator((yyvsp[-3].lex).string, (yylsp[-3]), (yyvsp[-1].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -4673,9 +4567,7 @@
   case 251:
 
     {
-        if ((yyvsp[-2].interm.intermBlock) != 0) {
-            (yyvsp[-2].interm.intermBlock)->setLine((yyloc));
-        }
+        (yyvsp[-2].interm.intermBlock)->setLine((yyloc));
         (yyval.interm.intermBlock) = (yyvsp[-2].interm.intermBlock);
     }
 
@@ -4720,7 +4612,7 @@
   case 258:
 
     {
-        (yyval.interm.intermBlock) = 0;
+        (yyval.interm.intermBlock) = nullptr;
     }
 
     break;
@@ -4728,9 +4620,7 @@
   case 259:
 
     {
-        if ((yyvsp[-1].interm.intermBlock)) {
-            (yyvsp[-1].interm.intermBlock)->setLine((yyloc));
-        }
+        (yyvsp[-1].interm.intermBlock)->setLine((yyloc));
         (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock);
     }
 
@@ -4740,7 +4630,6 @@
 
     {
         (yyval.interm.intermBlock) = new TIntermBlock();
-        (yyval.interm.intermBlock)->setLine((yyloc));
         (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode));
     }
 
@@ -4763,15 +4652,14 @@
 
   case 263:
 
-    { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[-1].interm.intermTypedNode)); }
+    { (yyval.interm.intermNode) = (yyvsp[-1].interm.intermTypedNode); }
 
     break;
 
   case 264:
 
     {
-        context->checkIsScalarBool((yylsp[-4]), (yyvsp[-2].interm.intermTypedNode));
-        (yyval.interm.intermNode) = context->intermediate.addIfElse((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yylsp[-4]));
+        (yyval.interm.intermNode) = context->addIfElse((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yylsp[-4]));
     }
 
     break;
@@ -4789,7 +4677,7 @@
 
     {
         (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode);
-        (yyval.interm.nodePair).node2 = 0;
+        (yyval.interm.nodePair).node2 = nullptr;
     }
 
     break;
@@ -4867,8 +4755,6 @@
   case 276:
 
     {
-        context->checkIsScalarBool((yylsp[0]), (yyvsp[-2].interm.intermTypedNode));
-
         (yyval.interm.intermNode) = context->addLoop(ELoopDoWhile, 0, (yyvsp[-2].interm.intermTypedNode), 0, (yyvsp[-5].interm.intermNode), (yylsp[-4]));
         context->decrLoopNestingLevel();
     }
@@ -4976,7 +4862,6 @@
   case 289:
 
     {
-        FRAG_ONLY("discard", (yylsp[-1]));
         (yyval.interm.intermNode) = context->addBranch(EOpKill, (yylsp[-1]));
     }