In Parser, dedupe the String instances referred to by StringLiteral instances. Implement the same optimization in the serialization code.

Some .bzl files have tons of duplicate string constants.

We can't dedupe the StringLiteral instances themselves, because they all have different Locations.

RELNOTES: None
PiperOrigin-RevId: 232495067
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
index dea8f33..000c6de 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
@@ -19,7 +19,9 @@
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Interner;
 import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.concurrent.BlazeInterners;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.events.Location;
@@ -164,6 +166,8 @@
   private int errorsCount;
   private boolean recoveryMode;  // stop reporting errors until next statement
 
+  private final Interner<String> stringInterner = BlazeInterners.newStrongInterner();
+
   private Parser(Lexer lexer, EventHandler eventHandler) {
     this.lexer = lexer;
     this.eventHandler = eventHandler;
@@ -599,7 +603,8 @@
     Preconditions.checkState(token.kind == TokenKind.STRING);
     int end = token.right;
     StringLiteral literal =
-        setLocation(new StringLiteral((String) token.value), token.left, end);
+        setLocation(
+            new StringLiteral(stringInterner.intern((String) token.value)), token.left, end);
 
     nextToken();
     if (token.kind == TokenKind.STRING) {
@@ -958,7 +963,7 @@
       if (expr instanceof StringLiteral && secondary instanceof StringLiteral) {
         StringLiteral left = (StringLiteral) expr;
         StringLiteral right = (StringLiteral) secondary;
-        return new StringLiteral(left.getValue() + right.getValue());
+        return new StringLiteral(stringInterner.intern(left.getValue() + right.getValue()));
       }
     }
     return new BinaryOperatorExpression(operator, expr, secondary);