whitespace

This commit is contained in:
Richard Harrington 2015-07-22 17:38:45 -04:00
parent 1541c667e4
commit 90e31a4b22

View File

@ -24,7 +24,7 @@
[lines] [lines]
(map #(re-find #"[^;]*" %) lines)) (map #(re-find #"[^;]*" %) lines))
(def lex-re (def lex-re
(let [op-string (join op-commands)] (let [op-string (join op-commands)]
(re-pattern (str "[" op-string "]|[^" op-string "\\s]+")))) (re-pattern (str "[" op-string "]|[^" op-string "\\s]+"))))
@ -33,8 +33,8 @@
are intended to be human-readable for error-reporting are intended to be human-readable for error-reporting
purposes, so they're indexed from 1." purposes, so they're indexed from 1."
[line-num line] [line-num line]
(map (fn [[s n]] (map (fn [[s n]]
^{:line (inc line-num), :pos (inc n)} {:token-str s}) ^{:line (inc line-num), :pos (inc n)} {:token-str s})
(re-seq-with-pos lex-re line))) (re-seq-with-pos lex-re line)))
(defn lex (defn lex
@ -62,7 +62,7 @@
(rather than building a new one) because it contains line and column (rather than building a new one) because it contains line and column
number metadata." number metadata."
[{token-str :token-str :as token}] [{token-str :token-str :as token}]
(let [parser-priority (let [parser-priority
[[(set commands) :command] [[(set commands) :command]
[str->int :number] [str->int :number]
[valid-word :identifier] [valid-word :identifier]
@ -93,11 +93,11 @@
(#{"GOTO" "GOSUB"} (:val (last parsed-tokens)))) (#{"GOTO" "GOSUB"} (:val (last parsed-tokens))))
(recur tail (conj parsed-tokens (assoc parsed-token :type :label))) (recur tail (conj parsed-tokens (assoc parsed-token :type :label)))
(recur tail (conj parsed-tokens (assoc parsed-token :type :register))))))))) (recur tail (conj parsed-tokens (assoc parsed-token :type :register)))))))))
(defn parse (defn parse
"take the lines of tokens and converts them to :val and :type format. "take the lines of tokens and converts them to :val and :type format.
After this point, tokens are no longer separated into sequences of sequences After this point, tokens are no longer separated into sequences of sequences
according to the linebreaks in the original source code -- according to the linebreaks in the original source code --
if we need that information later for error reporting, it's in the metadata. if we need that information later for error reporting, it's in the metadata.
if there's an error, this function just returns the token, if there's an error, this function just returns the token,
outside of any sequence." outside of any sequence."
@ -116,21 +116,21 @@
(loop [tokens initial-tokens (loop [tokens initial-tokens
results []] results []]
(let [{prev-type :type} (last results) (let [{prev-type :type} (last results)
[{current-val :val :as current-token} [{current-val :val :as current-token}
& [{next-val :val, next-type :type :as next-token} :as tail]] tokens] & [{next-val :val, next-type :type :as next-token} :as tail]] tokens]
(cond (cond
(empty? tokens) results (empty? tokens) results
(and (= current-val "-") (and (= current-val "-")
(= next-type :number) (= next-type :number)
(not (#{:number :register} prev-type))) (not (#{:number :register} prev-type)))
(recur (rest tail) (recur (rest tail)
(conj results (into current-token {:val (- next-val), :type :number}))) (conj results (into current-token {:val (- next-val), :type :number})))
:otherwise (recur tail (conj results current-token)))))) :otherwise (recur tail (conj results current-token))))))
(defn make-instr-pairs (defn make-instr-pairs
"Compiles the tokens into token-pairs. Commands consume the next token. "Compiles the tokens into token-pairs. Commands consume the next token.
When values are encountered that are not arguments to commands, When values are encountered that are not arguments to commands,
a special token-pair is created that is a comma followed by the value a special token-pair is created that is a comma followed by the value
(meaning push the value into the accumulator). The comma command re-uses (meaning push the value into the accumulator). The comma command re-uses
the same :line and :pos metadata from the token containing the value that is being pushed." the same :line and :pos metadata from the token containing the value that is being pushed."
[initial-tokens] [initial-tokens]
@ -139,11 +139,11 @@
(if (empty? tokens) (if (empty? tokens)
result result
(match [token] (match [token]
[{:type (:or :number :register)}] [{:type (:or :number :register)}]
(recur tail (conj result [(into token {:val ",", :type :command}) token])) (recur tail (conj result [(into token {:val ",", :type :command}) token]))
[(:or {:type :label} {:type :command, :val "ENDSUB"})] [(:or {:type :label} {:type :command, :val "ENDSUB"})]
(recur tail (conj result [token nil])) (recur tail (conj result [token nil]))
[{:type :command}] [{:type :command}]
(recur (rest tail) (conj result [token (first tail)])))))) (recur (rest tail) (conj result [token (first tail)]))))))
; TODO: preserve :line and :pos metadata with labels, ; TODO: preserve :line and :pos metadata with labels,
@ -154,21 +154,21 @@
and remove the labels from the instruction list itself (except as targets)" and remove the labels from the instruction list itself (except as targets)"
[initial-instrs] [initial-instrs]
(loop [[instr & tail :as instrs] initial-instrs (loop [[instr & tail :as instrs] initial-instrs
result {:labels {} result {:labels {}
:instrs []}] :instrs []}]
(if (empty? instrs) (if (empty? instrs)
result result
(let [command (first instr) (let [command (first instr)
next-instr-num (count (result :instrs))] next-instr-num (count (result :instrs))]
(if (= (command :type) :label) (if (= (command :type) :label)
(recur tail (assoc-in result [:labels (command :val)] next-instr-num)) (recur tail (assoc-in result [:labels (command :val)] next-instr-num))
(recur tail (assoc-in result [:instrs next-instr-num] instr))))))) (recur tail (assoc-in result [:instrs next-instr-num] instr)))))))
(defn assemble [src-code] (defn assemble [src-code]
"compiles robotwar code, with error-checking beginning after the lexing "compiles robotwar code, with error-checking beginning after the lexing
step. All functions that return errors will return a map with the keyword step. All functions that return errors will return a map with the keyword
:error, and then a token with a :val field containing the error string, :error, and then a token with a :val field containing the error string,
and metadata containing :pos and :line fields containing the location. and metadata containing :pos and :line fields containing the location.
So far only parse implements error-checking." So far only parse implements error-checking."
(let [lexed (-> src-code split-lines strip-comments lex)] (let [lexed (-> src-code split-lines strip-comments lex)]
(reduce (fn [result step] (reduce (fn [result step]