Parse loop/recur, and reindent all the things
This commit is contained in:
parent
e7eccca000
commit
362e76c323
|
@ -594,6 +594,69 @@
|
|||
|
||||
(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]
|
||||
(let [expr (if
|
||||
(contains? #{::token/else ::token/placeholder} (token-type parser))
|
||||
|
@ -791,6 +854,10 @@
|
|||
|
||||
::token/ref (parse-ref parser)
|
||||
|
||||
::token/loop (parse-loop parser)
|
||||
|
||||
::token/recur (parse-recur parser)
|
||||
|
||||
;; TODO: improve handling of comments?
|
||||
;; Scanner now just skips comments
|
||||
;; ::token/comment (advance parser)
|
||||
|
@ -813,7 +880,13 @@
|
|||
|
||||
(do
|
||||
(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))
|
||||
|
|
Loading…
Reference in New Issue
Block a user