go: parse.sx — struct type expressions + 8 tests [proposes-ast]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
Adds Go struct types to gp-parse-type:
struct {} → (list :ty-struct ())
struct { x int } → (list :ty-struct [(:field [x] (:ty-name int))])
struct { x int; y string } → multiple field rows
struct { x, y int } → shared-type row (NAMES is a list)
struct { inner struct { x int } } → nested struct types
gp-parse-struct-fields walks field rows tolerating ASI-inserted semis
(from newlines between fields). Each row collects 1+ names separated
by commas, then a single type that all the names share. Embedded
fields, field tags, and methods are deferred.
The :field shape (NAMES + TYPE) is a recurring multi-language pattern —
struct fields, func params, method receivers, var decls all map to it.
Logged in Blockers as a canonical-AST candidate
(ast-binding-group / ast-named-of-type); worth promoting once a second
consumer (parser of another statically-typed guest, or Go func decls)
exercises the same shape.
parse 98/98, total 227/227.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -95,6 +95,49 @@
|
||||
:else nil)))
|
||||
(gp-args-rest)
|
||||
args)))))
|
||||
(define
|
||||
gp-parse-struct-fields
|
||||
;; Caller positioned BEFORE '{'. Parses fields until '}'.
|
||||
;; field := name [, name]* TYPE
|
||||
;; Tolerates ASI-inserted semis between fields. Embedded fields
|
||||
;; (anonymous type without preceding names) and field tags are
|
||||
;; deferred. Returns a list of (list :field NAMES TYPE).
|
||||
(fn
|
||||
()
|
||||
(when (and (= (gp-tok-type) "op") (= (gp-tok-value) "{"))
|
||||
(gp-advance!))
|
||||
(let ((fields (list)))
|
||||
(define
|
||||
gp-struct-loop
|
||||
(fn
|
||||
()
|
||||
(cond
|
||||
(= (gp-tok-type) "semi")
|
||||
(do (gp-advance!) (gp-struct-loop))
|
||||
(and (= (gp-tok-type) "op") (= (gp-tok-value) "}"))
|
||||
(gp-advance!)
|
||||
(= (gp-tok-type) "ident")
|
||||
(do
|
||||
(let ((names (list (gp-tok-value))))
|
||||
(gp-advance!)
|
||||
(define
|
||||
gp-names-rest
|
||||
(fn
|
||||
()
|
||||
(when (and (= (gp-tok-type) "op")
|
||||
(= (gp-tok-value) ","))
|
||||
(gp-advance!)
|
||||
(when (= (gp-tok-type) "ident")
|
||||
(append! names (gp-tok-value))
|
||||
(gp-advance!))
|
||||
(gp-names-rest))))
|
||||
(gp-names-rest)
|
||||
(let ((ty (gp-parse-type)))
|
||||
(append! fields (list :field names ty))))
|
||||
(gp-struct-loop))
|
||||
:else nil)))
|
||||
(gp-struct-loop)
|
||||
fields)))
|
||||
(define
|
||||
gp-parse-func-type-params
|
||||
;; Anonymous-only func-type params: caller is positioned BEFORE
|
||||
@@ -204,6 +247,10 @@
|
||||
(let ((params (gp-parse-func-type-params)))
|
||||
(let ((results (gp-parse-func-type-results)))
|
||||
(list :ty-func params results))))
|
||||
(and (= (gp-tok-type) "keyword") (= (gp-tok-value) "struct"))
|
||||
(do
|
||||
(gp-advance!)
|
||||
(list :ty-struct (gp-parse-struct-fields)))
|
||||
(= (gp-tok-type) "ident")
|
||||
(let ((name (gp-tok-value)))
|
||||
(gp-advance!)
|
||||
|
||||
Reference in New Issue
Block a user