Parse multi-clause match expressions
This commit is contained in:
parent
e4e984bacd
commit
069e3b4a7b
|
@ -448,24 +448,48 @@
|
|||
|
||||
(defn- parse-match-clause [parser]
|
||||
(let [pattern (parse-pattern parser)
|
||||
rarrow (expect* #{::token/rarrow} "Expected arrow in match clause" pattern)
|
||||
rarrow (expect* #{::token/rarrow} "Expected arrow after pattern" pattern)
|
||||
]
|
||||
(if (:success rarrow)
|
||||
(let [body (parse-expr (:parser rarrow))]
|
||||
(assoc body ::ast {::ast/type ::ast/clause
|
||||
:pattern (::ast pattern) :body (::ast body)})
|
||||
)
|
||||
(panic rarrow "Expected -> in match clause. Clauses must be in the form pattern -> expression")
|
||||
(panic pattern "Expected -> in match clause. Clauses must be in the form pattern -> expression" #{::token/newline ::token/rbrace})
|
||||
)
|
||||
))
|
||||
|
||||
(defn- parse-match-clauses [parser]
|
||||
(loop [
|
||||
parser (accept-many #{::token/newline} (advance parser))
|
||||
clauses []]
|
||||
(let [curr (current parser)]
|
||||
(case (::token/type curr)
|
||||
::token/rbrace
|
||||
(assoc parser ::ast {::ast/type ::ast/clauses :clauses clauses})
|
||||
|
||||
::token/newline
|
||||
(recur (accept-many #{::token/newline} parser) clauses)
|
||||
|
||||
(let [clause (parse-match-clause parser)]
|
||||
(recur (accept-many #{::token/newline} clause) (conj clauses (::ast clause)))
|
||||
)
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
(defn- parse-match [parser]
|
||||
(let [match-expr (parse-expr (advance parser) #{::token/lbrace ::token/lparen})
|
||||
(let [match-expr (parse-expr (advance parser) #{::token/with})
|
||||
match-header (expect* #{::token/with} "Expected with" match-expr)]
|
||||
(if (:success match-header)
|
||||
(let [clauses (:parser match-header)]
|
||||
(if (= (token-type clauses) ::token/lbrace)
|
||||
(println "one or many clauses")
|
||||
;; match expression with one or many clauses in braces
|
||||
(let [clauses (parse-match-clauses clauses)]
|
||||
(assoc clauses ::ast {::ast/type ::ast/match
|
||||
:expr (::ast match-expr)
|
||||
:clauses (get-in clauses [::ast :clauses])}))
|
||||
;; match expression with single match clause
|
||||
(let [clause (parse-match-clause clauses)]
|
||||
(assoc clause ::ast {::ast/type ::ast/match
|
||||
:expr (::ast match-expr)
|
||||
|
@ -478,19 +502,22 @@
|
|||
|
||||
(defn- parse-expr
|
||||
([parser] (parse-expr parser sync-on))
|
||||
([parser sync-on] (let [token (current parser)]
|
||||
([parser sync-on]
|
||||
(let [token (current parser)]
|
||||
(case (::token/type token)
|
||||
|
||||
(::token/number ::token/string)
|
||||
(parse-atom parser)
|
||||
|
||||
::token/keyword (let [next (peek parser)
|
||||
::token/keyword
|
||||
(let [next (peek parser)
|
||||
type (::token/type next)]
|
||||
(if (= type ::token/lparen)
|
||||
(parse-synthetic parser)
|
||||
(parse-atom parser)))
|
||||
|
||||
::token/word (let [next (peek parser)
|
||||
::token/word
|
||||
(let [next (peek parser)
|
||||
type (::token/type next)]
|
||||
(case type
|
||||
(::token/lparen ::token/keyword) (parse-synthetic parser)
|
||||
|
@ -534,14 +561,14 @@
|
|||
(:tokens)
|
||||
(parser)
|
||||
(parse-script)
|
||||
))
|
||||
))
|
||||
|
||||
(do
|
||||
(def pp pp/pprint)
|
||||
(def source "match foo with (foo, bar, 0) -> {
|
||||
let foo = bar
|
||||
if foo then bar else baz
|
||||
:foo
|
||||
(def source "match foo with {
|
||||
_ -> foo
|
||||
foo () -> bar
|
||||
() -> baz
|
||||
}")
|
||||
(def lexed (scanner/scan source))
|
||||
(def tokens (:tokens lexed))
|
||||
|
|
Loading…
Reference in New Issue
Block a user