blob: bee6d324978ec85852337ddfa444b381f47e11cd (
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
|
(ns cljcc.parser
(:require
[instaparse.core :as insta]
[clojure.pprint :as pp]))
(def whitespace
(insta/parser
"whitespace = #'\\s+'"))
(declare parse)
(def c-parser
(insta/parser
"<program> = function+
function = #'int\\b' identifier <'('> #'void\\b' <')'> <'{'> statement <'}'>
statement = #'return\\b' exp <';'>
exp = exp-prime
<exp-prime> = <'('> exp-prime <')'> | unop-exp | constant-exp
unop-exp = unop exp
unop = #'-' | #'~'
identifier = #'[a-zA-Z_]\\w*\\b'
constant-exp = #'[0-9]+\\b'
keyword = #'int\\b' | #'return\\b' | #'void\\b'"
:auto-whitespace whitespace))
(def binop-parser
(insta/parser
"<program> = function+
function = #'int\\b' identifier <'('> #'void\\b' <')'> <'{'> statement <'}'>
statement = #'return\\b' exp <';'>
exp = exp-prime
<exp-prime> = mul-div-mod | add-exp | sub-exp
add-exp = exp-prime <'+'> mul-div-mod
sub-exp = exp-prime <'-'> mul-div-mod
<mul-div-mod> = term | mul-exp | div-exp | mod-exp
mul-exp = mul-div-mod <'*'> term
div-exp = mul-div-mod <'/'> term
mod-exp = mul-div-mod <'%'> term
<term> = constant-exp | unary-exp | <'('> exp-prime <')'>
unary-exp = unary-operator term
unary-operator = #'-' | #'~'
identifier = #'[a-zA-Z_]\\w*\\b'
constant-exp = #'[0-9]+\\b'
keyword = #'int\\b' | #'return\\b' | #'void\\b'"
:auto-whitespace whitespace))
(defn parseable? [result]
(not (insta/failure? result)))
(defn parse [source]
(binop-parser source))
(comment
(parse "int main(void) {return 2;}")
(parse "
int main(void) {
return 2;
}")
(parse "int main(void) {
return -(((((10)))));
}")
(pp/pprint (parse "int main(void) {
return -(((((10)))));
}"))
(pp/pprint
(binop-parser
"int main(void) {
return -1 * 2 - ~3 * -(-4 + 5);
}"))
(pp/pprint
(binop-parser
"int main(void) {
return -2;
}"))
())
|