blob: f1da784aa70806e0f0c03a3f255973f31b1e88cf (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
(ns cljcc.parser
(:require
[cljcc.lexer :as l]
[clojure.pprint :as pp]))
(defn- expect [kind [token & rst]]
(if (= kind (:kind token))
[token rst]
(throw (ex-info "Parser Error." {:expected kind
:actual (:kind token)}))))
(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)
[exp-node rst] (parse-exp rst)]
[{:type :statement
:statement-type :return
:value exp-node}
rst]))
(defn- parse-statement
"Parses a single statement. Expects a semicolon at the end."
[[token :as tokens]]
(let [[statement rst]
(cond
(= (:kind token) :kw-return) (parse-return-statement tokens)
:else (throw (ex-info "Parser Error. Unexpected statement. " {:token token})))
[_ rst] (expect :semicolon rst)]
[statement rst]))
(defn- keyword->type [k]
(condp = k
:kw-int "int"
(throw (ex-info "Parser Error. Unsupported type." {:keyword k}))))
(defn- parse-function [tokens]
(let [[fn-type-token rst] (expect :kw-int tokens)
[fn-identifier-token rst] (expect :identifier rst)
[_ rst] (expect :left-paren rst)
[fn-parameter-token rst] (expect :kw-void rst)
[_ rst] (expect :right-paren rst)
[_ rst] (expect :left-curly rst)
[statement rst] (parse-statement rst)
[_ rst] (expect :right-curly rst)]
[{:type :function
:return-type (keyword->type (:kind fn-type-token))
:identifier (:literal fn-identifier-token)
:parameters (:kind fn-parameter-token)
:statements [statement]}
rst]))
(defn- parse-program [tokens]
(let [[ast rst] (parse-function tokens)
_ (expect :eof rst)]
[ast]))
(defn parse [tokens]
(-> tokens
:tokens
parse-program))
(comment
(pp/pprint (parse (l/lex "
int main(void) {
return -(~~~(2));
}")))
(pp/pprint
(l/lex
"int main(void) {return (((2)))}"))
(pp/pprint
(l/lex "
int main(void) {
return 2;
}"))
(parse "int main(void) {
return -(((((10)))));
}")
(pp/pprint (parse "int main(void) {
return 1 & 2 + 6 & 6;
}"))
())
|