Parse loop/recur, and reindent all the things

This commit is contained in:
Scott Richmond 2022-05-18 18:32:57 -04:00
parent e7eccca000
commit 362e76c323

View File

@ -594,6 +594,69 @@
(panic parser "Expected with after match expression")))) (panic parser "Expected with after match expression"))))
(defn- parse-loop-clause [parser]
(if (not (= ::token/lparen (token-type parser)))
(panic parser "Loop clauses must begin with tuple patterns")
(let [pattern (parse-tuple-pattern parser)
arrow (expect* #{::token/rarrow} "Expected arrow" pattern)
body (parse-expr (:parser arrow))]
(if (:success arrow)
(assoc body ::ast {::ast/type ::ast/clause
:pattern (::ast pattern) :body (::ast body)})
(panic pattern "Expected -> in loop clause. Clauses must be in the form of (pattern) -> expression")))))
(defn- parse-loop-clauses [parser]
(loop [parser (accept-many #{::token/newline} (advance parser))
clauses []]
(let [curr (current parser)]
(case (::token/type curr)
::token/rbrace
(if (< 0 (count clauses))
(assoc (advance parser) ::ast {::ast/type ::ast/clauses :clauses clauses})
(panic parser "Expected one or more loop clauses" #{::token/rbrace}))
::token/newline
(recur (accept-many #{::token/newline} parser) clauses)
(let [clause (parse-loop-clause parser)]
(recur (accept-many #{::token/newline} clause) (conj clauses (::ast clause))))))))
(defn- parse-loop [parser]
(let [next (advance parser)]
(if (= ::token/lparen (token-type next))
(let [loop-tup (parse-tuple (advance next))
loop-header (expect* #{::token/with} "Expected with" loop-tup)]
(if (:success loop-header)
(let [clauses (:parser loop-header)]
(if (= (token-type clauses) ::token/lbrace)
;; loop expression with one or many clauses in braces
(let [clauses (parse-loop-clauses clauses)]
(assoc clauses ::ast {::ast/type ::ast/loop
:expr (::ast loop-tup)
:clauses (get-in clauses [::ast :clauses])}))
;; loop expression with single match clause
(let [clause (parse-loop-clause clauses)]
(assoc clause ::ast {::ast/type ::ast/loop
:expr (::ast loop-tup)
:clauses [(::ast clause)]}))))
(panic parser "Expected with after loop expression")))
(panic parser "Expected tuple as loop expression")
)))
(defn- parse-recur [parser]
(let [next (advance parser)]
(if (= ::token/lparen (token-type next))
(let [tuple (parse-tuple (advance next))]
(assoc tuple ::ast {::ast/type ::ast/recur
:tuple (::ast tuple)})
)
(panic parser "Expected tuple after recur")
)
)
)
(defn- parse-cond-clause [parser] (defn- parse-cond-clause [parser]
(let [expr (if (let [expr (if
(contains? #{::token/else ::token/placeholder} (token-type parser)) (contains? #{::token/else ::token/placeholder} (token-type parser))
@ -791,6 +854,10 @@
::token/ref (parse-ref parser) ::token/ref (parse-ref parser)
::token/loop (parse-loop parser)
::token/recur (parse-recur parser)
;; TODO: improve handling of comments? ;; TODO: improve handling of comments?
;; Scanner now just skips comments ;; Scanner now just skips comments
;; ::token/comment (advance parser) ;; ::token/comment (advance parser)
@ -813,7 +880,13 @@
(do (do
(def pp pp/pprint) (def pp pp/pprint)
(def source "ref foo = 42 (def source "loop (10) with {
(0) -> print (:boom)
(n) -> {
print (:tick)
recur (dec (n))
}
}
") ")
(def lexed (scanner/scan source)) (def lexed (scanner/scan source))