ruby: WIP — parser Phase 1 in-progress changes (save before session close)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 46s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 46s
228 insertions, 75 deletions on lib/ruby/parser.sx. Work mid-flight when the tmux session was wrapped up. Saving here so it isn't lost; not validated, not under test. Pick up from here when the Ruby loop resumes.
This commit is contained in:
@@ -725,84 +725,237 @@
|
||||
(rb-p-advance!)
|
||||
{:type "massign" :targets targets :value (rb-p-parse-multi-val)})))
|
||||
|
||||
|
||||
;; if cond [then] body [elsif cond [then] body ...] [else body] end
|
||||
(define rb-p-parse-if
|
||||
(fn ()
|
||||
(rb-p-advance!)
|
||||
(let ((cond-val (rb-p-parse-expr)))
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "then"))
|
||||
(rb-p-advance!))
|
||||
(rb-p-skip-seps!)
|
||||
(let ((then-body (rb-p-parse-stmts (list "end" "else" "elsif"))))
|
||||
(let ((elsifs (list)) (else-body nil))
|
||||
(define rb-p-elsif-loop
|
||||
(fn ()
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "elsif"))
|
||||
(do
|
||||
(rb-p-advance!)
|
||||
(let ((ec (rb-p-parse-expr)))
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "then"))
|
||||
(rb-p-advance!))
|
||||
(rb-p-skip-seps!)
|
||||
(let ((eb (rb-p-parse-stmts (list "end" "else" "elsif"))))
|
||||
(append! elsifs {:cond ec :then eb})
|
||||
(rb-p-elsif-loop)))))))
|
||||
(rb-p-elsif-loop)
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "else"))
|
||||
(do
|
||||
(rb-p-advance!)
|
||||
(rb-p-skip-seps!)
|
||||
(set! else-body (rb-p-parse-stmts (list "end")))))
|
||||
(rb-p-expect-kw! "end")
|
||||
{:type "if" :cond cond-val :then then-body
|
||||
:elsif elsifs :else else-body})))))
|
||||
|
||||
;; unless cond [then] body [else body] end
|
||||
(define rb-p-parse-unless
|
||||
(fn ()
|
||||
(rb-p-advance!)
|
||||
(let ((cond-val (rb-p-parse-expr)))
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "then"))
|
||||
(rb-p-advance!))
|
||||
(rb-p-skip-seps!)
|
||||
(let ((then-body (rb-p-parse-stmts (list "end" "else"))))
|
||||
(let ((else-body nil))
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "else"))
|
||||
(do
|
||||
(rb-p-advance!)
|
||||
(rb-p-skip-seps!)
|
||||
(set! else-body (rb-p-parse-stmts (list "end")))))
|
||||
(rb-p-expect-kw! "end")
|
||||
{:type "unless" :cond cond-val :then then-body :else else-body})))))
|
||||
|
||||
;; while cond [do] body end
|
||||
(define rb-p-parse-while
|
||||
(fn ()
|
||||
(rb-p-advance!)
|
||||
(let ((cond-val (rb-p-parse-expr)))
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "do"))
|
||||
(rb-p-advance!))
|
||||
(rb-p-skip-seps!)
|
||||
(let ((body (rb-p-parse-stmts (list "end"))))
|
||||
(rb-p-expect-kw! "end")
|
||||
{:type "while" :cond cond-val :body body}))))
|
||||
|
||||
;; until cond [do] body end
|
||||
(define rb-p-parse-until
|
||||
(fn ()
|
||||
(rb-p-advance!)
|
||||
(let ((cond-val (rb-p-parse-expr)))
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "do"))
|
||||
(rb-p-advance!))
|
||||
(rb-p-skip-seps!)
|
||||
(let ((body (rb-p-parse-stmts (list "end"))))
|
||||
(rb-p-expect-kw! "end")
|
||||
{:type "until" :cond cond-val :body body}))))
|
||||
|
||||
;; for var in iter [do] body end
|
||||
(define rb-p-parse-for
|
||||
(fn ()
|
||||
(rb-p-advance!)
|
||||
(let ((var (rb-p-val)))
|
||||
(rb-p-advance!)
|
||||
(rb-p-expect-kw! "in")
|
||||
(let ((iter (rb-p-parse-expr)))
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "do"))
|
||||
(rb-p-advance!))
|
||||
(rb-p-skip-seps!)
|
||||
(let ((body (rb-p-parse-stmts (list "end"))))
|
||||
(rb-p-expect-kw! "end")
|
||||
{:type "for" :var var :iter iter :body body})))))
|
||||
|
||||
;; case [expr] when val[, val] [then] body... [else body] end
|
||||
(define rb-p-parse-case
|
||||
(fn ()
|
||||
(rb-p-advance!)
|
||||
(let ((case-val (if (rb-p-sep?) nil (rb-p-parse-expr))))
|
||||
(rb-p-skip-seps!)
|
||||
(let ((whens (list)) (else-body nil))
|
||||
(define rb-p-when-loop
|
||||
(fn ()
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "when"))
|
||||
(do
|
||||
(rb-p-advance!)
|
||||
(let ((wvals (list)))
|
||||
(define rb-p-wval-loop
|
||||
(fn ()
|
||||
(append! wvals (rb-p-parse-assign))
|
||||
(when (= (rb-p-type) "comma")
|
||||
(do (rb-p-advance!) (rb-p-skip-newlines!) (rb-p-wval-loop)))))
|
||||
(rb-p-wval-loop)
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "then"))
|
||||
(rb-p-advance!))
|
||||
(rb-p-skip-seps!)
|
||||
(let ((wb (rb-p-parse-stmts (list "end" "else" "when"))))
|
||||
(append! whens {:values wvals :body wb})
|
||||
(rb-p-when-loop)))))))
|
||||
(rb-p-when-loop)
|
||||
(when (and (= (rb-p-type) "keyword") (= (rb-p-val) "else"))
|
||||
(do
|
||||
(rb-p-advance!)
|
||||
(rb-p-skip-seps!)
|
||||
(set! else-body (rb-p-parse-stmts (list "end")))))
|
||||
(rb-p-expect-kw! "end")
|
||||
{:type "case" :value case-val :whens whens :else else-body}))))
|
||||
|
||||
(define rb-p-parse-stmt
|
||||
(fn ()
|
||||
(cond
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "def"))
|
||||
(rb-p-parse-def))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "class"))
|
||||
(rb-p-parse-class))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "module"))
|
||||
(rb-p-parse-module))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "return"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "return"
|
||||
:value (if (or (rb-p-sep?) (= (rb-p-type) "eof"))
|
||||
nil (rb-p-parse-multi-val))}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "yield"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "yield"
|
||||
:args (cond
|
||||
((= (rb-p-type) "lparen") (rb-p-parse-args-parens))
|
||||
((or (rb-p-sep?) (= (rb-p-type) "eof")) (list))
|
||||
(:else (rb-p-parse-args-bare)))}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "break"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "break"
|
||||
:value (if (or (rb-p-sep?) (= (rb-p-type) "eof"))
|
||||
nil (rb-p-parse-expr))}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "next"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "next"
|
||||
:value (if (or (rb-p-sep?) (= (rb-p-type) "eof"))
|
||||
nil (rb-p-parse-expr))}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "redo"))
|
||||
(do (rb-p-advance!) {:type "redo"}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "raise"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "raise"
|
||||
:value (if (or (rb-p-sep?) (= (rb-p-type) "eof"))
|
||||
nil (rb-p-parse-expr))}))
|
||||
;; Massign: token followed by comma
|
||||
((and (or (= (rb-p-type) "ident") (= (rb-p-type) "ivar")
|
||||
(= (rb-p-type) "cvar") (= (rb-p-type) "gvar")
|
||||
(= (rb-p-type) "const"))
|
||||
(= (get (rb-p-peek 1) :type) "comma"))
|
||||
(rb-p-parse-massign))
|
||||
(:else
|
||||
(let ((node (rb-p-parse-assign)))
|
||||
(if (and (= (get node :type) "send")
|
||||
(= (len (get node :args)) 0)
|
||||
(nil? (get node :block)))
|
||||
;; Bare send: check for block or no-paren args
|
||||
(let ((node
|
||||
(cond
|
||||
;; Block immediately follows (do or {)
|
||||
((or (and (= (rb-p-type) "keyword") (= (rb-p-val) "do"))
|
||||
(= (rb-p-type) "lbrace"))
|
||||
(let ((blk (rb-p-parse-block)))
|
||||
{:type "send" :name (get node :name) :args (list) :block blk}))
|
||||
;; No-paren args (stop before block/sep/end keywords)
|
||||
((and (not (rb-p-sep?))
|
||||
(not (= (rb-p-type) "eof"))
|
||||
(not (= (rb-p-type) "op"))
|
||||
(not (= (rb-p-type) "dot"))
|
||||
(not (= (rb-p-type) "dcolon"))
|
||||
(not (= (rb-p-type) "rparen"))
|
||||
(not (= (rb-p-type) "rbracket"))
|
||||
(not (= (rb-p-type) "rbrace"))
|
||||
(not (= (rb-p-type) "lbrace"))
|
||||
(not (and (= (rb-p-type) "keyword")
|
||||
(contains? (list "end" "else" "elsif" "when"
|
||||
"rescue" "ensure" "then" "do"
|
||||
"and" "or" "not")
|
||||
(rb-p-val)))))
|
||||
(let ((args (rb-p-parse-args-bare))
|
||||
(blk (rb-p-parse-block)))
|
||||
(if (> (len args) 0)
|
||||
{:type "send" :name (get node :name) :args args :block blk}
|
||||
node)))
|
||||
(:else node))
|
||||
node))))))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "def"))
|
||||
(rb-p-parse-def))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "class"))
|
||||
(rb-p-parse-class))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "module"))
|
||||
(rb-p-parse-module))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "if"))
|
||||
(rb-p-parse-if))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "unless"))
|
||||
(rb-p-parse-unless))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "while"))
|
||||
(rb-p-parse-while))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "until"))
|
||||
(rb-p-parse-until))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "case"))
|
||||
(rb-p-parse-case))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "for"))
|
||||
(rb-p-parse-for))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "return"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "return"
|
||||
:value (if (or (rb-p-sep?) (= (rb-p-type) "eof"))
|
||||
nil (rb-p-parse-multi-val))}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "yield"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "yield"
|
||||
:args (cond
|
||||
((= (rb-p-type) "lparen") (rb-p-parse-args-parens))
|
||||
((or (rb-p-sep?) (= (rb-p-type) "eof")) (list))
|
||||
(:else (rb-p-parse-args-bare)))}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "break"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "break"
|
||||
:value (if (or (rb-p-sep?) (= (rb-p-type) "eof"))
|
||||
nil (rb-p-parse-expr))}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "next"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "next"
|
||||
:value (if (or (rb-p-sep?) (= (rb-p-type) "eof"))
|
||||
nil (rb-p-parse-expr))}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "redo"))
|
||||
(do (rb-p-advance!) {:type "redo"}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "raise"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "raise"
|
||||
:value (if (or (rb-p-sep?) (= (rb-p-type) "eof"))
|
||||
nil (rb-p-parse-expr))}))
|
||||
;; Massign: token followed by comma
|
||||
((and (or (= (rb-p-type) "ident") (= (rb-p-type) "ivar")
|
||||
(= (rb-p-type) "cvar") (= (rb-p-type) "gvar")
|
||||
(= (rb-p-type) "const"))
|
||||
(= (get (rb-p-peek 1) :type) "comma"))
|
||||
(rb-p-parse-massign))
|
||||
(:else
|
||||
(let ((nd (rb-p-parse-assign)))
|
||||
(if (and (= (get nd :type) "send")
|
||||
(= (len (get nd :args)) 0)
|
||||
(nil? (get nd :block)))
|
||||
(cond
|
||||
((or (and (= (rb-p-type) "keyword") (= (rb-p-val) "do"))
|
||||
(= (rb-p-type) "lbrace"))
|
||||
(let ((blk (rb-p-parse-block)))
|
||||
{:type "send" :name (get nd :name)
|
||||
:args (list) :block blk}))
|
||||
((and (not (rb-p-sep?))
|
||||
(not (= (rb-p-type) "eof"))
|
||||
(not (= (rb-p-type) "op"))
|
||||
(not (= (rb-p-type) "dot"))
|
||||
(not (= (rb-p-type) "dcolon"))
|
||||
(not (= (rb-p-type) "rparen"))
|
||||
(not (= (rb-p-type) "rbracket"))
|
||||
(not (= (rb-p-type) "rbrace"))
|
||||
(not (= (rb-p-type) "lbrace"))
|
||||
(not (and (= (rb-p-type) "keyword")
|
||||
(contains? (list "end" "else" "elsif"
|
||||
"when" "rescue" "ensure"
|
||||
"then" "do" "and" "or"
|
||||
"not" "if" "unless"
|
||||
"while" "until")
|
||||
(rb-p-val)))))
|
||||
(let ((args (rb-p-parse-args-bare))
|
||||
(blk (rb-p-parse-block)))
|
||||
(if (> (len args) 0)
|
||||
{:type "send" :name (get nd :name)
|
||||
:args args :block blk}
|
||||
nd)))
|
||||
(:else nd))
|
||||
nd))))))
|
||||
;; Postfix modifiers
|
||||
(cond
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "if"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "postfix-if" :cond (rb-p-parse-expr) :body node}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "unless"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "postfix-unless" :cond (rb-p-parse-expr) :body node}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "while"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "postfix-while" :cond (rb-p-parse-expr) :body node}))
|
||||
((and (= (rb-p-type) "keyword") (= (rb-p-val) "until"))
|
||||
(do (rb-p-advance!)
|
||||
{:type "postfix-until" :cond (rb-p-parse-expr) :body node}))
|
||||
(:else node)))))
|
||||
|
||||
(define rb-p-parse-stmts
|
||||
(fn (terminators)
|
||||
|
||||
Reference in New Issue
Block a user