go: parse.sx — if/else, for, break/continue, inc-dec + 11 tests [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 27s

Adds the most-used control-flow forms:
  if COND { ... } [else { ... } | else if ...]
  for { ... }                          — infinite
  for COND { ... }                     — while-like
  for INIT; COND; POST { ... }         — C-style
  break / continue                     — keyword stmts (no labels yet)
  x++ / x--                            — Go statement inc-dec

AST shapes:
  (list :if COND THEN ELSE)              — ELSE nil / :if / :block
  (list :for INIT COND POST BODY)        — any of INIT/COND/POST may be nil
  (list :break LABEL)  (list :continue LABEL)
  (list :inc-dec OP EXPR)                — OP is "++" / "--"

**Closes the parser-mode caveat** logged when composite literals
landed. `gp-no-comp-lit` is a re-entrant counter on the parser state;
control-flow constructs increment it before parsing their condition
and decrement after, suppressing the postfix `{` → composite-lit
interpretation so that `if Foo { ... }` correctly reads `{ ... }` as
the body, not as `Foo{}` composite literal. Verified by the test:

  (go-parse "if Foo {}")  →  (:if (:var "Foo") (:block ()) nil)

gp-parse-control-cond is the single helper that bracket-wraps the
flag bump so future control-flow forms (switch, select, range) can't
forget to engage suppression.

switch / select / defer / go / for-range / channel-send still deferred.

parse 152/152, total 281/281.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 20:17:40 +00:00
parent 5f6d62f45b
commit ba41f8a580
5 changed files with 186 additions and 14 deletions

View File

@@ -911,6 +911,72 @@
(list)
(list :block (list (ast-app (ast-var "f") (list (ast-var "x")))))))
(go-parse-test
"if: if x { }"
(go-parse "if x { }")
(list :if (ast-var "x") (list :block (list)) nil))
(go-parse-test
"if: if cond { body } else { body }"
(go-parse "if x { y := 1 } else { z := 2 }")
(list
:if (ast-var "x")
(list
:block (list
(list :short-decl (list (ast-var "y")) (list (ast-literal "1")))))
(list
:block (list
(list :short-decl (list (ast-var "z")) (list (ast-literal "2")))))))
(go-parse-test
"if: chained else-if"
(go-parse "if a { } else if b { } else { }")
(list
:if (ast-var "a")
(list :block (list))
(list :if (ast-var "b") (list :block (list)) (list :block (list)))))
(go-parse-test
"if: comparison condition"
(go-parse "if x == 0 { return 0 }")
(list
:if (ast-app (ast-var "==") (list (ast-var "x") (ast-literal "0")))
(list :block (list (list :return (list (ast-literal "0")))))
nil))
(go-parse-test
"for: infinite — for { }"
(go-parse "for { }")
(list :for nil nil nil (list :block (list))))
(go-parse-test
"for: while-like — for cond { }"
(go-parse "for x { }")
(list :for nil (ast-var "x") nil (list :block (list))))
(go-parse-test
"for: C-style — for i := 0; i < 10; i++ { }"
(go-parse "for i := 0; i < 10; i++ { }")
(list
:for (list :short-decl (list (ast-var "i")) (list (ast-literal "0")))
(ast-app (ast-var "<") (list (ast-var "i") (ast-literal "10")))
(list :inc-dec "++" (ast-var "i"))
(list :block (list))))
(go-parse-test "stmt: break" (go-parse "break") (list :break nil))
(go-parse-test "stmt: continue" (go-parse "continue") (list :continue nil))
(go-parse-test
"stmt: x++ (inc-dec)"
(go-parse "x++")
(list :inc-dec "++" (ast-var "x")))
(go-parse-test
"control: composite-lit suppression in if cond"
(go-parse "if Foo {}")
(list :if (ast-var "Foo") (list :block (list)) nil))
(go-parse-test "non-primary: '+'" (go-parse "+") nil)
(go-parse-test "non-primary: empty" (go-parse "") nil)