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
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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user