~kingcons/rascal

d4cde863c4dce5a499d0068bb16272312805e9ef — Brit Butler 1 year, 1 month ago 8c92d54
Wire the parser up to parse-program and add tests.
5 files changed, 53 insertions(+), 3 deletions(-)

A examples/lang-int1.ras
M rascal.asd
M src/parse.lisp
A test/parse.lisp
M test/tests.lisp
A examples/lang-int1.ras => examples/lang-int1.ras +1 -0
@@ 0,0 1,1 @@
(+ (read) (- 8))

M rascal.asd => rascal.asd +2 -1
@@ 41,6 41,7 @@
  :components ((:module "test"
                :serial t
                :components
                ((:file "tests"))))
                ((:file "parse")
                 (:file "tests"))))
  :perform (test-op (o s)
                    (uiop:symbol-call '#:rascal.test '#:test)))

M src/parse.lisp => src/parse.lisp +24 -1
@@ 1,6 1,11 @@
(mgl-pax:define-package :rascal.parse
  (:use :cl :alexandria :mgl-pax :esrap)
  (:import-from :serapeum #:~>>))
  (:import-from :serapeum
                #:~>>
                #:chomp)
  (:import-from :rascal.protocol
                #:program
                #:parse-program))

(in-package :rascal.parse)



@@ 71,6 76,24 @@ nodes are also provided."
                     :operator (first children)
                     :args (second children)))))

(defrule lang-int
    (or digits form))

;; (defrule identifier
;;     (+ (or letter digit #\- #\! #\?))
;;   (:text t))

;;;; KLUDGE:
;;;; At some point, we will need to rework this to support languages
;;;; with multiple toplevel forms rather than a single form.

(defmethod parse-program ((source pathname))
  (unless (probe-file source)
    (error 'missing-file "Could not find file with path: ~A" source))
  (let ((contents (chomp (read-file-into-string source))))
    (parse-program contents)))

(defmethod parse-program ((source string))
  (make-instance 'program
                 :body (parse 'lang-int source)
                 :metadata nil))

A test/parse.lisp => test/parse.lisp +25 -0
@@ 0,0 1,25 @@
(defpackage :rascal.test.parse
  (:use :cl :rascal.protocol :rascal.parse :try)
  (:import-from :serapeum #:concat)
  (:export #:test-parse))

(in-package :rascal.test.parse)

(defun example (name)
  (let ((relpath (concat "examples/" name)))
    (asdf:system-relative-pathname :rascal relpath)))

(deftest test-parse ()
  (test-lang-int-examples))

(deftest test-lang-int-examples ()
  (let ((example-1 (parse-program (example "lang-int1.ras"))))
    (is (typep example-1 'program))
    (let ((root-node (body example-1)))
      (is (eql (operator-of root-node) '+))
      (is (= 2 (length (args-of root-node))))
      (let ((subforms (mapcar #'operator-of (args-of root-node))))
        (is (equalp subforms '(read -)))))))

#+nil
(try 'test-parse)

M test/tests.lisp => test/tests.lisp +1 -1
@@ 5,7 5,7 @@
(in-package :rascal.test)

(deftest test-all ()
  (is (= (+ 2 2) 4)))
  (rascal.test.parse:test-parse))

(defun test (&key (debug nil) (print 'unexpected) (describe 'unexpected))
  (warn-on-tests-not-run ((find-package :rascal-test))