Add splats to list patterns in parser

This commit is contained in:
Scott Richmond 2022-06-19 14:48:53 -04:00
parent 4254359934
commit 68bc37ef61

View File

@ -484,17 +484,45 @@
(def sync-pattern (s/union sync-on #{::token/equals ::token/rarrow}))
(defn- parse-splat-pattern [origin]
(let [splatted (advance origin)]
(case (token-type splatted)
::token/word
(assoc (advance splatted) ::ast
{::ast/type ::ast/splat
:token (current origin)
:into (::ast (parse-word splatted))})
::token/placeholder
(assoc (advance splatted) ::ast
{::ast/type ::ast/splat
:token (current origin)
:into {::ast/type ::ast/placeholder :token (current splatted)}})
(::token/comma ::token/newline ::token/rbrace ::token/rparen ::token/rbracket)
(assoc splatted ::ast
{::ast/type ::ast/splat
:token (current origin)
:into {::ast/type ::ast/placeholder :token (current origin)}})
(panic origin "Splat patterns may only splat into words or placeholders.")
)))
(defn- parse-list-pattern [origin]
(loop [parser (accept-many #{::token/newline ::token/comma} (advance origin))
members []
current_member nil]
(let [curr (current parser)]
(case (token-type parser)
::token/rbracket (let [ms (add-member members current_member)]
::token/rbracket
(let [ms (add-member members current_member)]
(if (not-any? #(= (::ast/type %) ::ast/splat) (drop-last ms))
(assoc (advance parser) ::ast
{::ast/type ::ast/list
{::ast/type ::ast/tuple
:token (current origin)
:members ms}))
:length (count ms)
:members ms})
(panic parser "A splat my only appear once in a pattern, at the end of a pattern.")))
(::token/comma ::token/newline)
(recur
@ -507,6 +535,10 @@
::token/eof
(panic (assoc origin ::errors (::errors parser)) "Unterminated list pattern" ::token/eof)
::token/splat
(let [splatted (parse-splat-pattern parser)]
(recur splatted members (::ast splatted)))
(let [parsed (parse-pattern parser)]
(recur parsed members (::ast parsed)))))))
@ -584,19 +616,22 @@
(panic parser "Struct patterns may only include single words or keyword+pattern pairs." #{::token/rbrace})))))
(defn- parse-tuple-pattern [origin]
(loop [parser (accept-many #{::token/newline ::token/comma} (advance origin))
members []
current_member nil]
(let [curr (current parser)]
(case (token-type parser)
::token/rparen (let [ms (add-member members current_member)]
::token/rparen
(let [ms (add-member members current_member)]
(assoc (advance parser) ::ast
{::ast/type ::ast/tuple
:token (current origin)
:length (count ms)
:members ms}))
(::token/comma ::token/newline)
(recur
(accept-many #{::token/comma ::token/newline} parser)
@ -1070,10 +1105,9 @@
(parser)
(parse-script)))
(comment
(do
(def pp pp/pprint)
(def source "if let foo = bar then foo else bar")
(def source "let [a, b, (c, d), ...e] = [1, 2, (4, 5), 6]")
(println "")
(println "")