code: private static Node constructStringExprNode(
        Iterator<CharSequence> parts, Node objLitNode, Node refNode) throws MalformedException {
      checkNotNull(refNode);
  
      CharSequence part = parts.next();
      Node partNode = null;
      if (part instanceof JsMessage.PlaceholderReference) {
        JsMessage.PlaceholderReference phRef =
            (JsMessage.PlaceholderReference) part;
  
        // The translated message is null
        if (objLitNode == null) {
          throw new MalformedException("Empty placeholder value map " +
              "for a translated message with placeholders.", refNode);
        }
  
        for (Node key = objLitNode.getFirstChild(); key != null;
             key = key.getNext()) {
          if (key.getString().equals(phRef.getName())) {
            Node valueNode = key.getFirstChild();
            partNode = valueNode.cloneTree();
          }
        }
  
        if (partNode == null) {
          throw new MalformedException(
              "Unrecognized message placeholder referenced: " + phRef.getName(),
              objLitNode);
        }
      } else {
        // The part is just a string literal.
        partNode = IR.string(part.toString());
      }
  
      if (parts.hasNext()) {
        return IR.add(partNode,
            constructStringExprNode(parts, objLitNode, refNode));
      } else {
        return partNode;
      }
    }
docs: Creates a parse tree corresponding to the remaining message parts in an
  iteration. The result consists of one or more STRING nodes, placeholder
  replacement value nodes (which can be arbitrary expressions), and ADD
  nodes.
  
  @param parts  an iterator over message parts
  @param objLitNode  an OBJLIT node mapping placeholder names to values
  @return the root of the constructed parse tree
  
  @throws MalformedException if {@code parts} contains a placeholder
  reference that does not correspond to a valid placeholder name