Add addBinaryMath and addUnaryMath helpers to ParseContext

This refactoring reduces code duplication and moves functionality that is
not immediately related to the language grammar out of glslang.y.

BUG=angle:911

Change-Id: If5e225461890ed542dee01905829df1c9a6f5e27
Reviewed-on: https://chromium-review.googlesource.com/248570
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 06c2ea6..ff57a8f 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -2588,6 +2588,53 @@
     return publicType;
 }
 
+TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
+{
+    TIntermTyped *node = intermediate.addUnaryMath(op, child, loc);
+    if (node == 0)
+    {
+        unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
+        recover();
+        return child;
+    }
+    return node;
+}
+
+TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
+{
+    if (lValueErrorCheck(loc, GetOperatorString(op), child))
+        recover();
+    return addUnaryMath(op, child, loc);
+}
+
+TIntermTyped *TParseContext::addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right,
+    const TSourceLoc &loc)
+{
+    TIntermTyped *node = intermediate.addBinaryMath(op, left, right, loc);
+    if (node == 0)
+    {
+        binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString());
+        recover();
+        return left;
+    }
+    return node;
+}
+
+TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right,
+    const TSourceLoc &loc)
+{
+    TIntermTyped *node = intermediate.addBinaryMath(op, left, right, loc);
+    if (node == 0)
+    {
+        binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString());
+        recover();
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setBConst(false);
+        return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), loc);
+    }
+    return node;
+}
+
 //
 // Parse an array of strings using yyparse.
 //
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
index 23be57e..f38cc96 100644
--- a/src/compiler/translator/ParseContext.h
+++ b/src/compiler/translator/ParseContext.h
@@ -164,6 +164,13 @@
     void exitStructDeclaration();
 
     bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
+
+    TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &);
+    TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &);
+    TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right,
+        const TSourceLoc &);
+    TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right,
+        const TSourceLoc &);
 };
 
 int PaParseStrings(size_t count, const char* const string[], const int length[],
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index 26c9af2..e66cccb 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -272,24 +272,10 @@
         $$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3);
     }
     | postfix_expression INC_OP {
-        if (context->lValueErrorCheck(@2, "++", $1))
-            context->recover();
-        $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2);
-        if ($$ == 0) {
-            context->unaryOpError(@2, "++", $1->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addUnaryMathLValue(EOpPostIncrement, $1, @2);
     }
     | postfix_expression DEC_OP {
-        if (context->lValueErrorCheck(@2, "--", $1))
-            context->recover();
-        $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2);
-        if ($$ == 0) {
-            context->unaryOpError(@2, "--", $1->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addUnaryMathLValue(EOpPostDecrement, $1, @2);
     }
     ;
 
@@ -490,41 +476,14 @@
         $$ = $1;
     }
     | INC_OP unary_expression {
-        if (context->lValueErrorCheck(@1, "++", $2))
-            context->recover();
-        $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1);
-        if ($$ == 0) {
-            context->unaryOpError(@1, "++", $2->getCompleteString());
-            context->recover();
-            $$ = $2;
-        }
+        $$ = context->addUnaryMathLValue(EOpPreIncrement, $2, @1);
     }
     | DEC_OP unary_expression {
-        if (context->lValueErrorCheck(@1, "--", $2))
-            context->recover();
-        $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1);
-        if ($$ == 0) {
-            context->unaryOpError(@1, "--", $2->getCompleteString());
-            context->recover();
-            $$ = $2;
-        }
+        $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1);
     }
     | unary_operator unary_expression {
         if ($1.op != EOpNull) {
-            $$ = context->intermediate.addUnaryMath($1.op, $2, @1);
-            if ($$ == 0) {
-                const char* errorOp = "";
-                switch($1.op) {
-                  case EOpNegative:   errorOp = "-"; break;
-                  case EOpPositive:   errorOp = "+"; break;
-                  case EOpLogicalNot: errorOp = "!"; break;
-                  case EOpBitwiseNot: errorOp = "~"; break;
-                  default: break;
-                }
-                context->unaryOpError(@1, errorOp, $2->getCompleteString());
-                context->recover();
-                $$ = $2;
-            }
+            $$ = context->addUnaryMath($1.op, $2, @1);
         } else
             $$ = $2;
     }
@@ -545,49 +504,24 @@
 multiplicative_expression
     : unary_expression { $$ = $1; }
     | multiplicative_expression STAR unary_expression {
-        $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpMul, $1, $3, @2);
     }
     | multiplicative_expression SLASH unary_expression {
-        $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpDiv, $1, $3, @2);
     }
     | multiplicative_expression PERCENT unary_expression {
         ES3_ONLY("%", @2, "integer modulus operator");
-        $$ = context->intermediate.addBinaryMath(EOpMod, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "%", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpMod, $1, $3, @2);
     }
     ;
 
 additive_expression
     : multiplicative_expression { $$ = $1; }
     | additive_expression PLUS multiplicative_expression {
-        $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpAdd, $1, $3, @2);
     }
     | additive_expression DASH multiplicative_expression {
-        $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpSub, $1, $3, @2);
     }
     ;
 
@@ -595,89 +529,37 @@
     : additive_expression { $$ = $1; }
     | shift_expression LEFT_OP additive_expression {
         ES3_ONLY("<<", @2, "bit-wise operator");
-        $$ = context->intermediate.addBinaryMath(EOpBitShiftLeft, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "<<", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2);
     }
     | shift_expression RIGHT_OP additive_expression {
         ES3_ONLY(">>", @2, "bit-wise operator");
-        $$ = context->intermediate.addBinaryMath(EOpBitShiftRight, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, ">>", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2);
     }
     ;
 
 relational_expression
     : shift_expression { $$ = $1; }
     | relational_expression LEFT_ANGLE shift_expression {
-        $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
+        $$ = context->addBinaryMathBooleanResult(EOpLessThan, $1, $3, @2);
     }
     | relational_expression RIGHT_ANGLE shift_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
+        $$ = context->addBinaryMathBooleanResult(EOpGreaterThan, $1, $3, @2);
     }
     | relational_expression LE_OP shift_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
+        $$ = context->addBinaryMathBooleanResult(EOpLessThanEqual, $1, $3, @2);
     }
     | relational_expression GE_OP shift_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
+        $$ = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, $1, $3, @2);
     }
     ;
 
 equality_expression
     : relational_expression { $$ = $1; }
     | equality_expression EQ_OP relational_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
+        $$ = context->addBinaryMathBooleanResult(EOpEqual, $1, $3, @2);
     }
     | equality_expression NE_OP relational_expression {
-        $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
+        $$ = context->addBinaryMathBooleanResult(EOpNotEqual, $1, $3, @2);
     }
     ;
 
@@ -685,12 +567,7 @@
     : equality_expression { $$ = $1; }
     | and_expression AMPERSAND equality_expression {
         ES3_ONLY("&", @2, "bit-wise operator");
-        $$ = context->intermediate.addBinaryMath(EOpBitwiseAnd, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "&", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2);
     }
     ;
 
@@ -698,12 +575,7 @@
     : and_expression { $$ = $1; }
     | exclusive_or_expression CARET and_expression {
         ES3_ONLY("^", @2, "bit-wise operator");
-        $$ = context->intermediate.addBinaryMath(EOpBitwiseXor, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "^", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2);
     }
     ;
 
@@ -711,54 +583,28 @@
     : exclusive_or_expression { $$ = $1; }
     | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
         ES3_ONLY("|", @2, "bit-wise operator");
-        $$ = context->intermediate.addBinaryMath(EOpBitwiseOr, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "|", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            $$ = $1;
-        }
+        $$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2);
     }
     ;
 
 logical_and_expression
     : inclusive_or_expression { $$ = $1; }
     | logical_and_expression AND_OP inclusive_or_expression {
-        $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
+        $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2);
     }
     ;
 
 logical_xor_expression
     : logical_and_expression { $$ = $1; }
     | logical_xor_expression XOR_OP logical_and_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
+        $$ = context->addBinaryMathBooleanResult(EOpLogicalXor, $1, $3, @2);
     }
     ;
 
 logical_or_expression
     : logical_xor_expression { $$ = $1; }
     | logical_or_expression OR_OP logical_xor_expression  {
-        $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2);
-        if ($$ == 0) {
-            context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
-        }
+        $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2);
     }
     ;
 
diff --git a/src/compiler/translator/glslang_tab.cpp b/src/compiler/translator/glslang_tab.cpp
index 214cd09..4792327 100644
--- a/src/compiler/translator/glslang_tab.cpp
+++ b/src/compiler/translator/glslang_tab.cpp
@@ -688,32 +688,32 @@
 static const yytype_uint16 yyrline[] =
 {
        0,   205,   205,   206,   209,   233,   236,   241,   246,   251,
-     256,   262,   265,   268,   271,   274,   284,   297,   305,   422,
-     425,   433,   436,   442,   446,   453,   459,   468,   476,   479,
-     489,   492,   502,   512,   535,   536,   537,   538,   546,   547,
-     555,   563,   575,   576,   584,   595,   596,   605,   617,   618,
-     628,   638,   648,   661,   662,   672,   685,   686,   698,   699,
-     711,   712,   724,   725,   738,   739,   752,   753,   766,   767,
-     784,   785,   798,   799,   800,   801,   805,   806,   807,   811,
-     815,   819,   823,   830,   833,   844,   852,   860,   887,   893,
-     904,   908,   912,   916,   923,   979,   982,   989,   997,  1018,
-    1039,  1049,  1077,  1082,  1092,  1097,  1107,  1110,  1113,  1116,
-    1122,  1129,  1132,  1136,  1140,  1144,  1151,  1155,  1159,  1166,
-    1170,  1174,  1181,  1190,  1196,  1199,  1205,  1211,  1218,  1227,
-    1236,  1244,  1247,  1254,  1258,  1265,  1268,  1272,  1276,  1285,
-    1294,  1302,  1312,  1324,  1327,  1330,  1336,  1343,  1346,  1352,
-    1355,  1358,  1364,  1367,  1382,  1386,  1390,  1394,  1398,  1402,
-    1407,  1412,  1417,  1422,  1427,  1432,  1437,  1442,  1447,  1452,
-    1457,  1462,  1467,  1472,  1477,  1482,  1487,  1492,  1497,  1502,
-    1507,  1511,  1515,  1519,  1523,  1527,  1531,  1535,  1539,  1543,
-    1547,  1551,  1555,  1559,  1563,  1567,  1575,  1583,  1587,  1600,
-    1600,  1603,  1603,  1609,  1612,  1628,  1631,  1640,  1644,  1650,
-    1657,  1672,  1676,  1680,  1681,  1687,  1688,  1689,  1690,  1691,
-    1695,  1696,  1696,  1696,  1706,  1707,  1711,  1711,  1712,  1712,
-    1717,  1720,  1730,  1733,  1739,  1740,  1744,  1752,  1756,  1766,
-    1771,  1788,  1788,  1793,  1793,  1800,  1800,  1808,  1811,  1817,
-    1820,  1826,  1830,  1837,  1844,  1851,  1858,  1869,  1878,  1882,
-    1889,  1892,  1898,  1898
+     256,   262,   265,   268,   271,   274,   277,   283,   291,   408,
+     411,   419,   422,   428,   432,   439,   445,   454,   462,   465,
+     475,   478,   481,   484,   494,   495,   496,   497,   505,   506,
+     509,   512,   519,   520,   523,   529,   530,   534,   541,   542,
+     545,   548,   551,   557,   558,   561,   567,   568,   575,   576,
+     583,   584,   591,   592,   598,   599,   605,   606,   612,   613,
+     630,   631,   644,   645,   646,   647,   651,   652,   653,   657,
+     661,   665,   669,   676,   679,   690,   698,   706,   733,   739,
+     750,   754,   758,   762,   769,   825,   828,   835,   843,   864,
+     885,   895,   923,   928,   938,   943,   953,   956,   959,   962,
+     968,   975,   978,   982,   986,   990,   997,  1001,  1005,  1012,
+    1016,  1020,  1027,  1036,  1042,  1045,  1051,  1057,  1064,  1073,
+    1082,  1090,  1093,  1100,  1104,  1111,  1114,  1118,  1122,  1131,
+    1140,  1148,  1158,  1170,  1173,  1176,  1182,  1189,  1192,  1198,
+    1201,  1204,  1210,  1213,  1228,  1232,  1236,  1240,  1244,  1248,
+    1253,  1258,  1263,  1268,  1273,  1278,  1283,  1288,  1293,  1298,
+    1303,  1308,  1313,  1318,  1323,  1328,  1333,  1338,  1343,  1348,
+    1353,  1357,  1361,  1365,  1369,  1373,  1377,  1381,  1385,  1389,
+    1393,  1397,  1401,  1405,  1409,  1413,  1421,  1429,  1433,  1446,
+    1446,  1449,  1449,  1455,  1458,  1474,  1477,  1486,  1490,  1496,
+    1503,  1518,  1522,  1526,  1527,  1533,  1534,  1535,  1536,  1537,
+    1541,  1542,  1542,  1542,  1552,  1553,  1557,  1557,  1558,  1558,
+    1563,  1566,  1576,  1579,  1585,  1586,  1590,  1598,  1602,  1612,
+    1617,  1634,  1634,  1639,  1639,  1646,  1646,  1654,  1657,  1663,
+    1666,  1672,  1676,  1683,  1690,  1697,  1704,  1715,  1724,  1728,
+    1735,  1738,  1744,  1744
 };
 #endif
 
@@ -2428,14 +2428,7 @@
   case 15:
 
     {
-        if (context->lValueErrorCheck((yylsp[0]), "++", (yyvsp[-1].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode), (yylsp[0]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->unaryOpError((yylsp[0]), "++", (yyvsp[-1].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addUnaryMathLValue(EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode), (yylsp[0]));
     }
 
     break;
@@ -2443,14 +2436,7 @@
   case 16:
 
     {
-        if (context->lValueErrorCheck((yylsp[0]), "--", (yyvsp[-1].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode), (yylsp[0]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->unaryOpError((yylsp[0]), "--", (yyvsp[-1].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addUnaryMathLValue(EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode), (yylsp[0]));
     }
 
     break;
@@ -2697,14 +2683,7 @@
   case 31:
 
     {
-        if (context->lValueErrorCheck((yylsp[-1]), "++", (yyvsp[0].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreIncrement, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->unaryOpError((yylsp[-1]), "++", (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addUnaryMathLValue(EOpPreIncrement, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2712,14 +2691,7 @@
   case 32:
 
     {
-        if (context->lValueErrorCheck((yylsp[-1]), "--", (yyvsp[0].interm.intermTypedNode)))
-            context->recover();
-        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreDecrement, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->unaryOpError((yylsp[-1]), "--", (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addUnaryMathLValue(EOpPreDecrement, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2728,20 +2700,7 @@
 
     {
         if ((yyvsp[-1].interm).op != EOpNull) {
-            (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath((yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-            if ((yyval.interm.intermTypedNode) == 0) {
-                const char* errorOp = "";
-                switch((yyvsp[-1].interm).op) {
-                  case EOpNegative:   errorOp = "-"; break;
-                  case EOpPositive:   errorOp = "+"; break;
-                  case EOpLogicalNot: errorOp = "!"; break;
-                  case EOpBitwiseNot: errorOp = "~"; break;
-                  default: break;
-                }
-                context->unaryOpError((yylsp[-1]), errorOp, (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-                context->recover();
-                (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
-            }
+            (yyval.interm.intermTypedNode) = context->addUnaryMath((yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
         } else
             (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
     }
@@ -2784,12 +2743,7 @@
   case 39:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "*", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2797,12 +2751,7 @@
   case 40:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "/", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2811,12 +2760,7 @@
 
     {
         ES3_ONLY("%", (yylsp[-1]), "integer modulus operator");
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "%", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2830,12 +2774,7 @@
   case 43:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "+", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2843,12 +2782,7 @@
   case 44:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "-", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2863,12 +2797,7 @@
 
     {
         ES3_ONLY("<<", (yylsp[-1]), "bit-wise operator");
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpBitShiftLeft, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "<<", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitShiftLeft, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2877,12 +2806,7 @@
 
     {
         ES3_ONLY(">>", (yylsp[-1]), "bit-wise operator");
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpBitShiftRight, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), ">>", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitShiftRight, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2896,14 +2820,7 @@
   case 49:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "<", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[-1]));
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2911,14 +2828,7 @@
   case 50:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), ">", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[-1]));
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2926,14 +2836,7 @@
   case 51:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "<=", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[-1]));
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2941,14 +2844,7 @@
   case 52:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), ">=", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[-1]));
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2962,14 +2858,7 @@
   case 54:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "==", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[-1]));
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2977,14 +2866,7 @@
   case 55:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "!=", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[-1]));
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -2999,12 +2881,7 @@
 
     {
         ES3_ONLY("&", (yylsp[-1]), "bit-wise operator");
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpBitwiseAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "&", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitwiseAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -3019,12 +2896,7 @@
 
     {
         ES3_ONLY("^", (yylsp[-1]), "bit-wise operator");
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpBitwiseXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "^", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitwiseXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -3039,12 +2911,7 @@
 
     {
         ES3_ONLY("|", (yylsp[-1]), "bit-wise operator");
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpBitwiseOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "|", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMath(EOpBitwiseOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -3058,14 +2925,7 @@
   case 63:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "&&", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[-1]));
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -3079,14 +2939,7 @@
   case 65:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "^^", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[-1]));
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;
@@ -3100,14 +2953,7 @@
   case 67:
 
     {
-        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
-        if ((yyval.interm.intermTypedNode) == 0) {
-            context->binaryOpError((yylsp[-1]), "||", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(), (yyvsp[0].interm.intermTypedNode)->getCompleteString());
-            context->recover();
-            ConstantUnion *unionArray = new ConstantUnion[1];
-            unionArray->setBConst(false);
-            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[-1]));
-        }
+        (yyval.interm.intermTypedNode) = context->addBinaryMathBooleanResult(EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
     }
 
     break;