dequalify token keywords
This commit is contained in:
parent
3a7f86e401
commit
4936daa8dc
|
@ -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")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user