dequalify token keywords

This commit is contained in:
Scott Richmond 2023-05-02 19:02:28 -04:00
parent 3a7f86e401
commit 4936daa8dc

View File

@ -7,66 +7,66 @@
(def reserved-words (def reserved-words
"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 ;; impl for `import`; not yet for patterns {"as" :as ;; impl for `import`; not yet for patterns
"cond" ::token/cond ;; impl "cond" :cond ;; impl
"do" ::token/do ;; impl "do" :do ;; impl
"else" ::token/else ;; impl "else" :else ;; impl
"false" ::token/false ;; impl "false" :false ;; impl
"fn" ::token/fn ;; impl "fn" :fn ;; impl
"if" ::token/if ;; impl "if" :if ;; impl
"import" ::token/import ;; impl "import" :import ;; impl
"let" ::token/let ;; impl "let" :let ;; impl
"loop" ::token/loop ;; impl "loop" :loop ;; impl
"match" ::token/match ;; impl "match" :match ;; impl
"nil" ::token/nil ;; impl "nil" :nil ;; impl
"ns" ::token/ns ;; impl "ns" :ns ;; impl
;; "panic!" ::token/panic ;; impl (should be a function) ;; "panic!" :panic ;; impl (should be a function)
"recur" ::token/recur ;; impl "recur" :recur ;; impl
"ref" ::token/ref ;; impl "ref" :ref ;; impl
"then" ::token/then ;; impl "then" :then ;; impl
"true" ::token/true ;; impl "true" :true ;; impl
"with" ::token/with ;; impl "with" :with ;; impl
;; actor model/concurrency ;; actor model/concurrency
"receive" ::token/receive "receive" :receive
;;"self" ::token/self ;; maybe not necessary?: self() is a function ;;"self" :self ;; maybe not necessary?: self() is a function
;;"send" ::token/send ;; not necessary: send(pid, message) is a function ;;"send" :send ;; not necessary: send(pid, message) is a function
"spawn" ::token/spawn "spawn" :spawn
;;"to" ::token/to ;; not necessary if send is a function ;;"to" :to ;; not necessary if send is a function
;; type system ;; type system
;; "data" ::token/data ;; we are going to tear out datatypes for now: see if dynamism works for us ;; "data" :data ;; we are going to tear out datatypes for now: see if dynamism works for us
;; others ;; others
"repeat" ::token/repeat ;; syntax sugar over "loop": still unclear what this syntax could be "repeat" :repeat ;; syntax sugar over "loop": still unclear what this syntax could be
"test" ::token/test "test" :test
"when" ::token/when "when" :when
;; "module" ::token/module ;; not necessary if we don't have datatypes ;; "module" :module ;; not necessary if we don't have datatypes
}) })
(defn- new-scanner (defn- new-scanner
"Creates a new scanner." "Creates a new scanner."
[source] [source]
{::source source {:source source
::length (count source) :length (count source)
::errors [] :errors []
::start 0 :start 0
::current 0 :current 0
::line 1 :line 1
::tokens []}) :tokens []})
(defn- at-end? (defn- at-end?
"Tests if a scanner is at end of input." "Tests if a scanner is at end of input."
[scanner] [scanner]
(>= (::current scanner) (::length scanner))) (>= (:current scanner) (:length scanner)))
(defn- current-char (defn- current-char
"Gets the current character of the scanner." "Gets the current character of the scanner."
[scanner] [scanner]
(nth (::source scanner) (::current scanner) nil)) (nth (:source scanner) (:current scanner) nil))
(defn- advance (defn- advance
"Advances the scanner by a single character." "Advances the scanner by a single character."
[scanner] [scanner]
(update scanner ::current inc)) (update scanner :current inc))
(defn- next-char (defn- next-char
"Gets the next character from the scanner." "Gets the next character from the scanner."
@ -75,7 +75,7 @@
(defn- current-lexeme (defn- current-lexeme
[scanner] [scanner]
(subs (::source scanner) (::start scanner) (::current scanner))) (subs (:source scanner) (:start scanner) (:current scanner)))
(defn- char-in-range? [start end char] (defn- char-in-range? [start end char]
(and char (and char
@ -120,28 +120,28 @@
([scanner token-type] ([scanner token-type]
(add-token scanner token-type nil)) (add-token scanner token-type nil))
([scanner token-type literal] ([scanner token-type literal]
(update scanner ::tokens conj (update scanner :tokens conj
(token/token (token/token
token-type token-type
(current-lexeme scanner) (current-lexeme scanner)
literal literal
(::line scanner) (:line scanner)
(::start scanner))))) (:start scanner)))))
;; TODO: errors should also be in the vector of tokens ;; TODO: errors should also be in the vector of tokens
;; 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]
(let [token (token/token (let [token (token/token
::token/error :error
(current-lexeme scanner) (current-lexeme scanner)
nil nil
(::line scanner) (:line scanner)
(::start scanner)) (:start scanner))
err-token (assoc token :message msg)] err-token (assoc token :message msg)]
(-> scanner (-> scanner
(update ::errors conj err-token) (update :errors conj err-token)
(update ::tokens conj err-token)))) (update :tokens conj err-token))))
(defn- add-keyword (defn- add-keyword
[scanner] [scanner]
@ -149,7 +149,7 @@
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 :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 (str "Unexpected " char "after keyword :" key)))))) :else (add-error scanner (str "Unexpected " char "after keyword :" key))))))
@ -166,7 +166,7 @@
(= 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 :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 "."))))))
@ -179,10 +179,10 @@
(let [char (current-char scanner)] (let [char (current-char scanner)]
(case char (case char
\newline (add-error scanner "Unterminated string.") \newline (add-error scanner "Unterminated string.")
\" (add-token (advance scanner) ::token/string string) \" (add-token (advance scanner) :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)
@ -195,7 +195,7 @@
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 :word))
(word-char? curr) (recur (advance scanner) (str word curr)) (word-char? curr) (recur (advance scanner) (str word curr))
:else (add-error scanner (str "Unexpected " curr " after word " word ".")))))) :else (add-error scanner (str "Unexpected " curr " after word " word "."))))))
@ -205,7 +205,7 @@
word (str char)] word (str char)]
(let [curr (current-char scanner)] (let [curr (current-char scanner)]
(cond (cond
(terminates? curr) (add-token scanner ::token/datatype) (terminates? curr) (add-token scanner :datatype)
(word-char? curr) (recur (advance scanner) (str word curr)) (word-char? curr) (recur (advance scanner) (str word curr))
:else (add-error scanner (str "Unexpected " curr " after datatype " word ".")))))) :else (add-error scanner (str "Unexpected " curr " after datatype " word "."))))))
@ -215,7 +215,7 @@
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 :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 "."))))))
@ -224,7 +224,7 @@
comm (str char)] comm (str char)]
(let [char (current-char scanner)] (let [char (current-char scanner)]
(if (= \newline char) (if (= \newline char)
(update scanner ::line inc) (update scanner :line inc)
(recur (advance scanner) (str comm char)))))) (recur (advance scanner) (str comm char))))))
(defn- scan-token [scanner] (defn- scan-token [scanner]
@ -233,36 +233,36 @@
next (current-char scanner)] next (current-char scanner)]
(case char (case char
;; one-character tokens ;; one-character tokens
\( (add-token scanner ::token/lparen) \( (add-token scanner :lparen)
\) (add-token scanner ::token/rparen) \) (add-token scanner :rparen)
\{ (add-token scanner ::token/lbrace) \{ (add-token scanner :lbrace)
\} (add-token scanner ::token/rbrace) \} (add-token scanner :rbrace)
\[ (add-token scanner ::token/lbracket) \[ (add-token scanner :lbracket)
\] (add-token scanner ::token/rbracket) \] (add-token scanner :rbracket)
\; (add-token scanner ::token/semicolon) \; (add-token scanner :semicolon)
\, (add-token scanner ::token/comma) \, (add-token scanner :comma)
\newline (add-token (update scanner ::line inc) ::token/newline) \newline (add-token (update scanner :line inc) :newline)
\\ (add-token scanner ::token/backslash) \\ (add-token scanner :backslash)
\= (add-token scanner ::token/equals) \= (add-token scanner :equals)
\> (add-token scanner ::token/pipeline) \> (add-token scanner :pipeline)
;; two-character tokens ;; two-character tokens
;; -> ;; ->
\- (cond \- (cond
(= next \>) (add-token (advance scanner) ::token/rarrow) (= next \>) (add-token (advance scanner) :rarrow)
(digit? next) (add-number char scanner) (digit? next) (add-number char scanner)
:else (add-error scanner (str "Expected -> or negative number after `-`. Got `" char next "`"))) :else (add-error scanner (str "Expected -> or negative number after `-`. Got `" char next "`")))
;; at current we're not using this ;; at current we're not using this
;; <- ;; <-
;;\< (if (= next \-) ;;\< (if (= next \-)
;; (add-token (advance scanner) ::token/larrow) ;; (add-token (advance scanner) :larrow)
;; (add-error scanner (str "Expected <-. Got " char next))) ;; (add-error scanner (str "Expected <-. Got " char next)))
;; |> ;; |>
;; Consider => , with =>> for bind ;; Consider => , with =>> for bind
; \| (if (= next \>) ; \| (if (= next \>)
; (add-token (advance scanner) ::token/pipeline) ; (add-token (advance scanner) :pipeline)
; (add-error scanner (str "Expected |>. Got " char next))) ; (add-error scanner (str "Expected |>. Got " char next)))
;; possible additional operator: bind/result ;; possible additional operator: bind/result
@ -272,23 +272,23 @@
;; dict #{ ;; dict #{
\# (if (= next \{) \# (if (= next \{)
(add-token (advance scanner) ::token/startdict) (add-token (advance scanner) :startdict)
(add-error scanner (str "Expected beginning of dict: #{. Got " char next))) (add-error scanner (str "Expected beginning of dict: #{. Got " char next)))
;; set ${ ;; set ${
\$ (if (= next \{) \$ (if (= next \{)
(add-token (advance scanner) ::token/startset) (add-token (advance scanner) :startset)
(add-error scanner (str "Expected beginning of set: ${. Got " char next))) (add-error scanner (str "Expected beginning of set: ${. Got " char next)))
;; struct @{ ;; struct @{
\@ (if (= next \{) \@ (if (= next \{)
(add-token (advance scanner) ::token/startstruct) (add-token (advance scanner) :startstruct)
(add-error scanner (str "Expected beginning of struct: @{. Got " char next))) (add-error scanner (str "Expected beginning of struct: @{. Got " char next)))
;; placeholders ;; placeholders
;; there's a flat _, and then ignored words ;; there's a flat _, and then ignored words
\_ (cond \_ (cond
(terminates? next) (add-token scanner ::token/placeholder) (terminates? next) (add-token scanner :placeholder)
(alpha? next) (add-ignored scanner) (alpha? next) (add-ignored scanner)
:else (add-error scanner (str "Expected placeholder: _. Got " char next))) :else (add-error scanner (str "Expected placeholder: _. Got " char next)))
@ -306,7 +306,7 @@
;; 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)) :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
@ -321,14 +321,14 @@
:else (add-error scanner (str "Unexpected character: " char)))))) :else (add-error scanner (str "Unexpected character: " char))))))
(defn- next-token [scanner] (defn- next-token [scanner]
(assoc scanner ::start (::current scanner))) (assoc scanner :start (:current scanner)))
(defn scan [source] (defn scan [source]
(loop [scanner (new-scanner (str source "\n"))] (loop [scanner (new-scanner (str source "\n"))]
(if (at-end? scanner) (if (at-end? scanner)
(let [scanner (add-token scanner ::token/eof)] (let [scanner (add-token scanner :eof)]
{:tokens (::tokens scanner) {:tokens (:tokens scanner)
:errors (::errors scanner)}) :errors (:errors scanner)})
(recur (-> scanner (scan-token) (next-token)))))) (recur (-> scanner (scan-token) (next-token))))))
(scan "2 :three true nil") (scan "2 :three true nil")