diff --git a/ExprPrimaryNodes.py b/ExprPrimaryNodes.py
index 043b18beea79d0ac1acf87da0b4b14f1e44ca281..d04a094a14649292f69e51014d66b4b0767f8852 100644
--- a/ExprPrimaryNodes.py
+++ b/ExprPrimaryNodes.py
@@ -93,16 +93,22 @@ def helperDisambigName(node):
 # args exprs, exprs expr COMMA exprs
 class ArgsNode(ASTNode):
     # always list all fields in the init method to show the class structure
-    def __init__(self, parseTree, typeName):
+    def __init__(self, parseTree, typeName, exprs = []):
         self.parseTree = parseTree
         self.exprs = []  # a list of expressions
         self.env = None
         self.children = []
         self.typeName = typeName # the type (class/interface) this node belongs under
 
-        exprs = getParseTreeNodes(['expr'], parseTree)
-        for e in exprs:
-            self.exprs.append(makeNodeFromExpr(e, typeName))
+        if exprs == []:
+            exprs = getParseTreeNodes(['expr'], parseTree)
+            for e in exprs:
+                self.exprs.append(makeNodeFromExpr(e, typeName))
+        else:
+            # manually induce exprs
+            # for converting string concatenation to a method call
+            # see ExprPrimaryNodes:ExprNode on string concat
+            self.exprs = exprs
 
         self.children.extend(self.exprs)
 
@@ -582,6 +588,49 @@ class ExprNode(ASTNode):
         or (self.right.myType.name =='java.lang.String' and self.left.myType.name not in ['void'])) and self.op == '+':
             self.myType = TypeStruct('java.lang.String', self.env.getNode('java.lang.String', 'type'))
             self.myType.link(self.env)
+
+            # var1 + var2 === String.valueOf(var1).concat( String.valueOf(var2) )
+            
+            # methodInvoc name LPAREN args RPAREN (because it's static)
+            # MethodInvNode
+            # ID = NameNode
+            #       - name = "String.valueOf"
+            # args = ArgsNode
+            #       - exprs = [self.left]
+
+            # create MethodInvNode to call String.valueOf(left) and String.valueOf(right)
+            # 1. Make NameNode for String.valueOf
+            valueOfNameNode = NameNode(self.parseTree, True, self.typeName, "String.valueOf")
+            valueOfNameNode.env = self.env
+            # 2. Make ArgsNode for left and right
+            leftArg = ArgsNode(self.parseTree, self.typeName, [self.left])
+            rightArg = ArgsNode(self.parseTree, self.typeName, [self.right])
+            # 3. Put it all together
+            valueOfMethodInvLeft = MethodInvNode(self.parseTree, self.typeName, valueOfNameNode, leftArg)
+            valueOfMethodInvRight = MethodInvNode(self.parseTree, self.typeName, valueOfNameNode, rightArg)
+            # 4. Check type to be safe
+            # valueOfMethodInvLeft.checkType()
+            # valueOfMethodInvRight.checkType()
+
+            
+            # methodInvoc primary PERIOD ID LPAREN args RPAREN
+            # MethodInvNode
+            # primary = self.left
+            # ID = NameNode
+            #       - name = "concat"
+            # args = ArgsNode
+            #       - exprs = [self.right]
+
+            # create MethodInvNode to call left.concat(right)
+            # 1. Make NameNode for String.concat (name = "concat")
+            concatNameNode = NameNode(self.parseTree, True, self.typeName, "concat")
+            # 2. Make ArgsNode for right
+            rightArgMethodInv = ArgsNode(self.parseTree, self.typeName, [valueOfMethodInvRight])
+            # 3. Put it all together
+            self.concatMethodInv = MethodInvNode(self.parseTree, self.typeName, concatNameNode, rightArgMethodInv, valueOfMethodInvLeft)
+            # 4. Check type to be safe
+            self.concatMethodInv.checkType()
+            
             return
 
         raise Exception("ERROR: Incompatible types. Left of {} type can't be used with right of {} type on operation {}".format(self.left.myType.name, self.right.myType.name, self.op))
@@ -701,6 +750,20 @@ class ExprNode(ASTNode):
         # String Add TODO
         if (self.left.myType.name =='java.lang.String' or self.right.myType.name =='java.lang.String') \
         and self.op == '+':
+            # String.valueOf(left)
+            # if not hasattr(self.valueOfMethodInvLeft, "code"):
+            #     self.valueOfMethodInvLeft.codeGen()
+            # self.code += self.valueOfMethodInvLeft.code
+
+            # String.valueOf(right)
+            # if not hasattr(self.valueOfMethodInvLeft, "code"):
+            #     self.valueOfMethodInvLeft.codeGen()
+            # self.code += self.valueOfMethodInvLeft.code
+
+            # ( String.valueOf(right) ).concat( left )
+            if not hasattr(self.concatMethodInv, "code"):
+                self.concatMethodInv.codeGen()
+            self.code += self.concatMethodInv.code
             return
         # Number Add, Subtract, Multiply
         if self.op in ['+', '-', '*']:
@@ -928,7 +991,7 @@ class FieldAccessNode(ASTNode):
 # methodInvoc
 class MethodInvNode(ASTNode):
     # always list all fields in the init method to show the class structure
-    def __init__(self, parseTree, typeName):
+    def __init__(self, parseTree, typeName, ID = '', args = None, primary = None):
         self.parseTree = parseTree
         self.primary = None  # can be empty
         self.ID = '' # can be either ID or compID
@@ -938,12 +1001,23 @@ class MethodInvNode(ASTNode):
         self.method = None
         self.typeName = typeName # the type (class/interface) this node belongs under
 
-        # input parse tree is either: methodInvoc primary PERIOD ID LPAREN args RPAREN
-        #  methodInvoc name LPAREN args RPAREN
-        self.ID = NameNode(parseTree.children[-4], True, typeName)
-        self.args = ArgsNode(parseTree.children[-2], typeName)
-        if parseTree.children[0].name == 'primary':
-            self.primary = makeNodeFromAllPrimary(parseTree.children[0], typeName)
+        if ID == '' or args is None:
+            # input parse tree is either: methodInvoc primary PERIOD ID LPAREN args RPAREN
+            #  methodInvoc name LPAREN args RPAREN
+            self.ID = NameNode(parseTree.children[-4], True, typeName)
+            self.args = ArgsNode(parseTree.children[-2], typeName)
+            if parseTree.children[0].name == 'primary':
+                self.primary = makeNodeFromAllPrimary(parseTree.children[0], typeName)
+            self.override = False
+        else:
+            # manually induce ID and args
+            # for converting string concatenation to a method call
+            # see ExprPrimaryNodes:ExprNode on string concat
+            self.ID = ID
+            self.args = args
+            if primary is not None:
+                self.primary = primary
+            self.override = True
 
         self.children.append(self.primary)
         self.children.append(self.args)
@@ -986,7 +1060,7 @@ class MethodInvNode(ASTNode):
         if m:
 
             # check static
-            if (not self.ID.shouldBeStatic) and 'static' in m.mods:
+            if (not self.ID.shouldBeStatic and not self.override) and 'static' in m.mods:
                 raise Exception("ERROR: Non-static access of static method {}.".format(m.name))
 
             # check protected
diff --git a/NameNode.py b/NameNode.py
index 859f25fdeb799941053e0a70b25754de7ab09056..70ce82cf4de5bb8c57ac120ea9f530274ac48b5b 100644
--- a/NameNode.py
+++ b/NameNode.py
@@ -19,7 +19,7 @@ from codeGenNodes import genNameNode
 
 
 class NameNode(ASTNode):
-    def __init__(self, parseTree, methodInvoke, typeName):
+    def __init__(self, parseTree, methodInvoke, typeName, name = ""):
 
         self.parseTree = parseTree
         self.name = "" # str: stores original lex of the name (ID/COMPID)
@@ -40,7 +40,14 @@ class NameNode(ASTNode):
         self.staticField = None
         self.prefixNodes = [] # stores the past prefix links so we can evaluate them one by one
 
-        self.name = getParseTreeNodes(["ID", "COMPID"], parseTree)[0].lex
+        if name == "":
+            self.name = getParseTreeNodes(["ID", "COMPID"], parseTree)[0].lex
+        else:
+            # manually induce name
+            # for converting string concatenation to a method call
+            # see ExprPrimaryNodes:ExprNode on string concat
+            self.name = name
+
         self.IDs = self.name.split(".")
 
     # Updates the resolved/identified prefix
diff --git a/UnitNodes.py b/UnitNodes.py
index 606114766223e0f486d3e7238a877ad841611c2f..15d466e337b367f3cdc9881cbb090a9a02660ff7 100644
--- a/UnitNodes.py
+++ b/UnitNodes.py
@@ -1,7 +1,7 @@
 from AST import ASTNode, getParseTreeNodes
 from Environment import Env
 from TheTypeNode import TypeNode, TypeStruct
-from CodeGenUtils import p, getLStringLabel
+from CodeGenUtils import p, getLStringLabel, importHelper
 
 #   LiteralNode
 #   ParamNode
@@ -55,20 +55,88 @@ class LiteralNode(ASTNode):
                 self.code += p("mov", "eax", "0", " set to literal false")
                 return
 
-        # char TODO
+        # char
         if self.name == 'char':
-            self.code += p("mov", "eax", str(self.getConstant()), " set to literal char")
+            self.code += p("mov", "eax", str("dword " + self.getConstant()), " set to literal char")
             return
 
-        # string TODO
-        # if self.name == 'java.lang.String':
-        #     n = getLStringLabel()
-        #     lStringLabel = "_literalstring" + n
+        # string
+        if self.name == 'java.lang.String':
+            self.code += ";Start of String Literal Creation for class " + self.typeName + "\n"
+            # generate array of characters
+            # then call new String(array)
+            
+            # remove quotation marks
+            value = self.value[1:-1]
 
-        #     self.code += p(lStringLabel + ":", "")
-        #     self.code += p("db", str(self.getConstant()))
-        #     self.code += p("mov", "eax", "[" + lStringLabel + "]", " set to literal string")
-        #     return
+            # FIRST: create char array for this string
+            # 1. Allocating space for the char array in heap
+            # Note: uses ecx to temporarily store the array length
+            self.code += ";Start of char array creation\n" + \
+                p(instruction="mov", arg1="eax", arg2=str(len(value)), comment="array length") + \
+                p(instruction="push", arg1="ecx", comment="saving ecx's value") + \
+                p(instruction="mov", arg1="ecx", arg2="eax", comment="ecx now stroes the array's length") + \
+                p(instruction="add", arg1="eax", arg2=2, comment="number of items to allocate on heap") + \
+                p(instruction="imul", arg1="eax", arg2=4, comment="number of bytes to allocate on heap") + \
+                p(instruction="call", arg1="__malloc", comment="allocating memory for array on heap")
+
+            # 2. Pointing first item to vtable
+            aLabel = "A_char"
+            self.code += p(instruction="extern", arg1=aLabel) + \
+                p(instruction="mov", arg1="[eax]", arg2="dword "+aLabel, comment="first item is vtable pointer")
+            
+            # 3. Storing length in the second slot
+            self.code += p(instruction="mov", arg1="[eax+4]", arg2="ecx", comment="storing array length in second slot")
+
+            # 4. populate array with this string literal's chars
+            self.code += ";Start of populating char array\n"
+            # loop through string
+            for i in range(len(value)):
+                self.code += p(instruction="mov", arg1="[eax+"+str(8+i*4)+"]", arg2=str("dword '"+value[i]+"'"), comment="a["+str(i)+"]="+str(value[i]))
+            self.code += ";End of populating char array\n"
+
+            # 5. Restoring ecx
+            self.code += p(instruction="pop", arg1="ecx", comment="restoring register ecx")
+            self.code += ";End of char array creation\n"
+
+            # SECOND: create new string object with the char array 
+
+            # push array pointer
+            self.code += p(instruction="push", arg1="eax", comment="save pointer to char array")
+
+            # 1. alloc enough space for this object
+            classDef = self.env.getNode('java.lang.String', 'type')
+            fieldOffset = classDef.fieldOffset
+            numFields = len(fieldOffset)
+            numBytes = (numFields + 1) * 4
+            self.code += "; Creating an object for class " + self.typeName + "\n"
+            self.code += p(instruction="mov", arg1="eax", arg2=numBytes, comment="allocating memory for object") + \
+                         p(instruction="call", arg1="__malloc")
+
+            # 2. Pointing first item to vtable
+            self.code += importHelper(classDef.name, self.typeName, "C_"+classDef.name)
+            self.code += p(instruction="mov", arg1="[eax]", arg2="dword C_" + classDef.name, comment="first item is vtable pointer")
+
+            # restore pointer to our char array
+            self.code += p("pop", "ebx", comment="restore pointer to our char array")
+
+            # 3. Calling constructor
+            self.code += "; Calling constructor for String\n"
+            self.code += p(instruction="push", arg1="eax", comment="pushing object as first argument")
+            # Evaluate arguments and pushing parameters
+            self.code += p("push", "ebx", comment="add our char array as arg")
+
+            # 4. call String::String(char[] chars)
+            label = "M_String_String_char"
+            self.code += importHelper(classDef.name, self.typeName, label)
+            self.code += p(instruction="call", arg1=label, comment="Calling constructor")
+
+            # 4. Popping parameters and pointer to object
+            self.code += p(instruction="add", arg1="esp", arg2=4, comment="Popping parameters")
+            self.code += p(instruction="pop", arg1="eax", comment="eax now contains pointer to newly created object")
+            self.code += ";End of object creation\n"
+            self.code += ";End of String Literal Creation for class " + self.typeName + "\n"
+            return
 
         # null
         if self.name == 'null':