diff --git a/janet/recursive.janet b/janet/recursive.janet index e12f4bb..567a785 100644 --- a/janet/recursive.janet +++ b/janet/recursive.janet @@ -1,20 +1,15 @@ ### A recursive descent parser for Ludus ### We still need to scan some things -(os/cd "janet") # when in repl to do relative imports +#(os/cd "janet") # when in repl to do relative imports (import ./scanner :as s) -### First, some mutual recursion helpers -(defn unreachable - "A function that errors out if called." - [&] (error "reached the unreachable")) - (defmacro declare "Forward-declares a function name, so that it can be called in a mutually recursive manner." [& names] (def bindings @[]) (loop [name :in names] - (def binding ~(var ,name unreachable)) + (def binding ~(var ,name nil)) (array/push bindings binding)) ~(upscope ,;bindings)) @@ -22,7 +17,7 @@ "Defines a function depended on by another function, that has been forward `declare`d." [name & forms] (if-not (dyn name) (error "recursive functions must be declared before they are defined")) - ~(set ,name (defn ,name ,;forms))) + ~(set ,name (defn- ,name ,;forms))) ### Next: a data structure for a parser (defn- new-parser @@ -139,7 +134,7 @@ # atoms (defn- bool [parser] - (expect parser :bool) + (expect parser :true :false) (def curr (-> parser current)) (def ttype (type curr)) (def value (if (= ttype :true) true false)) @@ -194,9 +189,6 @@ {:type :word :data (first-token :lexeme) :token first-token} :else {:type :error :msg "string interpolations/patterns must be single words"})) -(def foo [{:foo :bar}]) -(-> foo first (get :foo)) - (defn- is-error? [data] (cond (buffer? data) false @@ -360,7 +352,7 @@ (def term (if (check parser :splat) (do (advance parser) - (def splatted (try (word-only parser) ([e] e))) + (def splatted (capture word-only parser)) {:type :splat :data splatted :token origin} ) (capture nonbinding parser))) @@ -412,7 +404,7 @@ (def key (try (kw parser) ([e] e))) (def value (capture nonbinding parser)) {:type :pair :data [key value] :token origin}) - (try (panic parser (string expect "expected dict term, got " (type origin))) ([e] e)) + (try (panic parser (string "expected dict term, got " (type origin))) ([e] e)) )) (array/push (ast :data) term) (try (separators parser) ([e] (array/push (ast :data) e)))) @@ -499,12 +491,16 @@ (def origin (current parser)) (def term (case (type origin) :splat {:type :splat :data (when (check (advance parser) :word) (word-only parser)) :token origin} - :word (capture word-pattern parser) + :word (do + (def word (capture word-pattern parser)) + (def name (word :data)) + (def key {:type :keyword :data (keyword name) :token origin}) + {:type :pair :data [key word] :token origin}) :keyword (do (def key (capture kw parser)) (def value (capture pattern parser)) {:type :pair :data [key value] :token origin}) - (try (panic parser (string expect "expected dict term, got " (type origin))) ([e] e)) + (try (panic parser (string "expected dict term, got " (type origin))) ([e] e)) )) (array/push (ast :data) term) (try (separators parser) ([e] (array/push (ast :data) e)))) @@ -743,6 +739,7 @@ (if (check parser :eof) (error {:type :error :token origin :data data :msg "unclosed brace"})) (array/push data (capture fn-clause parser))) + (advance parser) data) (defn- lambda [parser] @@ -781,6 +778,7 @@ (error {:type :error :token origin :data data :msg "unclosed brace"})) (array/push data (capture expr parser)) (terminator parser)) + (advance parser) {:type :block :data data :token origin}) ### TODO: decide whether this design works @@ -943,7 +941,7 @@ :pkg-name (pkg-name parser) :recur (recur parser) :panic (panicc parser) - (panic parser (string expect "expected simple expression, got " (type curr))) + (panic parser (string "expected simple expression, got " (type curr))) ) ) @@ -1017,6 +1015,7 @@ :number (num parser) :keyword (kw parser) :string (str parser) + :interpolated (interpolated parser) :lparen (tup parser) :lbracket (list parser) :startdict (dict parser) @@ -1060,6 +1059,12 @@ (capture terminator parser)) {:type :script :data lines :token origin}) +(defn parse [scanned] + (def parser (new-parser scanned)) + (def ast (script parser)) + (set (parser :ast) ast) + parser) + (defn- indent-by [n] (def indentation @"") (repeat n (buffer/push indentation "..")) @@ -1081,12 +1086,13 @@ (do #(comment (def source ` -panic! foo +"foo {bar} baz" `) (def scanned (s/scan source)) -(def a-parser (new-parser scanned)) (print "\n***NEW PARSE***\n") -(def parsed (toplevel a-parser)) +(def a-parser (new-parser scanned)) +(def parsed (script a-parser)) + # (print (pp-ast parsed)) (pp parsed) )