aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cljcc/analyze/resolve.clj4
-rw-r--r--src/cljcc/lexer.clj36
-rw-r--r--src/cljcc/schema.clj6
-rw-r--r--src/cljcc/util.clj43
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})))