(t (values nil nil)))))
(lambda () (recur node nil))))
-(defun parse-tree (string)
+(defun parse-tree (string &key (start 0) (end (length string)))
"Parse STRING, and return the tree described.
The syntax is simple:
The ambiguity is resolved by always treating `(' as a tree when a tree is
expected."
- (let ((len (length string)))
- (labels ((parse (i)
- (cond ((and (< i len) (char= (char string i) #\())
- (multiple-value-bind (left i) (parse (1+ i))
- (unless (< i len) (error "no data"))
- (let ((data (char string i)))
- (multiple-value-bind (right i) (parse (1+ i))
- (unless (and (< i len)
- (char= (char string i) #\)))
- (error "missing )"))
- (values
- (make-node :left left :data data :right right)
- (1+ i))))))
- (t (values nil i)))))
- (multiple-value-bind (tree i) (parse 0)
- (unless (= i len) (error "trailing junk"))
- tree))))
+ (labels ((parse (i)
+ (cond ((and (< i end) (char= (char string i) #\())
+ (multiple-value-bind (left i) (parse (1+ i))
+ (unless (< i end) (error "no data"))
+ (let ((data (char string i)))
+ (multiple-value-bind (right i) (parse (1+ i))
+ (unless (and (< i end)
+ (char= (char string i) #\)))
+ (error "missing )"))
+ (values
+ (make-node :left left :data data :right right)
+ (1+ i))))))
+ (t (values nil i)))))
+ (multiple-value-bind (tree i) (parse start)
+ (unless (= i end) (error "trailing junk"))
+ tree)))
;;;--------------------------------------------------------------------------
;;; Main program.
-(defun main (args)
+(defun main (prog args)
"Main program: process ARGS."
- (destructuring-bind (&optional a b &rest junk) args
- (cond ((or (null a) junk) (error "bad args"))
- ((null b) (format t "~{~C~}~%"
- (list-iterator (iterate-fringe (parse-tree a)))))
- (t (format t "~:[no match~;match~]~%"
- (same-iterators-p (iterate-fringe (parse-tree a))
- (iterate-fringe (parse-tree b))))))))
-
-#+cl-launch
-(progn
- (defparameter *program-name*
- (pathname-name (or (cl-launch:getenv "CL_LAUNCH_FILE")
- (namestring *load-pathname*)
- "<unknown>")))
- (defun launch ()
- (flet ((bail (format args)
- (format *error-output* "~A: ~?~%" *program-name* format args)
- (cl-launch:quit 1)))
- (handler-case
- (main cl-launch:*arguments*)
+ (flet ((bail (format args)
+ (format *error-output* "~A: ~?~%" prog format args)
+ (return-from main 1)))
+ (handler-case
+ (destructuring-bind (&optional a b &rest junk) args
+ (cond ((or (null a) junk)
+ (error "bad args"))
+ ((null b)
+ (format t "~{~C~}~%"
+ (list-iterator (iterate-fringe (parse-tree a)))))
+ (t
+ (format t "~:[no match~;match~]~%"
+ (same-iterators-p
+ (iterate-fringe (parse-tree a))
+ (iterate-fringe (parse-tree b)))))))
(simple-error (err)
(bail (simple-condition-format-control err)
(simple-condition-format-arguments err)))
(error (err)
- (bail "~A" err))))))
+ (bail "~A" err)))
+ 0))
+
+#+cl-launch
+(defun launch ()
+ (cl-launch:quit (main (or (cl-launch:getenv "CL_LAUNCH_FILE")
+ (namestring *load-pathname*)
+ "<unknown>")
+ cl-launch:*arguments*)))
+
+#+(and (not cl-launch) ecl)
+(ext:quit (main (ext:argv 0)
+ (loop for i from 1 below (ext:argc) collect (ext:argv i))))
+
+#+(and (not cl-launch) sbcl)
+(sb-ext:quit :unix-status (main (pathname-name *load-pathname*)
+ (cdr sb-ext:*posix-argv*)))
;;;----- That's all, folks --------------------------------------------------