Improve parse-script; start work on let and pattern

This commit is contained in:
Scott Richmond 2022-02-21 15:38:47 -05:00
parent 8ec432c7a0
commit f96ec45d1b

View File

@ -3,7 +3,8 @@
[ludus.token :as token] [ludus.token :as token]
[ludus.scanner :as scanner] [ludus.scanner :as scanner]
[ludus.ast :as ast] [ludus.ast :as ast]
[clojure.pprint :as pp])) [clojure.pprint :as pp]
[clojure.set :as s]))
;; a parser map and some functions to work with them ;; a parser map and some functions to work with them
(defn- parser [tokens] (defn- parser [tokens]
@ -232,7 +233,9 @@
}))) })))
(::token/semicolon ::token/newline) (::token/semicolon ::token/newline)
(recur (advance parser) (add-member exprs current_expr) nil) (recur
(accept-many #{::token/newline ::token/semicolon} parser)
(add-member exprs current_expr) nil)
(::token/rbracket ::token/rparen) (::token/rbracket ::token/rparen)
(panic parser (str "Mismatched enclosure in block: " (::token/lexeme curr))) (panic parser (str "Mismatched enclosure in block: " (::token/lexeme curr)))
@ -245,37 +248,34 @@
(if current_expr (if current_expr
(panic parser "Expected end of expression" #{::token/semicolon ::token/newline}) (panic parser "Expected end of expression" #{::token/semicolon ::token/newline})
(parse-expr parser))] (parse-expr parser))]
(recur parsed exprs (::ast parsed)) (recur parsed exprs (::ast parsed)))))))
)
)
)
))
(defn- parse-script [parser] (defn- parse-script* [parser]
(loop [parser parser (loop [
parser (accept-many #{::token/newline ::token/semicolon} parser)
exprs [] exprs []
current_expr nil] current_expr nil
(if (at-end? parser) ]
(assoc parser ::ast (let [curr (current parser)]
{::ast/type ::ast/script :exprs (add-member exprs current_expr)}) (case (token-type parser)
(case (::token/type (current parser)) ::token/eof (let [es (add-member exprs current_expr)]
::token/eof (assoc parser ::ast (if (empty? es)
{::ast/type ::ast/script :exprs (add-member exprs current_expr)}) (panic parser "Scripts must have at least one expression")
(assoc parser ::ast {::ast/type ::ast/script :exprs es})))
(::token/semicolon ::token/newline) (::token/semicolon ::token/newline)
(recur (advance parser) (add-member exprs current_expr) nil) (recur
(accept-many #{::token/semicolon ::token/newline} parser)
(add-member exprs current_expr)
nil)
(if current_expr (let [parsed
(if (poisoned? current_expr) (if current_expr
(panic parser (:message current_expr) #{::token/newline ::token/semicolon}) (panic parser "Expected end of expression" #{::token/semicolon ::token/newline})
(let [synced (panic parser "Expected end of expression" #{::token/newline ::token/semicolon})] (parse-expr parser)
(recur synced exprs (::ast synced)) )
)) ]
(let [parsed (parse-expr parser)] (recur parsed exprs (::ast parsed)))))))
(recur parsed exprs (::ast parsed))
))
))))
(defn- parse-synthetic [parser] (defn- parse-synthetic [parser]
(loop [parser parser (loop [parser parser
@ -304,6 +304,8 @@
(advance) (advance)
(assoc ::ast {::ast/type ::ast/word :word (::token/lexeme curr)})))) (assoc ::ast {::ast/type ::ast/word :word (::token/lexeme curr)}))))
(def sync-pattern (s/union sync-on #{::token/equals ::token/rarrow}))
(defn- parse-pattern [parser] (defn- parse-pattern [parser]
(let [curr (current parser) (let [curr (current parser)
type (::token/type curr)] type (::token/type curr)]
@ -312,9 +314,11 @@
(::token/number ::token/string ::token/keyword) (parse-atom parser) (::token/number ::token/string ::token/keyword) (parse-atom parser)
(-> parser
(advance) ::token/error
(assoc ::ast {::ast/type ::ast/poison :message "Expected pattern"})) (panic parser (:message (current parser)) sync-pattern)
(panic parser "Expected pattern" sync-pattern)
))) )))
(defn- parse-let-expr [parser pattern] (defn- parse-let-expr [parser pattern]
@ -330,9 +334,7 @@
(defn- parse-let [parser] (defn- parse-let [parser]
(let [pattern (parse-pattern (advance parser))] (let [pattern (parse-pattern (advance parser))]
(if (poisoned? pattern) (parse-assignment pattern)))
(panic parser (get-in pattern [::ast :message]) #{::token/newline ::token/semicolon})
(parse-assignment pattern))))
(defn- parse-if [parser] (defn- parse-if [parser]
(let [ (let [
@ -401,15 +403,20 @@
(do (do
(def pp pp/pprint) (def pp pp/pprint)
(def source "{ 1; 2; \"foo (def source "let foo^ = bar")
}")
(def lexed (scanner/scan source)) (def lexed (scanner/scan source))
(def tokens (:tokens lexed)) (def tokens (:tokens lexed))
(def p (parser tokens)) (def p (parser tokens))
(println "")
(println "")
(println "******************************************************")
(println "")
(println "*** *** NEW PARSE *** ***")
(-> p (-> p
(parse-script) (parse-script*)
(::errors) (::ast)
(pp) (pp)
) )
) )