fix(lexer): {array}[index] no longer mis-tokenises [ as bracket-string

The lexer's isStringBracket disambiguator decides whether `[` opens
an indexing operator or a Harbour bracket-string literal. The
heuristic checks the previous token's kind and treats the bracket
as indexing only when preceded by an IDENT, RPAREN, RBRACKET, or a
literal. RBRACE was missing — so

   FieldPut(3, {"Kim","Lee","Park","Choi","Yoon"}[Int(Mod(i-1,5))+1])

tokenised the `[` after `}` as a bracket-string opener, swallowed
through the first `]` it found, and produced bogus parse errors
("expected ), got STRING …"). RBRACE is now in the indexing-context
set, so an inline array-literal followed by `[index]` works.

Surfaced by the examples/ build sweep — fixed test_all_rdd,
test_index_adv, test_multi_rdd, test_rdd_full all in one go.

The sweep itself is committed as tests/examples_build.sh — builds
every PRG under examples/ and reports any compiler / preprocessor
errors. Run it after compiler changes to catch regressions in
broad-coverage user-style code that the focused suites don't
exercise.

Current sweep state: 65 / 71 examples build cleanly. The remaining
6 failures are all #pragma BEGINDUMP blocks that import external
Go packages (http, websocket, sqlite, time) — not Five-side bugs.

Other gates green:
  go test ./...      : PASS
  FiveSql2 SQL:1999  : 43/43
  Harbour compat     : 56/56
  std.ch suite       : 16/16
  FRB suite          : 7/7
  examples build     : 65/71 (rest = external Go deps)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-04 21:06:13 +09:00
parent 2008266da7
commit af0d54d352
2 changed files with 45 additions and 2 deletions

View File

@@ -330,10 +330,11 @@ func (l *Lexer) scanString(quote byte) token.Token {
}
// isStringBracket returns true if [ should be treated as string delimiter.
// Harbour: [text] is string when not preceded by ident, ), ], literal.
// Harbour: [text] is string when not preceded by ident, ), ], literal,
// or `}` (close of array literal — `{1,2,3}[2]` is index access).
func (l *Lexer) isStringBracket() bool {
switch l.lastKind {
case token.IDENT, token.RPAREN, token.RBRACKET,
case token.IDENT, token.RPAREN, token.RBRACKET, token.RBRACE,
token.INT, token.LONG, token.DOUBLE, token.STRING,
token.TRUE, token.FALSE, token.NIL_LIT:
return false // array index context