get the recursive descent framework worked out

This commit is contained in:
Scott Richmond 2024-04-29 16:25:24 -04:00
parent 402b444231
commit 98fcfe7eb4

View File

@ -31,7 +31,12 @@
}) })
### and some helper functions for interfacing with that data structure ### and some helper functions for interfacing with that data structure
(defn- current [parser] (get (parser :tokens) (parser :current))) (defn- current [parser]
(def curr (get (parser :tokens) (parser :current)))
(if (not curr)
(error "no more tokens")
curr))
(defn- peek [parser] (get (parser :tokens) (inc (parser :current)))) (defn- peek [parser] (get (parser :tokens) (inc (parser :current))))
@ -39,46 +44,110 @@
(defn- type [token] (get token :type)) (defn- type [token] (get token :type))
(defn- expect [parser type] (defn- check [parser type]
(def current-type (-> parser current (get :type))) (def current-type (-> parser current (get :type)))
(= type current-type)) (= type current-type))
### Parsing functions ### Parsing functions
(declare expr) (declare nonbinding binding)
# errors
(def terminators [:break :newline :semicolon :eof])
(defn- terminates? [parser]
(def curr (current parser))
(def ttype (type curr))
(has-value? terminators ttype))
(defn- panic [parser message]
(print "Panic in the parser: " message)
(def origin (current parser))
(advance parser)
(def skipped @[origin])
(while (not (terminates? parser))
(array/push skipped (current parser))
(advance parser))
(array/push skipped (current parser))
(advance parser)
(error {:type :error :data skipped :token origin}))
(defn- expected [parser ttype]
(panic parser (string "expected " ttype ", got " (-> parser current type))))
(defn- expect [parser type]
(if-not (check parser type) (expected parser type)))
# atoms # atoms
(defn- bool [parser] (defn- bool [parser]
(expect parser :bool)
(def curr (-> parser current)) (def curr (-> parser current))
(def ttype (type curr)) (def ttype (type curr))
(def value (if (= ttype :true) true false)) (def value (if (= ttype :true) true false))
(def ast {:type :bool :value value :token curr}) (advance parser)
(update parser :ast array/push ast) {:type :bool :data value :token curr}
(advance parser)) )
(defn- num [parser] (defn- num [parser]
(expect parser :number)
(def curr (-> parser current)) (def curr (-> parser current))
(def ast {:type :number :value (curr :literal) :token curr}) (advance parser)
(update parser :ast array/push ast) {:type :number :data (curr :literal) :token curr}
(advance parser)) )
(defn- kw [parser] (defn- kw [parser]
(expect parser :keyword)
(def curr (-> parser current)) (def curr (-> parser current))
(def ast {:type :keyword :value (curr :literal) :token curr}) (advance parser)
(update parser :ast array/push ast) {:type :keyword :data (curr :literal) :token curr}
(advance parser)) )
(defn- nill [parser] (defn- nill [parser]
(def ast {:type :nil :token (current parser)}) (expect parser :nil)
(update parser :ast array/push ast) (advance parser)
(advance parser)) {:type :nil :token (current parser)}
)
(defn- str [parser] (defn- str [parser]
(expect parser :string)
(def curr (-> parser current)) (def curr (-> parser current))
(def ast {:type :string :value (curr :literal) :token curr}) (advance parser)
(update parser :ast array/push ast) {:type :string :data (curr :literal) :token curr}
(advance parser)) )
(defrec expr [parser] (def separates [:break :newline :comma])
(defn- separates? [parser]
(def curr (current parser))
(def ttype (type curr))
(has-value? separates ttype))
(defn- separators [parser]
(if-not (separates? parser)
(panic parser (string "expected separator, got " (-> parser current type))))
(while (separates? parser) (advance parser)))
(defn- tup-term [parser]
(def term (nonbinding parser))
(if (separates? parser)
(do
(while (separates? parser) (advance parser))
term)
(panic parser (string "expected separator, got " (type (current parser))))))
(defn- tup [parser]
(def origin (current parser))
(advance parser) # consume the :lparen
(def ast {:type :tuple :data @[] :token origin})
(while (separates? parser) (advance parser)) # consume any separators
(while (not (check parser :rparen))
(def term (try (nonbinding parser) ([e] e)))
(array/push (ast :data) term)
(try (separators parser)
([e] (pp e) (array/push (ast :data) e))))
(advance parser)
ast)
(defrec nonbinding [parser]
(def curr (current parser)) (def curr (current parser))
(case (type curr) (case (type curr)
# atoms # atoms
@ -92,18 +161,30 @@
:string (str parser) :string (str parser)
### TODO: interpolated strings ### TODO: interpolated strings
# tuples
:lparen (tup parser)
(panic parser (string "expected nonbinding expression, got " (type curr)))
)
)
(defrec binding [parser]
(def curr (current parser))
(case (type curr)
:let nil
:fn nil
) )
) )
(do
#(comment
(os/cd "janet") # For repl to do relative imports (os/cd "janet") # For repl to do relative imports
(import ./scanner :as s) (import ./scanner :as s)
(do
#(comment
(def scanned (s/scan "\"foo bar baz\"")) (def scanned (s/scan "(1, (2 3), 3)"))
(def a-parser (new-parser scanned)) (def a-parser (new-parser scanned))
(def parsed (expr a-parser)) (def parsed (nonbinding a-parser))
(-> parsed (get :ast) (get 0) (get :value)) (-> parsed (get :data) )
) )