diff options
| author | Shagun Agrawal <agrawalshagun07@gmail.com> | 2024-08-18 14:30:04 +0530 |
|---|---|---|
| committer | Shagun Agrawal <agrawalshagun07@gmail.com> | 2024-08-18 14:30:04 +0530 |
| commit | 702daa89c7f451f01933e659b59a4daaa01f10ab (patch) | |
| tree | e92040dceb734996a0df5d1dc5c5cba13d7bb925 | |
| parent | 9867129bf45bb620ca56715c74243de3bde9de3c (diff) | |
Fix tacky, assembly, emit phase for chapter 3
| -rw-r--r-- | src/cljcc/emit.clj | 2 | ||||
| -rw-r--r-- | src/cljcc/parser.clj | 67 | ||||
| -rw-r--r-- | src/cljcc/tacky.clj | 66 | ||||
| -rw-r--r-- | src/cljcc/token.clj | 8 |
4 files changed, 82 insertions, 61 deletions
diff --git a/src/cljcc/emit.clj b/src/cljcc/emit.clj index 514cd45..d18edb3 100644 --- a/src/cljcc/emit.clj +++ b/src/cljcc/emit.clj @@ -48,7 +48,7 @@ (let [operand (operand-emit (:operand instruction)) assembly-operator (condp = (:unary-operator instruction) :complement "notl" - :hyphen "negl" + :negate "negl" (throw (AssertionError. (str "Invalid unary operator: " instruction))))] [(format " %s %s" assembly-operator operand)])) diff --git a/src/cljcc/parser.clj b/src/cljcc/parser.clj index f1da784..e8f1791 100644 --- a/src/cljcc/parser.clj +++ b/src/cljcc/parser.clj @@ -1,8 +1,11 @@ (ns cljcc.parser (:require [cljcc.lexer :as l] + [cljcc.token :as t] [clojure.pprint :as pp])) +(declare parse parse-exp) + (defn- expect [kind [token & rst]] (if (= kind (:kind token)) [token rst] @@ -15,25 +18,59 @@ (throw (ex-info "Parser Error." {:expected kinds :actual token})))) -(defn- parse-exp [[{kind :kind :as token} :as tokens]] +(defn- constant-exp-node [v] + {:type :exp + :exp-type :constant-exp + :value v}) + +(defn- unary-exp-node [op v] + {:type :exp + :exp-type :unary-exp + :unary-operator op + :value v}) + +(defn- binary-exp-node [l r op] + {:type :exp + :exp-type :binary-exp + :binary-operator op + :left l + :right r}) + +(defn- parse-factor [[{kind :kind :as token} :as tokens]] (cond - (= kind :number) [{:type :exp - :exp-type :constant-exp - :value (:literal token)} - (rest tokens)] + (= kind :number) [(constant-exp-node (: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]) + [e rst] (parse-factor (rest tokens))] + [(unary-exp-node operator 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})))) + :else (throw (ex-info "Parser Error. Malformed token." {:token token})))) + +(defn- precedence [kind] + (kind t/bin-ops)) + +(defn- parse-exp + ([tokens] + (parse-exp tokens 0)) + ([tokens min-prec] + (loop [[left rst] (parse-factor tokens) + tokens rst] + (let [[{kind :kind :as _token} :as tokens] tokens] + (if (and (contains? t/bin-ops kind) (>= (precedence kind) min-prec)) + (let [[right rst] (parse-exp (rest tokens) (+ (precedence kind) 1))] + (recur [(binary-exp-node left right kind)] rst)) + [left tokens]))))) + +(comment + + (pp/pprint (parse (l/lex " + int main(void) { + return -1 * 2 + 3; + }"))) + + ()) (defn- parse-return-statement [tokens] (let [[_ rst] (expect :kw-return tokens) @@ -88,12 +125,12 @@ (pp/pprint (parse (l/lex " int main(void) { - return -(~~~(2)); + return 1 * 2 - 3 * (4 + 5); }"))) (pp/pprint (l/lex - "int main(void) {return (((2)))}")) + "int main(void) {return 1 + 2;}")) (pp/pprint (l/lex " diff --git a/src/cljcc/tacky.clj b/src/cljcc/tacky.clj index 1d0af27..5f09181 100644 --- a/src/cljcc/tacky.clj +++ b/src/cljcc/tacky.clj @@ -27,23 +27,23 @@ {:type :constant :value v}) -(defn- unary-operator [^String unop] - (condp = unop - "~" :complement - "-" :negate)) +(defn- unary-operator [op] + (condp = op + :complement :complement + :hyphen :negate)) (defn- binary-operator [binop] (condp = binop - :add-exp :add - :sub-exp :sub - :mul-exp :mul - :div-exp :div - :mod-exp :mod - :bit-and-exp :bit-and - :bit-or-exp :bit-or - :bit-xor-exp :bit-xor - :bit-right-shift-exp :bit-right-shift - :bit-left-shift-exp :bit-left-shift)) + :plus :add + :hyphen :sub + :multiply :mul + :divide :div + :remainder :mod + :bit-and :bit-and + :bit-or :bit-or + :bit-xor :bit-xor + :bit-right-shift :bit-right-shift + :bit-left-shift :bit-left-shift)) (defn- unary-instruction [unary-operator src dst] {:type :unary @@ -62,21 +62,6 @@ {:type :return :val val}) -(def binary-exprs - #{:add-exp - :sub-exp - :mul-exp - :mod-exp - :div-exp - :bit-and-exp - :bit-or-exp - :bit-xor-exp - :bit-right-shift-exp - :bit-left-shift-exp}) - -(defn- binary-expr? [v] - (contains? binary-exprs v)) - (declare expression-handler) (defn- constant-expr-handler [e] @@ -86,18 +71,18 @@ (let [inner (expression-handler (:value e)) dst (variable) src (:val inner) - unary-operator (:unary-operator e) + unary-operator (unary-operator (:unary-operator e)) instruction (unary-instruction unary-operator src dst)] {:val dst :instructions (flatten [(:instructions inner) instruction])})) (defn- binary-expr-handler [e] - (let [e1 (expression-handler (nth e 1)) - e2 (expression-handler (nth e 2)) + (let [e1 (expression-handler (:left e)) + e2 (expression-handler (:right e)) src1 (:val e1) src2 (:val e2) dst (variable) - binary-operator (binary-operator (first e)) + binary-operator (binary-operator (:binary-operator e)) instruction (binary-instruction binary-operator src1 src2 dst)] {:val dst :instructions (flatten [(:instructions e1) (:instructions e2) instruction])})) @@ -107,7 +92,8 @@ (cond (= exp-type :constant-exp) (constant-expr-handler e) (= exp-type :unary-exp) (unary-expr-handler e) - (binary-expr? exp-type) (binary-expr-handler e)))) + (= exp-type :binary-exp) (binary-expr-handler e) + :else (throw (ex-info "Tacky error. Invalid expression." {e e}))))) (defn- exp-instructions [exp] (expression-handler exp)) @@ -139,16 +125,6 @@ (pp/pprint (tacky-generate - (p/parse "int main(void) {return 1 * 2 & 3 * (4 + 5);}"))) - - (pp/pprint - (p/parse "int main(void) {return 1 * 2 - 3 * (4 + 5);}")) - - (pp/pprint - (p/parse "int main(void) {return 1 + 2 + -3 + -(4 + 5);}")) - - (pp/pprint - (tacky-generate - (p/parse "int main(void) {return 1 + 2 + -3 + -(4 + 5);}"))) + (p/parse (l/lex "int main(void) {return 1 * -2 / ~3 * (4 - 5);}")))) ()) diff --git a/src/cljcc/token.clj b/src/cljcc/token.clj index 63c1eda..429e593 100644 --- a/src/cljcc/token.clj +++ b/src/cljcc/token.clj @@ -37,6 +37,14 @@ (def chrs #{}) +(def bin-ops + "Binary operanrs and their precedence." + {:plus 40 + :hyphen 40 + :multiply 50 + :divide 50 + :remainder 50}) + (def chrs-kind-map {\( :left-paren \) :right-paren |
