aboutsummaryrefslogtreecommitdiff
path: root/src/cljcc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cljcc')
-rw-r--r--src/cljcc/parser.clj48
1 files changed, 35 insertions, 13 deletions
diff --git a/src/cljcc/parser.clj b/src/cljcc/parser.clj
index 0feb388..f1da784 100644
--- a/src/cljcc/parser.clj
+++ b/src/cljcc/parser.clj
@@ -3,24 +3,44 @@
[cljcc.lexer :as l]
[clojure.pprint :as pp]))
-(defn- expect [expected-kind [token & rst]]
- (if (= expected-kind (:kind token))
+(defn- expect [kind [token & rst]]
+ (if (= kind (:kind token))
[token rst]
- (throw (ex-info "Parser Error." {:expected expected-kind
+ (throw (ex-info "Parser Error." {:expected kind
:actual (:kind token)}))))
-(defn- parse-exp [tokens]
- (let [[t rst] (expect :number tokens)]
- [{:type :exp
- :value {:type :constant-exp
- :value (:literal t)}} rst]))
+(defn- expect-in [kinds [{kind :kind :as token} & rst]]
+ (if (contains? kinds kind)
+ [token rst]
+ (throw (ex-info "Parser Error." {:expected kinds
+ :actual token}))))
+
+(defn- parse-exp [[{kind :kind :as token} :as tokens]]
+ (cond
+ (= kind :number) [{:type :exp
+ :exp-type :constant-exp
+ :value (:literal token)}
+ (rest tokens)]
+ (contains?
+ #{:complement :hyphen} kind) (let [operator kind
+ [e rst] (parse-exp (rest tokens))]
+ [{:type :exp
+ :exp-type :unary-exp
+ :unary-operator operator
+ :value e}
+ rst])
+ (= kind :left-paren) (let [[e rst] (parse-exp (rest tokens))
+ [_ rst] (expect :right-paren rst)]
+ [e rst])
+ :else (throw (ex-info "Parser Error." {:expected "number, (, -, ~"
+ :actual token}))))
(defn- parse-return-statement [tokens]
(let [[_ rst] (expect :kw-return tokens)
- [constant-node rst] (parse-exp rst)]
+ [exp-node rst] (parse-exp rst)]
[{:type :statement
:statement-type :return
- :value constant-node}
+ :value exp-node}
rst]))
(defn- parse-statement
@@ -66,14 +86,16 @@
(comment
- (parse "int main(void) {return 2;}")
-
(pp/pprint (parse (l/lex "
int main(void) {
- return 2;
+ return -(~~~(2));
}")))
(pp/pprint
+ (l/lex
+ "int main(void) {return (((2)))}"))
+
+ (pp/pprint
(l/lex "
int main(void) {
return 2;