Finally get it right?

This commit is contained in:
Scott Richmond 2023-05-20 14:18:30 -04:00
parent 4ea7a3a23d
commit 4fd593752b
2 changed files with 63 additions and 24 deletions

View File

@ -22,7 +22,7 @@
(def tuple-pattern-term (flat (choice :tuple-pattern-term [pattern splattern]))) (def tuple-pattern-term (flat (choice :tuple-pattern-term [pattern splattern])))
(def tuple-pattern-entry (order-1 :tuple-pattern-entry [tuple-pattern-term (quiet (one+ separator))])) (def tuple-pattern-entry (weak-order :tuple-pattern-entry [tuple-pattern-term separators]))
(def tuple-pattern (group (order-1 :tuple-pattern (def tuple-pattern (group (order-1 :tuple-pattern
[(quiet :lparen) [(quiet :lparen)
@ -40,7 +40,7 @@
(def dict-pattern-term (flat (choice :dict-pattern-term [pair-pattern :word splattern]))) (def dict-pattern-term (flat (choice :dict-pattern-term [pair-pattern :word splattern])))
(def dict-pattern-entry (order-1 :dict-pattern-entry [dict-pattern-term (quiet (one+ separator))])) (def dict-pattern-entry (weak-order :dict-pattern-entry [dict-pattern-term separators]))
(def dict-pattern (group (order-1 :dict-pattern (def dict-pattern (group (order-1 :dict-pattern
[(quiet :startdict) [(quiet :startdict)
@ -63,7 +63,7 @@
(def match-clause (group (order-0 :match-clause (def match-clause (group (order-0 :match-clause
[pattern (maybe constraint) (quiet :rarrow) expression]))) [pattern (maybe constraint) (quiet :rarrow) expression])))
(def match-entry (order-0 :match-entry [match-clause (quiet (one+ terminator))])) (def match-entry (weak-order :match-entry [match-clause terminators]))
(def match (group (order-1 :match (def match (group (order-1 :match
[(quiet :match) expression nls? [(quiet :match) expression nls?
@ -87,7 +87,7 @@
(def cond-clause (group (order-0 :cond-clause [cond-lhs (quiet :rarrow) expression]))) (def cond-clause (group (order-0 :cond-clause [cond-lhs (quiet :rarrow) expression])))
(def cond-entry (order-0 :cond-entry [cond-clause (quiet (one+ terminator))])) (def cond-entry (weak-order :cond-entry [cond-clause terminators]))
(def condd (order-1 :cond [(quiet :cond) (quiet :lbrace) (def condd (order-1 :cond [(quiet :cond) (quiet :lbrace)
(quiet (zero+ terminator)) (quiet (zero+ terminator))
@ -100,7 +100,7 @@
nls? nls?
expression]))) expression])))
(def tuple-entry (order-1 :tuple-entry [expression separators])) (def tuple-entry (weak-order :tuple-entry [expression separators]))
(def tuple (group (order-1 :tuple [(quiet :lparen) (def tuple (group (order-1 :tuple [(quiet :lparen)
(quiet (zero+ separator)) (quiet (zero+ separator))
@ -181,7 +181,7 @@
(def fnn (group (order-1 :fn [(quiet :fn) body]))) (def fnn (group (order-1 :fn [(quiet :fn) body])))
(def block-line (order-1 :block-line [expression terminators])) (def block-line (weak-order :block-line [expression terminators]))
(def block (group (order-1 :block [(quiet :lbrace) (def block (group (order-1 :block [(quiet :lbrace)
(quiet (zero+ terminator)) (quiet (zero+ terminator))
@ -251,7 +251,7 @@
(def toplevel (flat (choice :toplevel [importt nss expression testt]))) (def toplevel (flat (choice :toplevel [importt nss expression testt])))
(def script-line (order-0 :script-line [toplevel terminators])) (def script-line (weak-order :script-line [toplevel terminators]))
(def script (order-0 :script [nls? (def script (order-0 :script [nls?
(one+ script-line) (one+ script-line)
@ -260,20 +260,18 @@
;;;;;;;;;;;;;;;; REPL CRUFT ;;;;;;;;;;;;;;;; REPL CRUFT
;;TODO: improve current bug reporting in the parser
;; --e.g., give functions better names in the stack trace
;; --I think this might require a macro (::facepalm::)
;;TODO: fix forward declaration errors ;;TODO: fix forward declaration errors
;;TODO: in, e.g., script-line (repeated, separated entities -- zero/one+->order), order-0 gives an error before a closing token (in this case, :eof), because it's not a line; but using order-1 parses correctly but swallows orders further down. I need to revisit how no match vs. errors pass through the system, esp. the combination of repeats and orders
(def eg (:tokens (scan/scan (def eg (:tokens (scan/scan
"{1; 2; 3; (1, _)}" "
test \"foo\" bar
"
))) )))
(def result (apply-parser block eg)) (def result (apply-parser script eg))
(defn report [node] (defn report [node]

View File

@ -70,19 +70,15 @@
{:status :none :token (first tokens) :trace [name] :remaining rem-ts} {:status :none :token (first tokens) :trace [name] :remaining rem-ts}
:else (recur rem-ps)))))}) :else (recur rem-ps)))))})
;; TODO - figure out a scheme for zero and one lookahead
;; Lookahead isn't even the right term here
(defn order-1 [name parsers] (defn order-1 [name parsers]
{:name name {:name name
:rule (fn order-fn [tokens] :rule (fn order-fn [tokens]
(let [origin (first tokens) (let [origin (first tokens)
first-result (apply-parser (first parsers) tokens)] first-result (apply-parser (first parsers) tokens)]
(case (:status first-result) (case (:status first-result)
(:err :none) (:err :none)
{:status :none (update (assoc first-result :trace #(conj % name)) :status :none)
:token (first tokens)
:trace [name]
:remaining tokens}
(:ok :quiet :group) (:ok :quiet :group)
(loop [ps (rest parsers) (loop [ps (rest parsers)
@ -122,6 +118,7 @@
(vec (concat results (:data result))) (vec (concat results (:data result)))
res-rem) res-rem)
:quiet (recur (rest ps) results res-rem) :quiet (recur (rest ps) results res-rem)
(:err :none) (:err :none)
(assoc (update result :trace #(conj % name)) :status :err))))))))}) (assoc (update result :trace #(conj % name)) :status :err))))))))})
@ -165,9 +162,55 @@
(vec (concat results (:data result))) (vec (concat results (:data result)))
res-rem) res-rem)
:quiet (recur (rest ps) results res-rem) :quiet (recur (rest ps) results res-rem)
(:err :none)
(:err :none)
(assoc (update result :trace #(conj % name)) :status :err)))))))}) (assoc (update result :trace #(conj % name)) :status :err)))))))})
(defn weak-order [name parsers]
{:name name
:rule (fn order-fn [tokens]
(let [origin (first tokens)]
(loop [ps parsers
results []
ts tokens]
(let [result (apply-parser (first ps) ts)
res-rem (remaining result)]
(if (empty? (rest ps))
;; Nothing more: return
(case (:status result)
:ok {:status :group
:type name
:data (conj results result)
:token origin
:remaining res-rem}
:quiet {:status :group
:type name
:data results
:token origin
:remaining res-rem}
:group {:status :group
:type name
:data (vec (concat results (:data result)))
:token origin
:remaining res-rem}
(:err :none)
(update result :trace #(conj % name)))
;; Still parsers left in the vector: recur
(case (:status result)
:ok (recur (rest ps) (conj results result) res-rem)
:group (recur (rest ps)
(vec (concat results (:data result)))
res-rem)
:quiet (recur (rest ps) results res-rem)
(:err :none)
(update result :trace #(conj % name))))))))})
(defn quiet [parser] (defn quiet [parser]
{:name (kw+str (? (:name parser) parser) "-quiet") {:name (kw+str (? (:name parser) parser) "-quiet")
:rule (fn quiet-fn [tokens] :rule (fn quiet-fn [tokens]
@ -219,9 +262,7 @@
:token (first tokens) :token (first tokens)
:remaining (remaining rest-result)} :remaining (remaining rest-result)}
:err (update rest-result :trace #(conj % name))) :err (update rest-result :trace #(conj % name))))
)
:quiet :quiet
(let [rest-result (apply-parser rest-parser (remaining first-result))] (let [rest-result (apply-parser rest-parser (remaining first-result))]