Parse cond

This commit is contained in:
Scott Richmond 2022-04-06 19:21:49 -04:00
parent e6419f6b6a
commit 03713c67bc

View File

@ -501,7 +501,9 @@
(let [curr (current parser)] (let [curr (current parser)]
(case (::token/type curr) (case (::token/type curr)
::token/rbrace ::token/rbrace
(if (< 0 (count clauses))
(assoc (advance parser) ::ast {::ast/type ::ast/clauses :clauses clauses}) (assoc (advance parser) ::ast {::ast/type ::ast/clauses :clauses clauses})
(panic parser "Expected one or more clauses" #{::rbrace}))
::token/newline ::token/newline
(recur (accept-many #{::token/newline} parser) clauses) (recur (accept-many #{::token/newline} parser) clauses)
@ -528,6 +530,47 @@
(panic parser "Expected with after match expression")))) (panic parser "Expected with after match expression"))))
(defn- parse-cond-clause [parser]
(let [expr (parse-expr parser)
rarrow (expect* #{::token/rarrow} "Expected arrow after expression in cond clause" expr)]
(if (:success rarrow)
(let [body (parse-expr (:parser rarrow))]
(assoc body ::ast {::ast/type ::ast/clause
:test (::ast expr) :body (::ast body)}))
(panic expr "Expected -> in cond clause. Clauses must be in the form test_expression -> result_expression" #{::token/newline ::token/rbrace}))))
(defn- parse-cond-clauses [parser]
(loop [parser (accept-many #{::token/newline} parser)
clauses []]
(let [curr (current parser)]
(println "parsing a clause: " curr)
(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 clauses" #{::rbrace}))
::token/newline
(recur (accept-many #{::token/newline} parser) clauses)
(let [clause (parse-cond-clause parser)]
(recur (accept-many #{::token/newline} clause) (conj clauses (::ast clause))))))))
(defn- parse-cond [parser]
(let [header
(expect* #{::token/lbrace} "Expected { after cond" (advance parser))]
(if (:success header)
(let [clauses (parse-cond-clauses (:parser header))]
(println "Found all the clauses")
(assoc clauses ::ast {::ast/type ::ast/cond
:clauses (get-in clauses [::ast :clauses])})
)
(panic parser "Expected { after cond")
)
)
)
(defn- parse-fn-clause [parser] (defn- parse-fn-clause [parser]
(if (not (= ::token/lparen (token-type parser))) (if (not (= ::token/lparen (token-type parser)))
(panic parser "Function clauses must begin with tuple patterns") (panic parser "Function clauses must begin with tuple patterns")
@ -545,7 +588,9 @@
(let [curr (current parser)] (let [curr (current parser)]
(case (::token/type curr) (case (::token/type curr)
::token/rbrace ::token/rbrace
(if (< 0 (count clauses))
(assoc (advance parser) ::ast {::ast/type ::ast/clauses :clauses clauses}) (assoc (advance parser) ::ast {::ast/type ::ast/clauses :clauses clauses})
(panic parser "Expected one or more function clauses" #{::token/rbrace}))
::token/newline ::token/newline
(recur (accept-many #{::token/newline} parser) clauses) (recur (accept-many #{::token/newline} parser) clauses)
@ -644,6 +689,8 @@
::token/do (parse-do parser) ::token/do (parse-do parser)
::token/cond (parse-cond 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)
@ -664,9 +711,9 @@
(parser) (parser)
(parse-script))) (parse-script)))
(comment (do
(def pp pp/pprint) (def pp pp/pprint)
(def source "foo (1, 2, _) (def source "cond {}
") ")
(def lexed (scanner/scan source)) (def lexed (scanner/scan source))
@ -680,7 +727,7 @@
(println "*** *** NEW PARSE *** ***") (println "*** *** NEW PARSE *** ***")
(-> p (-> p
(parse-expr) (parse-script)
(::ast) (::ast)
(pp))) (pp)))