diff options
author | Siddarth Suresh <155843085+SiddarthSuresh98@users.noreply.github.com> | 2025-04-12 13:06:51 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-12 13:06:51 -0400 |
commit | fc20e7e7276b712f1e8db773b9215f900e877169 (patch) | |
tree | caecdd1499d2e391cd5bd2dcde3aebfade002a09 /src/parse.lisp | |
parent | 5dbf0b63988b42c112ca0087cbbbb090566df5c1 (diff) | |
parent | 639098b1ea82be82bd18a4af415458fcbaf5e20b (diff) |
Merge pull request #8 from bdunahu/bdunahu
Add write raw bytes stage
Diffstat (limited to 'src/parse.lisp')
-rw-r--r-- | src/parse.lisp | 86 |
1 files changed, 47 insertions, 39 deletions
diff --git a/src/parse.lisp b/src/parse.lisp index d971444..0ea6c0d 100644 --- a/src/parse.lisp +++ b/src/parse.lisp @@ -9,60 +9,62 @@ (+ (or #\space #\tab)) (:constant nil)) -(esrap:defrule nl (+ #\newline) +(esrap:defrule eol (and (esrap:? space) (esrap:? (and #\; (* (not #\newline)))) #\newline) (:constant nil)) -(esrap:defrule nl-inc (+ #\newline) - (:lambda (n) - (declare (ignore n)) - (incf line-number) - nil)) +(esrap:defrule newline (+ eol) + (:constant nil)) -(esrap:defrule alpha (+ (alphanumericp character)) +(esrap:defrule sign (or #\+ #\-)) + +(esrap:defrule alphanumeric (+ (alphanumericp character)) (:text t)) ;;; defines rules to parse an integer in various bases (defmacro define-number-rule ()) -(esrap:defrule binary (and #\0 #\B (+ (or "0" "1"))) +(esrap:defrule binary-number (and #\0 #\B (+ (or "0" "1"))) (:lambda (e) (parse-integer (esrap:text (cddr e)) :radix 2))) -(esrap:defrule octal (and #\0 #\O (+ (or (esrap:character-ranges (#\0 #\7))))) +(esrap:defrule octal-number (and #\0 #\O (+ (or (esrap:character-ranges (#\0 #\7))))) (:lambda (e) (parse-integer (esrap:text (cddr e)) :radix 8))) -(esrap:defrule decimal (+ (or (esrap:character-ranges (#\0 #\9)))) +(esrap:defrule decimal-number (+ (or (esrap:character-ranges (#\0 #\9)))) (:lambda (e) (parse-integer (esrap:text e) :radix 10))) -(esrap:defrule hex (and #\0 #\X (+ (or (esrap:character-ranges (#\0 #\9)) +(esrap:defrule hexadecimal-number (and #\0 #\X (+ (or (esrap:character-ranges (#\0 #\9)) "A" "B" "C" "D" "E" "F"))) (:lambda (e) (parse-integer (esrap:text (cddr e)) :radix 16))) -(esrap:defrule int (or binary octal hex decimal)) +(esrap:defrule integer (and (esrap:? sign) (or binary-number octal-number + hexadecimal-number decimal-number)) + (:destructure (s i) + (if (and s (string= s "-")) (- i) i))) ;;; defines rules to parse an operand -(esrap:defrule register (and #\$ int) +(esrap:defrule register (and #\$ integer) (:function cadr) (:lambda (e) (list 'emit::rr e))) -(esrap:defrule var alpha - (:lambda (e) (list (list 'emit::rr 0) (list 'emit::var e)))) +(esrap:defrule variable alphanumeric + (:lambda (e) (list 'emit::var e))) -(esrap:defrule dereference (and (esrap:? (or #\+ #\-)) int #\( register #\)) - (:destructure (s i1 w1 r w2) - (declare (ignore w1 w2)) - (list r (list 'emit::imm (if (and s (string= s "-")) (- i1) i1))))) +(esrap:defrule immediate (or integer variable) + (:lambda (e) e)) -(esrap:defrule immediate int - (:lambda (e) (list 'emit::imm e))) +(esrap:defrule dereference (and immediate #\( register #\)) + (:destructure (i1 w1 r w2) + (declare (ignore w1 w2)) + (list r i1))) ;;; defines rules to parse labels -(esrap:defrule label alpha +(esrap:defrule label alphanumeric (:lambda (e) (list 'emit::l e line-number))) -(esrap:defrule label-decl (and alpha #\:) +(esrap:defrule label-declaration (and alphanumeric #\:) (:function car) (:lambda (e) (util:add-label e line-number) @@ -82,11 +84,12 @@ (generate-mnemonic 'i-type-2-m '("STOREV" "STORE")) (generate-mnemonic 'j-type-1-m '("JMP" "JAL")) (generate-mnemonic 'j-type-2-m '("PUSH" "POP")) +(generate-mnemonic 'j-type-3-m '("RET" "NOP")) ;; we need to reverse to ensure rules like "ADDV" are matched before "ADD" (generate-mnemonic 'r-type-3-m (reverse util:r-type)) (generate-mnemonic 'i-type-3-m (reverse util:i-type)) -(generate-mnemonic 'j-type-3-m (reverse util:j-type)) +(generate-mnemonic 'j-type-4-m (reverse util:j-type)) ;; TODO this is pretty gross (defmacro defrule-instr (name type-id order &rest destructure-pattern) @@ -107,15 +110,15 @@ DESTRUCTURE-PATTERN is the list of non-terminals on the right side of the gramma (defrule-instr r-type-1 'emit::r (1 2 0) register register) (defrule-instr r-type-2 'emit::r (0 1 2) register register) (defrule-instr r-type-3 'emit::r (1 2 0) register register register) -(defrule-instr i-type-3 'emit::i (0 1 2) register register immediate) -(defrule-instr j-type-3 'emit::j (1 0) label) +(defrule-instr i-type-3 'emit::i (1 0 2) register register immediate) +(defrule-instr j-type-4 'emit::j (1 0) label) -(esrap:defrule i-type-1 (and i-type-1-m space register space (or dereference var)) +(esrap:defrule i-type-1 (and i-type-1-m space register space dereference) (:destructure (m w1 s w2 di) (declare (ignore w1 w2)) `(emit::i ,m ,s ,@di))) -(esrap:defrule i-type-2 (and i-type-2-m space register space (or dereference var)) +(esrap:defrule i-type-2 (and i-type-2-m space register space dereference) (:destructure (m w1 s w2 di) (declare (ignore w1 w2)) `(emit::i ,m ,@(util:insert-in-middle di s)))) @@ -128,47 +131,52 @@ DESTRUCTURE-PATTERN is the list of non-terminals on the right side of the gramma (esrap:defrule j-type-2 (and j-type-2-m space register) (:destructure (m w r) (declare (ignore w)) - `(emit::j ,m ,r (emit::imm 0)))) + `(emit::j ,m ,r 0))) + +(esrap:defrule j-type-3 j-type-3-m + (:lambda (m) + `(emit::j ,m (emit::rr 0) 0))) (esrap:defrule instr (or r-type-1 r-type-2 r-type-3 i-type-1 i-type-2 - i-type-3 j-type-1 j-type-2 j-type-3)) + i-type-3 j-type-1 j-type-2 j-type-3 j-type-4)) ;;; defines rules to parse the .text segment -(esrap:defrule instr-clean (and (esrap:? space) instr (esrap:? space) nl-inc) - (:function cadr)) +(esrap:defrule instr-clean (and (esrap:? space) instr newline) + (:function cadr) + (:lambda (i) (incf line-number) i)) -(esrap:defrule label-clean (and label-decl (esrap:? space) nl) +(esrap:defrule label-clean (and label-declaration newline) (:function car)) (esrap:defrule text-line (or instr-clean label-clean)) -(esrap:defrule text (and ".TEXT" (esrap:? space) nl (* text-line)) +(esrap:defrule text (and ".TEXT" (esrap:? space) newline (* text-line)) (:function cadddr) (:lambda (e) `(emit::x ,@(remove nil e)))) ;;; defines rules to parse the .data segment -(esrap:defrule data-word (and (esrap:? space) int) +(esrap:defrule data-word (and (esrap:? space) integer) (:function cadr) (:lambda (e) (incf var-offset) e)) -(esrap:defrule var-decl alpha +(esrap:defrule var-declaration alphanumeric (:lambda (e) (util:add-variable e var-offset) nil)) -(esrap:defrule data-line (and (esrap:? space) var-decl (+ data-word) (esrap:? space) nl) +(esrap:defrule data-line (and (esrap:? space) var-declaration (+ data-word) newline) (:function caddr)) -(esrap:defrule data (and ".DATA" (esrap:? space) nl (* data-line)) +(esrap:defrule data (and ".DATA" (esrap:? space) newline (* data-line)) (:function cadddr) (:lambda (e) `(emit::d ,@(apply #'append e)))) ;;; defines rules to parse a program -(esrap:defrule str->ast (and (* (or space nl)) data text) +(esrap:defrule str->ast (and (* (or space newline)) data text) (:function cdr) (:lambda (e) `(emit::p ,@e))) |