diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cljcc/analyze/resolve.clj | 4 | ||||
| -rw-r--r-- | src/cljcc/lexer.clj | 36 | ||||
| -rw-r--r-- | src/cljcc/schema.clj | 6 | ||||
| -rw-r--r-- | src/cljcc/util.clj | 43 |
4 files changed, 60 insertions, 29 deletions
diff --git a/src/cljcc/analyze/resolve.clj b/src/cljcc/analyze/resolve.clj index 5982312..9f09333 100644 --- a/src/cljcc/analyze/resolve.clj +++ b/src/cljcc/analyze/resolve.clj @@ -271,8 +271,8 @@ ;; Program is list of block items, which are themselves just blocks. (defn resolve-program [program] - (let [res (:block (resolve-block program)) - _ (m/coerce s/Program res)] + (let [res (:block (resolve-block program))] + ; _ (m/coerce s/Program res)] res)) (comment diff --git a/src/cljcc/lexer.clj b/src/cljcc/lexer.clj index 3651d16..d4e20d3 100644 --- a/src/cljcc/lexer.clj +++ b/src/cljcc/lexer.clj @@ -1,6 +1,6 @@ (ns cljcc.lexer (:require - [cljcc.util :refer [newline? whitespace? read-number digit? letter-digit? letter?]] + [cljcc.util :refer [newline? whitespace? read-number digit? letter-digit? letter? letter-digit-period?]] [cljcc.exception :as exc] [cljcc.token :as t])) @@ -9,6 +9,8 @@ :line 1 :col 1}) +(set! *warn-on-reflection* true) + (defn lex ([source] (lex source (lexer-ctx))) @@ -19,6 +21,9 @@ (-> ctx (update :line inc) (update :col (fn [_] 1)))) + (whitespace? ch) (recur (next source) + (-> ctx + (update :col inc))) (contains? t/chrs-kind-map (str ch pk th)) (recur (next (next (next source))) (-> ctx @@ -34,17 +39,13 @@ (-> ctx (update :col inc) (update :tokens #(conj % (t/create (get t/chrs-kind-map ch) line col))))) - (whitespace? ch) (recur (next source) - (-> ctx - (update :col inc))) - (digit? ch) (let [[chrs rst] (split-with letter-digit? source) - number (read-number (apply str chrs) line col) - cnt (count chrs) - token (t/create :number line col number)] - (recur (apply str rst) - (-> ctx - (update :col #(+ % cnt)) - (update :tokens #(conj % token))))) + (or (= \. ch) (digit? ch)) (let [[number rst] (read-number (apply str source) line col) + cnt (count number) + token (t/create :number line col number)] + (recur rst + (-> ctx + (update :col #(+ % cnt)) + (update :tokens #(conj % token))))) (letter? ch) (let [[chrs rst] (split-with letter-digit? source) lexeme (apply str chrs) cnt (count chrs) @@ -59,10 +60,19 @@ (comment + (-> "./test-programs/example.c" + slurp) + + (-> "./test-programs/example.c" + slurp + lex) + + (lex "int x = 100;") + (lex " int main(void) { - return 42; + return 2- -1; } ") diff --git a/src/cljcc/schema.clj b/src/cljcc/schema.clj index 23d7967..663604c 100644 --- a/src/cljcc/schema.clj +++ b/src/cljcc/schema.clj @@ -21,6 +21,10 @@ [:map [:type [:= :ulong]]]) +(def DoubleType + [:map + [:type [:= :double]]]) + (def FunType [:map [:type [:= :function]] @@ -32,12 +36,14 @@ ::mtype-long #'LongType ::mtype-uint #'UIntType ::mtype-ulong #'ULongType + ::mtype-double #'DoubleType ::mtype-function #'FunType}} [:multi {:dispatch :type} [:int #'IntType] [:long #'LongType] [:uint #'UIntType] [:ulong #'ULongType] + [:double #'DoubleType] [:function #'FunType]]]) (def Const diff --git a/src/cljcc/util.clj b/src/cljcc/util.clj index a40916b..7f59407 100644 --- a/src/cljcc/util.clj +++ b/src/cljcc/util.clj @@ -68,6 +68,13 @@ (or (= \_ ch) (Character/isLetterOrDigit ch))) +(defn letter-digit-period? [^Character ch] + (or (= \_ ch) + (= \. ch) + (= \+ ch) + (= \- ch) + (Character/isLetterOrDigit ch))) + (defn digit? [^Character ch] (Character/isDigit ch)) @@ -80,23 +87,31 @@ (defn matches-regex [re s] (not (nil? (re-matches re s)))) -(def unsigned-long-re #"[0-9]+([lL][uU]|[uU][lL])") -(def signed-long-re #"[0-9]+[lL]") -(def unsigned-int-re #"[0-9]+[uU]") -(def signed-int-re #"[0-9]+") -(def fractional-constant #"([0-9]*\.[0-9]+|[0-9]+\.?)[Ee][+-]?[0-9]+|[0-9]*\.[0-9]+|[0-9]+\.") +(def unsigned-long-re #"([0-9]+([lL][uU]|[uU][lL]))[^\w.]") +(def signed-long-re #"([0-9]+[lL])[^\w.]") +(def unsigned-int-re #"([0-9]+[uU])[^\w.]") +(def signed-int-re #"([0-9]+)[^\w.]") +(def floating-point-constant #"(([0-9]*\.[0-9]+|[0-9]+\.?)[Ee][+-]?[0-9]+|[0-9]*\.[0-9]+|[0-9]+\.)[^\w.]") -(defn read-number - "Returns number in string form. +(defn match-regex + "Returns matched string and remaining string tuple, otherwise returns nil. + + The first match by re-finds must be the starting subsequence, otherwise false." + [re s] + (when-let [matched (second (re-find re s))] + (when (str/starts-with? s matched) + [matched (str/replace-first s matched "")]))) - Checks whether number is valid long. If no, checks if it valid int. - Otherwise error." +(defn read-number + "Returns tuple of matched number and remaining string, otherwise nil." [s line col] - (if-let [_ (or (matches-regex signed-int-re s) - (matches-regex signed-long-re s) - (matches-regex unsigned-int-re s) - (matches-regex unsigned-long-re s))] - s + (if-let [x (or + (match-regex floating-point-constant s) + (match-regex signed-int-re s) + (match-regex signed-long-re s) + (match-regex unsigned-int-re s) + (match-regex unsigned-long-re s))] + x (exc/lex-error {:line line :col col}))) |
