aboutsummaryrefslogtreecommitdiff
path: root/src/cljcc/parser.clj
blob: 0d95ac816bc9077e437abb584c01d3e2a37ccfc1 (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
(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))

(def bitwise-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> = bitwise-exp-prime | mul-exp | div-exp | mod-exp
    mul-exp = mul-div-mod <'*'> bitwise-exp-prime
    div-exp = mul-div-mod <'/'> bitwise-exp-prime
    mod-exp = mul-div-mod <'%'> bitwise-exp-prime
    <bitwise-exp-prime> = bit-and-exp | bit-or-exp | bit-xor-exp | bit-left-shift-exp | bit-right-shift-exp | term
    bit-and-exp = bitwise-exp-prime <'&'> term
    bit-or-exp = bitwise-exp-prime <'|'> term
    bit-xor-exp = bitwise-exp-prime <'^'> term
    bit-left-shift-exp = bitwise-exp-prime <'<<'> term
    bit-right-shift-exp = bitwise-exp-prime <'>>'> 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]
  (bitwise-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 1 & 2 + 6 & 6;
   }"))

  (pp/pprint
   (binop-parser
    "int main(void) {
    return -1 * 2 - ~3 * -(-4 + 5);
     }"))

  (pp/pprint
   (binop-parser
    "int main(void) {
       return -2;
     }"))

  ())