diff options
| author | bd <bdunahu@operationnull.com> | 2024-12-31 01:41:03 -0700 | 
|---|---|---|
| committer | bd <bdunahu@operationnull.com> | 2024-12-31 01:41:03 -0700 | 
| commit | c4b297fcb0e981591ea8c98339498a68c0a89ce0 (patch) | |
| tree | b90e12c1c7020f5cb7b00c5ac3d012f18cef4036 | |
| parent | af71acaa9f22f17dc1a6ce0737b6255d3af0a7ab (diff) | |
Add (and test) sub, add, inc/decrement, and bit-complement to lexer
| -rwxr-xr-x | src/gscc | 50 | ||||
| -rw-r--r-- | src/modules/lexer/lexer.scm | 21 | ||||
| -rw-r--r-- | src/unit-tests/lexer/lexer-test.scm | 16 | 
3 files changed, 60 insertions, 27 deletions
@@ -30,13 +30,10 @@ Options:    (let ((extension (string-drop file (- (string-length file) 2))))      (string=? extension ".c"))) -(define (preprocess file) -  "Returns an input port containing FILE processed with gcc." -  (open-input-pipe (string-append "gcc -E -P " file))) - -(define (process port parse? generate? write?) +(define (process file parse? generate? write? dest)    "Driver for lexing, parsing, and assembly generation." -  (let* ((tokens (begin (set-current-input-port port) +  (let* ((port (preprocess file)) +         (tokens (begin (set-current-input-port port)                          (read-tokens))))      (close-input-port port)      (when parse? @@ -44,7 +41,19 @@ Options:          (when generate?            (let ((assembly-ast (g-program c-ast)))              (when write? -              (e-program assembly-ast)))))))) +              (let ((program (e-program assembly-ast)) +                    (a-file (string-append dest ".s"))) +                (when (file-exists? a-file) +                  (delete-file a-file)) +                (let ((port (open-output-file a-file))) +                  (display program port) +                  (close-port port)) +                (when (postprocess a-file dest) +                  (display (string-concatenate `("Postprocess reported success (wrote " ,dest ").\n")))))))))))) + +(define (preprocess file) +  "Returns an input port containing FILE processed with gcc." +  (open-input-pipe (string-append "gcc -E -P " file)))  (define (postprocess src dest)    "Assembles and links SRC, producing executable DEST. @@ -52,6 +61,7 @@ Returns #f on a failure, #t on a success."    (zero? (system (string-concatenate `("gcc " ,src " -o " ,dest)))))  (define (main args) +  "Entry point for the gscc. Handles user args and performs initial validity check."    (let* ((option-spec            '((version (single-char #\v) (value #f))              (debug   (single-char #\d) (value #f)) @@ -60,9 +70,7 @@ Returns #f on a failure, #t on a success."              (codegen (single-char #\c) (value #f))))           (options (getopt-long args option-spec))           (rest (option-ref options '() #f)) -         (file (if (null? rest) #f (car rest))) -         (executable (string-drop-right file 2)) -         (assembly (string-append executable ".s"))) +         (file (if (null? rest) #f (car rest))))      (cond       ((option-ref options 'version #f)        (display (string-concatenate `("gscc (the 'Guile Scheme C Compiler', " ,version ")\n")))) @@ -72,19 +80,15 @@ Returns #f on a failure, #t on a success."            (not (equal? 'regular (stat:type (stat file))))            (not (c-extension? file))) (error "The file could not be read, or it is not a C source code file."))       (#t -      (let* ((port (preprocess file)) -             (parse? (not (option-ref options 'lex #f))) -             (generate? (not (option-ref options 'parse #f))) -             (write? (not (option-ref options 'codegen #f))) -             (program (process port parse? generate? write?))) -        (when write? -          (when (file-exists? assembly) -            (delete-file assembly)) -          (let ((port (open-output-file assembly))) -            (display program port) -            (close-port port)) -          (when (postprocess assembly executable) -            (display (string-concatenate `("Postprocess reported success (wrote " ,executable ").\n")))))))))) +      (let ((parse? (not (option-ref options 'lex #f))) +            (generate? (not (option-ref options 'parse #f))) +            (write? (not (option-ref options 'codegen #f)))) +        (process file +                 parse? +                 generate? +                 write? +                 (string-drop-right file 2))))))) +  ;; Local Variables:  ;; mode: scheme diff --git a/src/modules/lexer/lexer.scm b/src/modules/lexer/lexer.scm index a6be215..4078db4 100644 --- a/src/modules/lexer/lexer.scm +++ b/src/modules/lexer/lexer.scm @@ -28,13 +28,25 @@ current input port."         'close-brace)        ((eqv? chr #\;)         'semi-colon) +      ((eqv? chr #\~) +       'complement) -      ((char-alphabetic? chr) -       (lookup-keyword (read-identifier chr))) +      ((eqv? chr #\+) +       (if (take-two? chr) +           'increment +           'add)) + +      ((eqv? chr #\-) +       (if (take-two? chr) +           'decrement +           'sub))        ((char-numeric? chr)         (read-constant chr)) +      ((char-alphabetic? chr) +       (lookup-keyword (read-identifier chr))) +        (#t (error "illegal lexical syntax")))))  (define (read-constant chr) @@ -58,6 +70,11 @@ current input port."              (#t (reverse chrs-so-far)))))    (list->string (read-identifier-helper (list chr)))) +(define (take-two? chr) +  (if (eqv? chr (peek-char)) +      (read-char) +      #f)) +  (define (lookup-keyword id)    "Given identifier ID, converts it to a keyword  if one is known." diff --git a/src/unit-tests/lexer/lexer-test.scm b/src/unit-tests/lexer/lexer-test.scm index 48291b9..324ba66 100644 --- a/src/unit-tests/lexer/lexer-test.scm +++ b/src/unit-tests/lexer/lexer-test.scm @@ -35,6 +35,18 @@    '(1)    (read-tokens)) +(test-equal (read-this "~+-") +  '(complement add sub) +  (read-tokens)) + +(test-equal (read-this "---") +  '(decrement sub) +  (read-tokens)) + +(test-equal (read-this "+--") +  '(add decrement) +  (read-tokens)) +  (test-equal (read-this "0")    '(0)    (read-tokens)) @@ -52,7 +64,7 @@    (read-tokens))  (test-error (read-this "3.4") -	    (read-tokens)) +            (read-tokens))  (test-equal (read-this "a")    '("a") @@ -63,7 +75,7 @@    (read-tokens))  (test-error (read-this "1foo") -	    (read-tokens)) +            (read-tokens))  (test-equal (read-this "void")    '(void)  | 
