Better errors? WIP
This commit is contained in:
parent
40367d7e57
commit
23e2e95e77
|
@ -9,34 +9,34 @@
|
||||||
"List of Ludus reserved words."
|
"List of Ludus reserved words."
|
||||||
;; see ludus-spec repo for more info
|
;; see ludus-spec repo for more info
|
||||||
{
|
{
|
||||||
"as" ::token/as
|
"as" ::token/as
|
||||||
"cond" ::token/cond
|
"cond" ::token/cond
|
||||||
"else" ::token/else
|
"else" ::token/else
|
||||||
"false" ::token/false
|
"false" ::token/false
|
||||||
"fn" ::token/fn
|
"fn" ::token/fn
|
||||||
"if" ::token/if
|
"if" ::token/if
|
||||||
"let" ::token/let
|
"let" ::token/let
|
||||||
"match" ::token/match
|
"match" ::token/match
|
||||||
"mut" ::token/mut
|
"mut" ::token/mut
|
||||||
"nil" ::token/nil
|
"nil" ::token/nil
|
||||||
"panic!" ::token/panic
|
"panic!" ::token/panic
|
||||||
"then" ::token/then
|
"then" ::token/then
|
||||||
"true" ::token/true
|
"true" ::token/true
|
||||||
"var" ::token/var
|
"var" ::token/var
|
||||||
"with" ::token/with
|
"with" ::token/with
|
||||||
;; below here, probable
|
;; below here, probable
|
||||||
"defer" ::token/defer
|
"defer" ::token/defer
|
||||||
"gen" ::token/gen
|
"gen" ::token/gen
|
||||||
"loop" ::token/loop
|
"loop" ::token/loop
|
||||||
"ns" ::token/ns
|
"ns" ::token/ns
|
||||||
"recur" ::token/recur
|
"recur" ::token/recur
|
||||||
"repeat" ::token/repeat
|
"repeat" ::token/repeat
|
||||||
"test" ::token/test
|
"test" ::token/test
|
||||||
"wait" ::token/wait
|
"wait" ::token/wait
|
||||||
"yield" ::token/yield
|
"yield" ::token/yield
|
||||||
;; below here, possible
|
;; below here, possible
|
||||||
"when" ::token/when
|
"when" ::token/when
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
(defn- new-scanner
|
(defn- new-scanner
|
||||||
|
@ -122,34 +122,45 @@
|
||||||
;; The goal is to be able to be able to hand this to an LSP?
|
;; The goal is to be able to be able to hand this to an LSP?
|
||||||
;; Do we need a different structure
|
;; Do we need a different structure
|
||||||
(defn- add-error [scanner msg]
|
(defn- add-error [scanner msg]
|
||||||
(update scanner ::errors conj {:msg msg :line (::line scanner) :start (::start scanner)}))
|
(let [
|
||||||
|
token (token/token
|
||||||
|
::token/error
|
||||||
|
(current-lexeme scanner)
|
||||||
|
nil
|
||||||
|
(::line scanner)
|
||||||
|
(::start scanner))
|
||||||
|
err-token (assoc token :msg msg)
|
||||||
|
]
|
||||||
|
(-> scanner
|
||||||
|
(update ::errors conj err-token)
|
||||||
|
(update ::tokens conj err-token))))
|
||||||
|
|
||||||
(defn- add-keyword
|
(defn- add-keyword
|
||||||
[scanner]
|
[scanner]
|
||||||
(loop [scanner scanner
|
(loop [scanner scanner
|
||||||
key ""]
|
key ""]
|
||||||
(let [char (current-char scanner)]
|
(let [char (current-char scanner)]
|
||||||
(cond
|
(cond
|
||||||
(terminates? char) (add-token scanner ::token/keyword (keyword key))
|
(terminates? char) (add-token scanner ::token/keyword (keyword key))
|
||||||
(word-char? char) (recur (advance scanner) (str key char))
|
(word-char? char) (recur (advance scanner) (str key char))
|
||||||
:else (add-error scanner "Unexpected " char "after keyword :" key)))))
|
:else (add-error scanner (str "Unexpected " char "after keyword :" key))))))
|
||||||
|
|
||||||
;; TODO: improve number parsing?
|
;; TODO: improve number parsing?
|
||||||
;; Currently this uses Clojure's number formatting rules (since we use the EDN reader)
|
;; Currently this uses Clojure's number formatting rules (since we use the EDN reader)
|
||||||
;; These rules are here: https://cljs.github.io/api/syntax/number
|
;; These rules are here: https://cljs.github.io/api/syntax/number
|
||||||
(defn- add-number [char scanner]
|
(defn- add-number [char scanner]
|
||||||
(loop [scanner scanner
|
(loop [scanner scanner
|
||||||
num (str char)
|
num (str char)
|
||||||
float? false]
|
float? false]
|
||||||
(let [curr (current-char scanner)]
|
(let [curr (current-char scanner)]
|
||||||
(cond
|
(cond
|
||||||
(= curr \_) (recur (advance scanner) num float?) ;; consume underscores unharmed
|
(= curr \_) (recur (advance scanner) num float?) ;; consume underscores unharmed
|
||||||
(= curr \.) (if float?
|
(= curr \.) (if float?
|
||||||
(add-error scanner (str "Unexpected second decimal point after " num "."))
|
(add-error scanner (str "Unexpected second decimal point after " num "."))
|
||||||
(recur (advance scanner) (str num curr) true))
|
(recur (advance scanner) (str num curr) true))
|
||||||
(terminates? curr) (add-token scanner ::token/number (edn/read-string num))
|
(terminates? curr) (add-token scanner ::token/number (edn/read-string num))
|
||||||
(digit? curr) (recur (advance scanner) (str num curr) float?)
|
(digit? curr) (recur (advance scanner) (str num curr) float?)
|
||||||
:else (add-error scanner (str "Unexpected " curr " after number " num "."))))))
|
:else (add-error scanner (str "Unexpected " curr " after number " num "."))))))
|
||||||
|
|
||||||
;; TODO: add string interpolation
|
;; TODO: add string interpolation
|
||||||
;; This still has to be devised
|
;; This still has to be devised
|
||||||
|
@ -163,9 +174,9 @@
|
||||||
\" (add-token (advance scanner) ::token/string string)
|
\" (add-token (advance scanner) ::token/string string)
|
||||||
\\ (let [next (next-char scanner)
|
\\ (let [next (next-char scanner)
|
||||||
scanner (if (= next \newline)
|
scanner (if (= next \newline)
|
||||||
(update scanner ::line inc)
|
(update scanner ::line inc)
|
||||||
scanner)]
|
scanner)]
|
||||||
(recur (advance (advance scanner)) (str string next)))
|
(recur (advance (advance scanner)) (str string next)))
|
||||||
(if (at-end? scanner)
|
(if (at-end? scanner)
|
||||||
(add-error scanner "Unterminated string.")
|
(add-error scanner "Unterminated string.")
|
||||||
(recur (advance scanner) (str string char)))))))
|
(recur (advance scanner) (str string char)))))))
|
||||||
|
@ -174,7 +185,7 @@
|
||||||
[char scanner]
|
[char scanner]
|
||||||
(loop [scanner scanner
|
(loop [scanner scanner
|
||||||
word (str char)]
|
word (str char)]
|
||||||
(let [curr (current-char scanner)]
|
(let [curr (current-char scanner)]
|
||||||
(cond
|
(cond
|
||||||
(terminates? curr) (add-token scanner (get reserved-words word ::token/word))
|
(terminates? curr) (add-token scanner (get reserved-words word ::token/word))
|
||||||
(word-char? curr) (recur (advance scanner) (str word curr))
|
(word-char? curr) (recur (advance scanner) (str word curr))
|
||||||
|
@ -184,11 +195,11 @@
|
||||||
[scanner]
|
[scanner]
|
||||||
(loop [scanner scanner
|
(loop [scanner scanner
|
||||||
ignored "_"]
|
ignored "_"]
|
||||||
(let [char (current-char scanner)]
|
(let [char (current-char scanner)]
|
||||||
(cond
|
(cond
|
||||||
(terminates? char) (add-token scanner ::token/ignored)
|
(terminates? char) (add-token scanner ::token/ignored)
|
||||||
(word-char? char) (recur (advance scanner) (str ignored char))
|
(word-char? char) (recur (advance scanner) (str ignored char))
|
||||||
:else (add-error scanner (str "Unexpected " char " after word " ignored "."))))))
|
:else (add-error scanner (str "Unexpected " char " after word " ignored "."))))))
|
||||||
|
|
||||||
(defn- add-comment [char scanner]
|
(defn- add-comment [char scanner]
|
||||||
(loop [scanner scanner
|
(loop [scanner scanner
|
||||||
|
@ -221,9 +232,9 @@
|
||||||
;; two-character tokens
|
;; two-character tokens
|
||||||
;; ->
|
;; ->
|
||||||
\- (cond
|
\- (cond
|
||||||
(= next \>) (add-token (advance scanner) ::token/rarrow)
|
(= next \>) (add-token (advance scanner) ::token/rarrow)
|
||||||
(digit? next) (add-number char scanner)
|
(digit? next) (add-number char scanner)
|
||||||
:else (add-error scanner (str "Expected -> or negative number. Got " char next)))
|
:else (add-error scanner (str "Expected -> or negative number. Got " char next)))
|
||||||
|
|
||||||
;; at current we're not using this
|
;; at current we're not using this
|
||||||
;; <-
|
;; <-
|
||||||
|
@ -268,15 +279,15 @@
|
||||||
;; TODO: instead of a separate token, scan a whole type keyword
|
;; TODO: instead of a separate token, scan a whole type keyword
|
||||||
;; e.g. ::string, ::number
|
;; e.g. ::string, ::number
|
||||||
\: (cond
|
\: (cond
|
||||||
;;(= \: next) (add-token (advance scanner) ::token/doublecolon))
|
;;(= \: next) (add-token (advance scanner) ::token/doublecolon))
|
||||||
(alpha? next) (add-keyword scanner)
|
(alpha? next) (add-keyword scanner)
|
||||||
:else (add-error scanner (str "Expected keyword. Got " char next)))
|
:else (add-error scanner (str "Expected keyword. Got " char next)))
|
||||||
|
|
||||||
;; splats
|
;; splats
|
||||||
\. (let [after_next (current-char (advance scanner))]
|
\. (let [after_next (current-char (advance scanner))]
|
||||||
(if (= ".." (str next after_next))
|
(if (= ".." (str next after_next))
|
||||||
(add-token (advance (advance scanner)) ::token/splat)
|
(add-token (advance (advance scanner)) ::token/splat)
|
||||||
(add-error scanner (str "Expected splat: ... . Got " (str "." next after_next)))))
|
(add-error scanner (str "Expected splat: ... . Got " (str "." next after_next)))))
|
||||||
|
|
||||||
;; strings
|
;; strings
|
||||||
\" (add-string scanner)
|
\" (add-string scanner)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user