Compare commits

..

No commits in common. "3d570beb457121e04a9a8a49b0304ffc5eb1e9b8" and "2bc32c35f255388a1b41b42b5ca3fb9f2805d867" have entirely different histories.

4 changed files with 4 additions and 117 deletions

2
.gitignore vendored
View File

@ -30,5 +30,3 @@ node_modules/
.helix/ .helix/
target/repl-port target/repl-port
.repl-buffer .repl-buffer
.repl-buffer.janet
.env

View File

@ -387,7 +387,6 @@ if (:)foo then :bar else :baz
(comment (comment
Okay, so I'm trying to figure out how to manage panics in this declarative (not recursive-descent) parser. Okay, so I'm trying to figure out how to manage panics in this declarative (not recursive-descent) parser.
The question is how to do the thing where we pop out of the stack up to the most relevant rule. The question is how to
Given that we may have deeply nested rules, we either want:
- A stack of rules in the parser, which
) )

View File

@ -1,109 +0,0 @@
### A recursive descent parser for Ludus
### First, some mutual recursion helpers
(defn unreachable
"A function that errors out if called."
[&] (error "cannot call recursive function before definition"))
(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))
(array/push bindings binding))
~(upscope ,;bindings))
(defmacro defrec
"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)))
### Next: a data structure for a parser
(defn- new-parser [tokens]
@{
:tokens (tokens :tokens)
:ast @[]
:current 0
:errors @[]
})
### and some helper functions for interfacing with that data structure
(defn- current [parser] (get (parser :tokens) (parser :current)))
(defn- peek [parser] (get (parser :tokens) (inc (parser :current))))
(defn- advance [parser] (update parser :current inc))
(defn- type [token] (get token :type))
(defn- expect [parser type]
(def current-type (-> parser current (get :type)))
(= type current-type))
### Parsing functions
(declare expr)
# atoms
(defn- bool [parser]
(def curr (-> parser current))
(def ttype (type curr))
(def value (if (= ttype :true) true false))
(def ast {:type :bool :value value :token curr})
(update parser :ast array/push ast)
(advance parser))
(defn- num [parser]
(def curr (-> parser current))
(def ast {:type :number :value (curr :literal) :token curr})
(update parser :ast array/push ast)
(advance parser))
(defn- kw [parser]
(def curr (-> parser current))
(def ast {:type :keyword :value (curr :literal) :token curr})
(update parser :ast array/push ast)
(advance parser))
(defn- nill [parser]
(def ast {:type :nil :token (current parser)})
(update parser :ast array/push ast)
(advance parser))
(defn- str [parser]
(def curr (-> parser current))
(def ast {:type :string :value (curr :literal) :token curr})
(update parser :ast array/push ast)
(advance parser))
(defrec expr [parser]
(def curr (current parser))
(case (type curr)
# atoms
:nil (nill parser)
:true (bool parser)
:false (bool parser)
:number (num parser)
:keyword (kw parser)
# strings
:string (str parser)
### TODO: interpolated strings
)
)
(do
#(comment
(os/cd "janet") # For repl to do relative imports
(import ./scanner :as s)
(def scanned (s/scan "\"foo bar baz\""))
(def a-parser (new-parser scanned))
(def parsed (expr a-parser))
(-> parsed (get :ast) (get 0) (get :value))
)

View File

@ -192,13 +192,12 @@
[scanner] [scanner]
(print "Adding string") (print "Adding string")
(defn recur [scanner buff interpolate?] (defn recur [scanner buff interpolate?]
(print "\n printing a thing from add-stirng" buff)
(let [char (current-char scanner)] (let [char (current-char scanner)]
(case char (case char
"{" (recur (advance scanner) (buffer/push buff char) true) "{" (recur (advance scanner) (buffer/push buff char) true)
# allow multiline strings # allow multiline strings
"\n" (recur (update (advance scanner) :line inc) (buffer/push buff char) interpolate?) "\n" (recur (update (advance scanner) :line inc) (buffer/push buff char) interpolate?)
### TODO: add interpolated strings
### :string -> (if (interpolate? :interpolated :string))
"\"" (add-token (advance scanner) :string (string buff)) "\"" (add-token (advance scanner) :string (string buff))
"\\" (let [next (next-char scanner) "\\" (let [next (next-char scanner)
scanner (if (= next "\n") scanner (if (= next "\n")
@ -315,7 +314,7 @@
(put scanner :start (get scanner :current))) (put scanner :start (get scanner :current)))
(defn scan [source &opt input] (defn scan [source &opt input]
(default input :input) (default input "")
(defn recur [scanner] (defn recur [scanner]
(if (at-end? scanner) (if (at-end? scanner)
(let [scanner (add-token (add-token scanner :break) :eof)] (let [scanner (add-token (add-token scanner :break) :eof)]