From c2dcc94ce21b1ff30a019b137e04264031030996 Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 25 Apr 2026 19:03:07 +0000 Subject: [PATCH] HS: parse socket feature --- lib/hyperscript/parser.sx | 100 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/lib/hyperscript/parser.sx b/lib/hyperscript/parser.sx index 0c337953..ae6af71f 100644 --- a/lib/hyperscript/parser.sx +++ b/lib/hyperscript/parser.sx @@ -2729,6 +2729,105 @@ (match-kw "end") (list (quote when-feat-no-op))))) (do (pwf-skip) (match-kw "end") (list (quote when-feat-no-op)))))) + (define + parse-socket-feat + (fn + () + ;; Collect name-path: ident (class)* → e.g. ["Foo"] or ["MyApp" "chat"] + (let + ((seg0 (tp-val))) + (adv!) + (define + collect-segs + (fn + (acc) + (if + (= (tp-type) "class") + (let + ((seg (tp-val))) + (adv!) + (collect-segs (append acc (list seg)))) + acc))) + (let + ((name-path (collect-segs (list seg0)))) + ;; url-cont?: token types that can appear inside a URL + (define + url-cont? + (fn + () + (or + (= (tp-type) "ident") + (= (tp-type) "number") + (= (tp-type) "op") + (= (tp-type) "colon") + (= (tp-type) "dot") + (and + (= (tp-type) "keyword") + (not + (or + (= (tp-val) "end") + (= (tp-val) "with") + (= (tp-val) "on") + (= (tp-val) "as"))))))) + ;; collect-url: accumulate URL tokens into a joined string + (define + collect-url + (fn + (parts) + (if + (and (not (at-end?)) (url-cont?)) + (let + ((v (tp-val))) + (adv!) + (collect-url (append parts (list v)))) + (join "" parts)))) + ;; Parse URL: /path, scheme://..., string literal, or expression + (let + ((url + (cond + ;; Relative path starting with / + ((and (= (tp-type) "op") (= (tp-val) "/")) + (adv!) + (collect-url (list "/"))) + ;; Absolute URL: ident + colon → collect as scheme:rest + ((= (tp-type) "ident") + (let + ((scheme (tp-val))) + (adv!) + (if + (= (tp-type) "colon") + (collect-url (list scheme)) + (parse-arith (parse-poss (list (quote ref) scheme)))))) + ;; String literal or other expression + (true (parse-atom))))) + ;; Optional: with timeout + (let + ((timeout-ms + (if + (match-kw "with") + (do + (adv!) + (parse-expr)) + nil))) + ;; Optional: on message [as JSON] + (let + ((on-msg + (if + (match-kw "on") + (do + (adv!) + (let + ((json? + (if + (match-kw "as") + (do (adv!) true) + false))) + (let + ((body (parse-cmd-list))) + (list (quote on-message) json? body)))) + nil))) + (match-kw "end") + (list (quote socket) name-path url timeout-ms on-msg)))))))) (define parse-feat (fn @@ -2749,6 +2848,7 @@ ((= val "behavior") (do (adv!) (parse-behavior-feat))) ((= val "live") (do (adv!) (parse-live-feat))) ((= val "when") (do (adv!) (parse-when-feat))) + ((= val "socket") (do (adv!) (parse-socket-feat))) (true (parse-cmd-list)))))) (define coll-feats