This is the grammar used to parse the simple example shown, and other more complex, many-state diagrams, not shown. This grammar uses specialized Lisp functions, appended the end of this grammar, to describe the detailed geometrical arrangement of the component of arrowheads.
(setf *grammar* ; a grammar object (defgrammar ;;; ********** < Finite Automato > ************* ( FA -> Init-state Transitions Final-states (Transitions) (Final-states) (Init-state) ) ; ;;; ********** < Transitions > ************* ( Transition -> A-state_1 Labeled-arrow A-state_2 (Labeled-arrow) (A-state_1 (touch (leave-pt (arrow Labeled-arrow)) '?)) (A-state_2 (touch (reach-pt (arrow Labeled-arrow)) '?)) ) ; ( Transitions -> set ( Transition ) ) ; ;;; ********** < Labeled-arrow > ************* ( Label -> Text (Text :constraints (numeric-textp Text)) ) ; ( Labeled-arrow -> Arrow Label (Arrow) (Label (touch Arrow '?) :select (min (distance (center Label) (arrow-back Arrow)))) ) ; ;;; ********** < Arrow > ************* ( Arrow -> Arrow-back Arrow-head (:additional-slots (leave-pt . (get-leave-pt self)) (reach-pt . (pt (arrow-head self)))) (Arrow-head) (Arrow-back (extends (touch (pt arrow-head) '?)) :select (min (distance (list (left-endpoint arrow-back) (right-endpoint arrow-back)) (pt arrow-head)))) ) ; ;;; ********** < Arrow-head > ************* ( Arrow-head -> Short-line_1 Short-line_2 (:additional-slots (pt . (get-arrow-head-pts self 'common-pt))) (Short-line_1) (Short-line_2 (touch Short-line_1 '?) :constraints (different Short-line_1 Short-line_2) (left (center Short-line_1) (center Short-line_2) :strictly t) (same-length (line Short-line_1) (line Short-line_2) :ratio 1.7) (< (distance (endpts short-line_1) (endpts short-line_2)) (/ (a-length (line Short-line_1)) 5.0))) ) ; ~ 40 ;;; ********** < Arrow-back > ************* ( Arrow-back -> Line (:additional-slots (left-endpoint . (left-endpoint (Line self))) (right-endpoint . (right-endpoint (Line self)))) (:constraints (long Line :ratio 22)) ) ; ( Arrow-back -> Curve-back (:additional-slots (left-endpoint . (left-endpoint (Curve-back self))) (right-endpoint . (right-endpoint (Curve-back self))))) ; ( Curve-back -> set ( Curve ) (:constraint connected) ) ; ;;; ********** < Short-line > ************* ( Short-line -> Line (:additional-slots (endpts . (endpoints (Line self))) ;(length . (a-length (Line self))) ) ;; add length (:constraints (short Line)) ) ; ;;; ********** < A-state > ************* ( A-state -> Circle Text (Circle :constraints (not (contained Circle (some* [circle])))) (Text (contain Circle '?)) ) ; ;;; ********** < Final-states > ************* ( Final-state -> A-state (A-state :constraints (contain (circle A-state) (some* [circle] :in (touch '? A-state)))) ) ; ( Final-states -> set ( Final-state ) ) ; ;;; ********** Init-state ************* ( Init-state -> A-state Arrow (A-state) (Arrow (touch A-state '?) :constraints (touch (reach-pt Arrow) A-state) (null (some* [a-state] :in (touch '? (leave-pt Arrow))))) ) ; ) ) ;;; ------------------------------------------- ;;; Non supported functions ;;; ------------------------------------------- (defmethod left-endpoint ((go curve-back)) (apply #'left-point (curve-cluster-endpoints (value go)))) (defmethod right-endpoint ((go curve-back)) (apply #'right-point (curve-cluster-endpoints (value go)))) ;;; (defmethod distance ((pt a-point) (go arrow-back<1>) &key (min-max 'min)) ; <1> the first alternative in the grammar. (distance pt (line go))) (defmethod distance ((pt a-point) (go arrow-back<2>) &key (min-max 'min)) (pt-curve-cluster-dist pt (value (curve-back go)))) ;;; ------------------------------------------- (defmethod get-arrow-head-pts ((ob arrow-head) type) (let* ((line1-end-pts (make-array '(2) :initial-contents (a-line-terminators (line (short-line_1 ob))))) (line2-end-pts (make-array '(2) :initial-contents (a-line-terminators (line (short-line_2 ob))))) (distance-array (make-array '(2 2) :initial-element nil))) (dotimes (i 2) (dotimes (j 2) (setf (aref distance-array i j) (distance (aref line1-end-pts i) (aref line2-end-pts j))))) (let (common-pt f-p1 f-p2 min id-1 id-2); ;; common-pt corresponds to the "corner" point of the arrow head (setf min (aref distance-array 0 0)) (dotimes (i 2) (dotimes (j 2) (when (<= (aref distance-array i j) min) (setf min (aref distance-array i j)) (setf id-1 i) (setf id-2 j)))) (setf common-pt (aref line1-end-pts id-1)) (setf f-p1 (aref line1-end-pts (- 1 id-1))) (setf f-p2 (aref line2-end-pts (- 1 id-2))) (cond ((equal type 'all) (list common-pt f-p1 f-p2)) ((equal type 'common-pt) common-pt) ((equal type 'p1) f-p1) (t f-p2))))) ;;; (defun get-head-pt (arrow-head) ) ;;; (defun get-leave-pt (arrow) (let ((pt (pt (arrow-head arrow)))) (if (> (distance pt (left-endpoint (arrow-back arrow))) (distance pt (right-endpoint (arrow-back arrow)))) (left-endpoint (arrow-back arrow)) (right-endpoint (arrow-back arrow))) ))
Back to automata example |
Back to Index page |