diff options
author | bd <bdunahu@operationnull.com> | 2025-04-08 01:56:18 -0400 |
---|---|---|
committer | bd <bdunahu@operationnull.com> | 2025-04-08 01:56:18 -0400 |
commit | b85c10ba1c53f1b442fea6bde4c2a2f73cfe5d6b (patch) | |
tree | 643d37db692c19d1ef64223eadcac7a28dbbd7db | |
parent | 4c76966b49e8559f710013463dac04143c1f4e09 (diff) |
Simplify lexer-error handling, skeletion parsing functions for types
-rw-r--r-- | src/lex.lisp | 30 | ||||
-rw-r--r-- | src/package.lisp | 17 | ||||
-rw-r--r-- | src/parse.lisp | 42 | ||||
-rw-r--r-- | src/util.lisp | 32 | ||||
-rw-r--r-- | t/lex.lisp | 4 | ||||
-rw-r--r-- | t/parse.lisp | 14 |
6 files changed, 86 insertions, 53 deletions
diff --git a/src/lex.lisp b/src/lex.lisp index d5c77a1..5b1457d 100644 --- a/src/lex.lisp +++ b/src/lex.lisp @@ -1,18 +1,12 @@ (in-package #:lex) -(define-condition invalid-immediate-or-keyword (error) - ((chr :initarg :chr - :initform nil - :reader chr) - (instance :initarg :instance - :initform nil - :reader instance)) +(define-condition lexer-error (error) + ((message :initarg :message + :initform nil + :reader message)) (:report (lambda (condition stream) - (format stream - "LEX failed--encountered ~a while reading ~a." - (chr condition) (instance condition)))) - (:documentation "Dedicated error for immediates/keywords which contain -invalid characters.")) + (format stream "~A" (message condition)))) + (:documentation "Dedicated error for an invalid lex.")) (defun file->tokens (file) "Opens FILE and parses returns a list of tokens, or @@ -63,7 +57,9 @@ Comments start with a semi-colon ';' and all tokens after are ignored." ((alpha-char-p chr) (read-keyword chr)) - (t (error (format nil "~a is not a valid lexical symbol.~%" chr)))))) + (t (error 'lexer-error + :message + (format nil "LEX failled--~a is not a valid lexical symbol.~%" chr)))))) (defun read-immediate (chr) "Reads a sequence of digits, in base 2, 8, 10, or 16.. Throws @@ -74,7 +70,9 @@ Comments start with a semi-colon ';' and all tokens after are ignored." (cond ((and (not (null chr)) (digit-char-p chr)) (read-immediate-helper (cons (read-char *standard-input* nil) chrs-so-far))) ((and (not (null chr)) (alpha-char-p chr)) - (error 'invalid-immediate-or-keyword :chr chr :instance "immediate")) + (error 'lexer-error + :message + (format nil "LEX failed--encountered ~a while reading immediate.~%" chr))) (t (reverse chrs-so-far))))) (let* ((next (peek-char nil *standard-input* nil)) @@ -99,7 +97,9 @@ error if a digit is encountered." (cond ((and (not (null chr)) (alpha-char-p chr)) (read-keyword-helper (cons (read-char *standard-input* nil) chrs-so-far))) ((and (not (null chr)) (digit-char-p chr)) - (error 'invalid-immediate-or-keyword :chr chr :instance "keyword")) + (error 'lexer-error + :message + (format nil "LEX failed--encountered ~a while reading keyword.~%" chr))) (t (reverse chrs-so-far))))) (coerce (read-keyword-helper (list chr)) 'string)) diff --git a/src/package.lisp b/src/package.lisp index d999783..3364856 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -1,4 +1,4 @@ -(defpackage #:rva +helper(defpackage #:rva (:use #:cl) (:export #:main)) @@ -6,18 +6,21 @@ (:use #:cl) (:export #:asm-extension? #:format-as-binary - #:label-loc - #:mnemonic-loc)) + #:type-r + #:type-i + #:type-j + #:label-loc)) (defpackage #:lex (:use #:cl) - (:export #:file->tokens + (:export #:lexer-error + #:file->tokens ;; exported for testing only - #:read-token - #:invalid-immediate-or-keyword)) + #:read-token)) (defpackage #:parse (:use #:cl) - (:export #:tokens->ast + (:export #:parser-error + #:tokens->ast ;; exported for testing only #:extract-label)) diff --git a/src/parse.lisp b/src/parse.lisp index 8bd8c50..3052583 100644 --- a/src/parse.lisp +++ b/src/parse.lisp @@ -1,9 +1,20 @@ -(in-package #:parse) +helper(in-package #:parse) + +(define-condition parser-error (error) + ((message :initarg :message + :initform nil + :reader message)) + (:report (lambda (condition stream) + (format stream "~A" (message condition)))) + (:documentation "Dedicated error for an invalid parse.")) (defun tokens->ast (program) - (let ((program (remove nil (mapcar #'extract-label program)))) - ;; TODO - program)) + "Given PROGRAM, which is a list of lists of symbols, +filters out the labels and parses." + ;; TODO add directives + (let ((program (remove nil (mapcar #'extract-label program))) + (i 0)) + (mapcar (lambda (l) (extract-instruction l i)) program))) (let ((i 0)) (defun extract-label (line) @@ -19,3 +30,26 @@ processing." (satisfies (lambda (x) (equal x 'lex::colon)))) (progn (push (cons (read-from-string id) i) util:label-loc) nil)) (_ (progn (incf i) line))))) + +(defun extract-instruction (line i) + "Given instruction LINE, determines the expected type format and passes +LINE and the index I to the the respective function." + ;; TODO add pseudo-ops (i.e., nop, mov, ...) + (let* ((type-map '((r-type . extract-r-type) + (i-type . extract-i-type) + (j-type . extract-j-type))) + (keyword (car line)) + (type-fn (cdr (assoc keyword type-map)))) + (if type-fn + (funcall type-fn line i) + (error 'parser-error + (format nil "PARSE failed--~a is not a known keyword.~%" (keyword)))))) + +(defun extract-r-type (line i) + 'r) + +(defun extract-i-type (line i) + 'i) + +(defun extract-j-type (line i) + 'j) diff --git a/src/util.lisp b/src/util.lisp index 1ea6dfc..5edee4a 100644 --- a/src/util.lisp +++ b/src/util.lisp @@ -11,27 +11,17 @@ (declare (type (integer 0 *) len)) (format nil "~V,'0b" len num)) -(defmacro generate-type-map (type opsize ops) - "Generates an alist where the key corresponds to an element in -OPS, while the value is the index of that key (padded to OPSIZE) -concatenated with TYPE." - `(let ((i 0)) - (mapcar (lambda (x) - (incf i) - (cons x (concatenate 'string ,type - (format-as-binary i ,opsize)))) - ,ops))) +(defparameter type-r + '(ADD SUB MUL QUOT REM SFTR SFTL AND OR NOT XOR ADDV SUBV MULV DIVV CMP CEV) + "R-type instructions.") + +(defparameter type-i + '(LOAD LOADV ADDI SUBI SFTRI SFTLI ANDI ORI XORI STORE STOREV) + "I-type instructions.") + +(defparameter type-j + '(JMP JRL JAL BEQ BGT BUF BOF PUSH POP) + "J-type instructions.") (defparameter label-loc '() "A symbol table mapping label names to line indices.") - -(defparameter mnemonic-loc - `(,@(generate-type-map "00" 5 - '(ADD SUB MUL QUOT REM SFTR SFTL AND OR NOT - XOR ADDV SUBV MULV DIVV CMP CEV)) - ,@(generate-type-map "01" 4 - '(LOAD LOADV ADDI SUBI SFTRI SFTLI ANDI ORI - XORI STORE STOREV)) - ,@(generate-type-map "10" 4 - '(JMP JRL JAL BEQ BGT BUF BOF PUSH POP))) - "An alist mapping known mnemonics to their binary representation.") @@ -76,7 +76,7 @@ (handler-case (progn (read-this "0v0" (lex:read-token)) (fail)) - (lex:invalid-immediate-or-keyword ()))) + (lex:lexer-error ()))) ;; do we want a custom error for this too? (test read-token-immediate-radix @@ -97,4 +97,4 @@ (handler-case (progn (read-this "sub0" (lex:read-token)) (fail)) - (lex:invalid-immediate-or-keyword ()))) + (lex:lexer-error ()))) diff --git a/t/parse.lisp b/t/parse.lisp index 2ab3e76..bd1310f 100644 --- a/t/parse.lisp +++ b/t/parse.lisp @@ -11,10 +11,16 @@ (test extract-label-not-a-label-one (let ((lst '("NICE" "TRY"))) - (is (equal lst - (parse:extract-label lst))))) + (is (equal lst + (parse:extract-label lst))))) (test extract-label-not-a-label-two (let ((lst '("LOOP" lex::colon lex::colon))) - (is (equal lst - (parse:extract-label lst))))) + (is (equal lst + (parse:extract-label lst))))) + +(test extract-line-invalid-type + (handler-case + (progn (parse:tokens->ast '(("foo" LEX::DOLLAR))) + (fail)) + (lex:parser-error ()))) |