bazel syntax: break dependence on EventHandler

This change removes nearly all uses of EventHandler in the interpreter.
(The remaining uses are for events created by the Starlark 'print' statement.
A follow-up change will create a dedicated StarlarkThread.PrintHandler.)

All parse functions now report errors in one of two ways:

1) by throwing a SyntaxError exception containing a list of events.
   This approach is used by "all-or-nothing" parse operations related
   to expressions. Clients may catch the exception, extract the events,
   and replay them on their handler should they choose. Example:

     try {
        Expression expr = Expression.parse(input)
        ...
     } catch (SyntaxError ex) {
        Event.replayEventsOn(handler, ex.errors());
     }

2) by recording a list of scan/parse errors in StarlarkFile.errors.
   The result of parsing a file is both a syntax tree (possibly incomplete),
   and a list of errors. If parsing is followed by validation,
   the validator appends its errors to this list. (Validation is now
   capable of reporting multiple errors per file. ValidationException is gone.)

     StarlarkFile file = StarlarkFile.parse(input)
     if (!file.ok()) {
        Event.replayEventsOn(handler, file.errors());
        return;
     }

    Or:

     StarlarkFile file = StarlarkFile.parse(input)
     if (!file.ok()) {
        throw new SyntaxError(file.errors());
     }

Details:
- error helpers for Identifiers have moved from Eval to ValidationEnvironment
  and no longer depend on EvalException.
- The EvalException.incompleteAST concept is irrelevant now that
  clients do not proceed to evaluation if the parser or validation
  step produced errors.
- StarlarkFile: exec + execTopLevelStatement have moved to EvalUtils, and will
  change further.
- replayLexerEvents is gone from the API. The validator (which has access
  to a StarlarkSemantics) can optionally copy the string escape events
  into the main error bucket, or ignore them.
- StarlarkFile: eliminate parseWithoutImports
- Parser: delete dead code parseStatement{,s}
- Lexer: delete dead code stringAtLine

Numerous fixes were required in the tests, because they are such a muddle
of different phases (scan, parse, validate, evaluate)
and modes (BUILD vs .bzl vs core Starlark).

RELNOTES: Multiple Starlark validation errors are reported in a single pass.
PiperOrigin-RevId: 272205103
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java
index 7baff22..002297c 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java
@@ -59,6 +59,7 @@
 import com.google.devtools.build.lib.syntax.StarlarkFile;
 import com.google.devtools.build.lib.syntax.StarlarkSemantics;
 import com.google.devtools.build.lib.syntax.StarlarkThread;
+import com.google.devtools.build.lib.syntax.SyntaxError;
 import com.google.devtools.build.lib.testutil.MoreAsserts;
 import com.google.devtools.build.lib.util.FileTypeSet;
 import java.util.Collection;
@@ -705,6 +706,9 @@
   protected void evalAndExport(String... lines) throws Exception {
     ParserInput input = ParserInput.fromLines(lines);
     StarlarkFile file = StarlarkFile.parseAndValidateSkylark(input, ev.getStarlarkThread());
+    if (!file.errors().isEmpty()) {
+      throw new SyntaxError(file.errors());
+    }
     SkylarkImportLookupFunction.execAndExport(
         file, FAKE_LABEL, ev.getEventHandler(), ev.getStarlarkThread());
   }
@@ -1255,14 +1259,6 @@
   }
 
   @Test
-  public void testStructMembersAreImmutable() throws Exception {
-    checkErrorContains(
-        "cannot assign to 's.x'",
-        "s = struct(x = 'a')",
-        "s.x = 'b'\n");
-  }
-
-  @Test
   public void testStructDictMembersAreMutable() throws Exception {
     eval(
         "s = struct(x = {'a' : 1})",