PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/commands.sc

https://bitbucket.org/bunny351/ezd
Scala | 194 lines | 171 code | 23 blank | 0 comment | 5 complexity | 5ace348f50db3982ea7b8bca3336b465 MD5 | raw file
  1. ;;; ezd - easy drawing for X11 displays.
  2. ;;;
  3. ;;; Command parsing and definition.
  4. ;* Copyright 1990-1993 Digital Equipment Corporation
  5. ;* All Rights Reserved
  6. ;*
  7. ;* Permission to use, copy, and modify this software and its documentation is
  8. ;* hereby granted only under the following terms and conditions. Both the
  9. ;* above copyright notice and this permission notice must appear in all copies
  10. ;* of the software, derivative works or modified versions, and any portions
  11. ;* thereof, and both notices must appear in supporting documentation.
  12. ;*
  13. ;* Users of this software agree to the terms and conditions set forth herein,
  14. ;* and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
  15. ;* right and license under any changes, enhancements or extensions made to the
  16. ;* core functions of the software, including but not limited to those affording
  17. ;* compatibility with other hardware or software environments, but excluding
  18. ;* applications which incorporate this software. Users further agree to use
  19. ;* their best efforts to return to Digital any such changes, enhancements or
  20. ;* extensions that they make and inform Digital of noteworthy uses of this
  21. ;* software. Correspondence should be provided to Digital at:
  22. ;*
  23. ;* Director of Licensing
  24. ;* Western Research Laboratory
  25. ;* Digital Equipment Corporation
  26. ;* 250 University Avenue
  27. ;* Palo Alto, California 94301
  28. ;*
  29. ;* This software may be distributed (but not offered for sale or transferred
  30. ;* for compensation) to third parties, provided such third parties agree to
  31. ;* abide by the terms and conditions of this notice.
  32. ;*
  33. ;* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  34. ;* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  35. ;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  36. ;* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  37. ;* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  38. ;* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  39. ;* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  40. ;* SOFTWARE.
  41. (module commands)
  42. ;;; COMMAND PARSING.
  43. ;;; Helper functions for command argument parsing.
  44. (define (ACONS x y) (if (eq? #f y) #f (cons x y)))
  45. (define (MATCHED-ARGS x y)
  46. (define (match-list x y)
  47. (if (null? x)
  48. '()
  49. (cons (if (pair? y) (car y) '())
  50. (match-list (cdr x) (if (pair? y) (cdr y) '())))))
  51. (if (= (length x) 1) (car y) (match-list x y)))
  52. (define (REST-ARGS x y)
  53. (if (or (null? x) (null? y)) y (rest-args (cdr x) (cdr y))))
  54. ;;; Command parsing is handled by the following procedure. Its arguments are
  55. ;;; a template describing the command arguments and the actual command
  56. ;;; arguments. It returns either a list of parsed arguments or #F. The
  57. ;;; template is a list composed of any of the following elements that are
  58. ;;; matched as noted:
  59. ;;;
  60. ;;; MATCHES WHEN TRUE:
  61. ;;;
  62. ;;; (OPTIONAL <template>) #t
  63. ;;;
  64. ;;; (REPEAT <template>) #t
  65. ;;;
  66. ;;; (OR <template>...) #t
  67. ;;;
  68. ;;; *REST* #t
  69. ;;;
  70. ;;; <a procedure> (<a procedure> argument)
  71. ;;;
  72. ;;; <any other obj> (EQUAL? <any other obj> argument)
  73. ;;;
  74. ;;; When the command can be parsed, the result is a list of arguments
  75. ;;; generated by the matches to the template. Template items contribute to
  76. ;;; the result as follows:
  77. ;;; RETURNS ON A MATCH:
  78. ;;;
  79. ;;; (OPTIONAL <template>) either #f when the <template> could not be
  80. ;;; matched, or the item it matched (<template>
  81. ;;; consists of one item), or a list of items
  82. ;;; matched.
  83. ;;;
  84. ;;; (REPEAT <template>) a list of items matched (<template> consists
  85. ;;; of one item), or a list of lists of items
  86. ;;; matched.
  87. ;;;
  88. ;;; (OR <template>...) the result of the first <template> that matches
  89. ;;; or #f when no <template> matched.
  90. ;;;
  91. ;;; *REST* a list of the remaining arguments.
  92. ;;;
  93. ;;; <a procedure> the argument.
  94. ;;;
  95. ;;; <any other obj> no value is returned.
  96. (define (ARG-PARSE template args)
  97. (if template
  98. (let ((x (car template)))
  99. (cond ((and (pair? x) (eq? (car x) 'optional))
  100. (let ((match (arg-parse (append (cdr x) (cdr template))
  101. args)))
  102. (if (not (eq? match #f))
  103. (acons (matched-args (cdr x) args)
  104. (arg-parse (cdr template)
  105. (rest-args (cdr x) args)))
  106. (acons #f (arg-parse (cdr template) args)))))
  107. ((and (pair? x) (eq? (car x) 'repeat))
  108. (let loop ((found '()) (args args))
  109. (let ((match (arg-parse
  110. (append (cdr x) '(*rest*)) args)))
  111. (if (not (eq? match #f))
  112. (loop (append found
  113. (list (matched-args (cdr x)
  114. match)))
  115. (rest-args (cdr x) match))
  116. (acons found
  117. (arg-parse (cdr template) args))))))
  118. ((and (pair? x) (eq? (car x) 'or))
  119. (let loop ((tl (cdr x)))
  120. (if (null? tl)
  121. #f
  122. (let ((match (arg-parse
  123. (append (car tl) '(*rest*))
  124. args)))
  125. (if (not (eq? match #f))
  126. (acons (matched-args (car tl) match)
  127. (arg-parse (cdr template)
  128. (rest-args (car tl) match)))
  129. (loop (cdr tl)))))))
  130. ((eq? x '*rest*) args)
  131. ((null? args) #f)
  132. ((procedure? x)
  133. (let ((arg (car args)))
  134. (if (x arg)
  135. (acons arg (arg-parse (cdr template) (cdr args)))
  136. #f)))
  137. ((equal? x (car args))
  138. (arg-parse (cdr template) (cdr args)))
  139. (else #f)))
  140. (if (null? args) '() #f)))
  141. ;;; Generally useful predicates for command decoding.
  142. (define (NON-NEGATIVE? x) (and (number? x) (>= x 0)))
  143. (define (NON-ZERO? x) (and (number? x) (not (= x 0))))
  144. (define (POSITIVE-NUMBER? x) (and (number? x) (> x 0)))
  145. (define (ANY? x) #t)
  146. (define (DASH? x) (eq? x 'dash))
  147. ;;; ezd commands are defined by calls to the following procedure. The caller
  148. ;;; provides the command name (a symbol), the argument parsing template, a
  149. ;;; string describing the correct form of the command, and the action procedure
  150. ;;; that is to be called when the command is successfully parsed.
  151. (define EZD-COMMANDS '())
  152. (define (DEFINE-EZD-COMMAND template description action)
  153. (let* ((command (car template))
  154. (x (assoc command ezd-commands)))
  155. (if x (set! ezd-commands (remove x ezd-commands)))
  156. (set! ezd-commands
  157. (cons (list command template description action) ezd-commands))
  158. command))
  159. ;;; Errors in ezd commands are reported by calling the procedure EZD-ERROR.
  160. ;;; This will result in either the message being logged to the stderr-port, or
  161. ;;; the Scheme error handler error being called.
  162. (define IN-READ-EVAL-DRAW #f)
  163. (define (EZD-ERROR id form . args)
  164. (if (not in-read-eval-draw) (apply error id form args))
  165. (apply format stderr-port form args)
  166. (newline stderr-port)
  167. #f)
  168. ;;; Module initialization procedure.
  169. (define (COMMANDS-MODULE-INIT)
  170. (set! in-read-eval-draw #f)
  171. #t)