Update of /project/mcclim/cvsroot/mcclim/Drei
In directory clnet:/tmp/cvs-serv24081/Drei
Modified Files:
packages.lisp lisp-syntax.lisp lisp-syntax-swine.lisp
lisp-syntax-commands.lisp input-editor.lisp
Log Message:
Improved the Lisp syntax module, in particular, the `form-to-object'
function (previously `token-to-object') should now be as capable as a
proper Lisp reader. This has been used to implement some (in my
opinion) neat behavior for the expression accept method.
Also added some test cases for the function.
--- /project/mcclim/cvsroot/mcclim/Drei/packages.lisp 2006/12/09 23:55:37 1.9
+++ /project/mcclim/cvsroot/mcclim/Drei/packages.lisp 2006/12/10 19:28:49 1.10
@@ -432,8 +432,12 @@
(:use :clim-lisp :clim :clim-extensions :drei-buffer :drei-base
:drei-syntax :drei-fundamental-syntax :flexichain :drei
:drei-motion :drei-editing :esa-utils :esa :drei-core :esa-io)
- (:export #:lisp-string
- #:edit-definition)
+ (:export #:lisp-syntax
+ #:lisp-string
+ #:edit-definition
+ #:form
+ #:form-to-object
+ #:form-conversion-error)
(:shadow clim:form))
(defpackage :drei-commands
--- /project/mcclim/cvsroot/mcclim/Drei/lisp-syntax.lisp 2006/12/06 11:31:12 1.11
+++ /project/mcclim/cvsroot/mcclim/Drei/lisp-syntax.lisp 2006/12/10 19:28:49 1.12
@@ -243,7 +243,7 @@
(defclass lexer-state ()
()
- (:documentation "These states are used to determine how the lexer
+ (:documentation "These states are used to determine how the lexer
should behave."))
(defmacro define-lexer-state (name superclasses &body body)
@@ -257,23 +257,23 @@
(define-lexer-state lexer-toplevel-state ()
()
- (:documentation "In this state, the lexer assumes it can skip
+ (:documentation "In this state, the lexer assumes it can skip
whitespace and should recognize ordinary lexemes of the language
except for the right parenthesis"))
(define-lexer-state lexer-list-state (lexer-toplevel-state)
()
- (:documentation "In this state, the lexer assumes it can skip
+ (:documentation "In this state, the lexer assumes it can skip
whitespace and should recognize ordinary lexemes of the language"))
(define-lexer-state lexer-string-state ()
()
- (:documentation "In this state, the lexer is working inside a string
+ (:documentation "In this state, the lexer is working inside a string
delimited by double quote characters."))
(define-lexer-state lexer-line-comment-state ()
()
- (:documentation "In this state, the lexer is working inside a line
+ (:documentation "In this state, the lexer is working inside a line
comment (starting with a semicolon."))
(define-lexer-state lexer-long-comment-state ()
@@ -314,7 +314,7 @@
(defclass parser-state () ())
(defmacro define-parser-state (name superclasses &body body)
- `(progn
+ `(progn
(defclass ,name ,superclasses
,@body)
(defvar ,name (make-instance ',name))))
@@ -336,12 +336,12 @@
(end (find-if-not #'null children :key #'end-offset :from-end t)))
(when start
(setf start-mark (slot-value start 'start-mark)
- size (- (end-offset end) (start-offset start)))))))
+ size (- (end-offset end) (start-offset start)))))))
;;; until here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defclass lisp-nonterminal (nonterminal) ())
+(defclass lisp-nonterminal (nonterminal) ())
(defclass form (lisp-nonterminal) ())
(defclass complete-form-mixin () ())
(defclass incomplete-form-mixin () ())
@@ -411,7 +411,7 @@
(setf (offset scan) start-offset)
(setf start-mark scan
size new-size))
- lexeme)))
+ lexeme)))
(defmethod lex ((syntax lisp-syntax) (state lexer-toplevel-state) scan)
(macrolet ((fo () `(forward-object scan)))
@@ -439,7 +439,7 @@
(#\# (fo)
(cond ((end-of-buffer-p scan)
(make-instance 'incomplete-lexeme))
- (t
+ (t
(let ((prefix 0))
(loop until (end-of-buffer-p scan)
while (digit-char-p (object-after scan))
@@ -450,7 +450,7 @@
(if (end-of-buffer-p scan)
(make-instance 'incomplete-lexeme)
(case (object-after scan)
- ((#\Backspace #\Tab #\Newline #\Linefeed
+ ((#\Backspace #\Tab #\Newline #\Linefeed
#\Page #\Return #\Space #\))
(fo)
(make-instance 'error-lexeme))
@@ -487,6 +487,9 @@
((#\O #\o) 8)
((#\X #\x) 16))))
(fo)
+ (when (char= (object-after scan)
+ #\-)
+ (fo))
(loop until (end-of-buffer-p scan)
while (digit-char-p (object-after scan) radix)
do (fo)))
@@ -666,31 +669,33 @@
(defmethod lex ((syntax lisp-syntax) (state lexer-escaped-token-state) scan)
(let ((bars-seen 0))
(macrolet ((fo () `(forward-object scan)))
- (tagbody
- start
- (when (end-of-buffer-p scan)
- (return-from lex (make-instance 'text-lexeme)))
- (when (eql (object-after scan) #\\)
- (fo)
- (when (end-of-buffer-p scan)
- (return-from lex (make-instance 'incomplete-lexeme)))
- (fo)
- (go start))
- (when (eql (object-after scan) #\|)
- (incf bars-seen)
- (fo)
- (go start))
- (if (evenp bars-seen)
- (unless (whitespacep syntax (object-after scan))
- (fo)
- (go start))
- (when (constituentp (object-after scan))
- (fo)
- (go start)))
- (return-from lex
- (if (oddp bars-seen)
- (make-instance 'multiple-escape-end-lexeme)
- (make-instance 'text-lexeme)))))))
+ (flet ((end ()
+ (return-from lex
+ (if (oddp bars-seen)
+ (make-instance 'multiple-escape-end-lexeme)
+ (make-instance 'text-lexeme)))))
+ (tagbody
+ start
+ (when (end-of-buffer-p scan)
+ (end))
+ (when (eql (object-after scan) #\\)
+ (fo)
+ (when (end-of-buffer-p scan)
+ (return-from lex (make-instance 'incomplete-lexeme)))
+ (fo)
+ (go start))
+ (when (eql (object-after scan) #\|)
+ (incf bars-seen)
+ (fo)
+ (go start))
+ (if (evenp bars-seen)
+ (unless (whitespacep syntax (object-after scan))
+ (fo)
+ (go start))
+ (when (constituentp (object-after scan))
+ (fo)
+ (go start)))
+ (end))))))
(defmethod lex ((syntax lisp-syntax) (state lexer-error-state) scan)
(macrolet ((fo () `(forward-object scan)))
@@ -703,7 +708,7 @@
;;; nonterminals
(defclass line-comment (lisp-nonterminal) ())
-(defclass long-comment (lisp-nonterminal) ())
+(defclass long-comment (lisp-nonterminal) ())
(defclass error-symbol (lisp-nonterminal) ())
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -772,13 +777,13 @@
(with-slots (start-mark size) result
(setf start-mark (clone-mark scan :right)
size 0))))
- result))
+ result))
(define-parser-state error-state (lexer-error-state parser-state) ())
(define-parser-state error-reduce-state (lexer-toplevel-state parser-state) ())
(define-lisp-action (error-reduce-state (eql nil))
- (throw 'done nil))
+ (throw 'done nil))
;;; the default action for any lexeme is shift
(define-lisp-action (t lisp-lexeme)
@@ -791,14 +796,14 @@
;;; the default new state is the error state
(define-new-lisp-state (t parser-symbol) error-state)
-;;; the new state when an error-state
+;;; the new state when an error-state
(define-new-lisp-state (t error-symbol) error-reduce-state)
-;;;;;;;;;;;;;;;; Top-level
+;;;;;;;;;;;;;;;; Top-level
#| rules
- form* ->
+ form* ->
form* -> form* form
|#
@@ -818,7 +823,7 @@
(reduce-all form*))
(define-new-lisp-state (|initial-state | form*) |form* | )
-
+
(define-lisp-action (|form* | (eql nil))
(throw 'done nil))
@@ -927,7 +932,7 @@
(define-lisp-action (|" word* " | t)
(reduce-until-type complete-string-form string-start-lexeme))
-;;; reduce at the end of the buffer
+;;; reduce at the end of the buffer
(define-lisp-action (|" word* | (eql nil))
(reduce-until-type incomplete-string-form string-start-lexeme))
@@ -1125,7 +1130,7 @@
(define-new-lisp-state (|#- form | form) |#- form form |)
(define-new-lisp-state (|#- | comment) |#- |)
(define-new-lisp-state (|#- form | comment) |#- form |)
-
+
(define-lisp-action (|#+ form form | t)
(reduce-until-type reader-conditional-positive-form reader-conditional-positive-lexeme))
@@ -1292,7 +1297,7 @@
(t (loop with new-tree = (cadr (member tree siblings :test #'eq))
until (null (children new-tree))
do (setf new-tree (car (children new-tree)))
- finally (return new-tree)))))))
+ finally (return new-tree)))))))
(defun find-last-valid-lexeme (parse-tree offset)
(cond ((or (null parse-tree) (null (start-offset parse-tree))) nil)
@@ -1302,7 +1307,7 @@
(find-last-valid-lexeme (car (last (children parse-tree))) offset))
((>= (end-offset parse-tree) offset)
(find-last-valid-lexeme (preceding-parse-tree parse-tree) offset))
- (t parse-tree)))
+ (t parse-tree)))
(defun find-first-potentially-valid-lexeme (parse-trees offset)
(cond ((null parse-trees) nil)
@@ -1322,7 +1327,7 @@
(and (eq (class-of tree1) (class-of tree2))
(eq (parser-state tree1) (parser-state tree2))
(= (end-offset tree1) (end-offset tree2))))
-
+
(defmethod print-object ((mark mark) stream)
(print-unreadable-object (mark stream :type t :identity t)
(format stream "~s" (offset mark))))
@@ -1350,7 +1355,7 @@
(>= (start-offset potentially-valid-trees)
(end-offset stack-top)))
do (setf potentially-valid-trees
- (next-tree potentially-valid-trees)))))))
+ (next-tree potentially-valid-trees)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
@@ -1435,7 +1440,7 @@
(typep x 'complete-list-form))
(let ((candidate (first-form (children x))))
(and (form-token-p candidate)
- (eq (token-to-object syntax candidate
+ (eq (form-to-object syntax candidate
:no-error t)
'cl:in-package)))))))
(with-slots (stack-top) syntax
@@ -1457,12 +1462,12 @@
(when (form-list-p x)
(let ((candidate (first-form (children x))))
(and (form-token-p candidate)
- (eq (token-to-object syntax candidate
+ (eq (form-to-object syntax candidate
:no-error t)
'cl:in-package)))))
(extract (x)
(let ((designator (second-form (children x))))
- (token-to-object syntax designator
+ (form-to-object syntax designator
:no-error t))))
(with-slots (stack-top) syntax
(loop for child in (children stack-top)
@@ -1672,18 +1677,18 @@
"Return the text of the definition at mark."
(let ((definition (definition-at-mark mark syntax)))
(buffer-substring (buffer mark)
- (start-offset definition)
+ (start-offset definition)
(end-offset definition))))
-
+
(defun text-of-expression-at-mark (mark-or-offset syntax)
"Return the text of the expression at `mark-or-offset'."
(let ((expression (expression-at-mark mark-or-offset syntax)))
- (token-string syntax expression)))
+ (form-string syntax expression)))
(defun symbol-name-at-mark (mark-or-offset syntax)
"Return the text of the symbol at `mark-or-offset'."
(let ((token (symbol-at-mark mark-or-offset syntax)))
- (when token (token-string syntax token))))
+ (when token (form-string syntax token))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
@@ -1711,6 +1716,7 @@
(define-form-predicate form-quoted-p (quote-form backquote-form))
(define-form-predicate form-comma-p (comma-form))
(define-form-predicate form-comma-at-p (comma-at-form))
+(define-form-predicate form-comma-dot-p (comma-dot-form))
(define-form-predicate comment-p (comment))
@@ -1805,16 +1811,16 @@
(defmethod display-parse-tree :around (parse-symbol stream (drei drei)
(syntax lisp-syntax))
(with-slots (top bot) drei
- (when (and (start-offset parse-symbol)
+ (when (and (start-offset parse-symbol)
(mark< (start-offset parse-symbol) bot)
(mark> (end-offset parse-symbol) top))
- (call-next-method))))
+ (call-next-method))))
(defmethod display-parse-tree (parse-symbol stream (drei drei)
(syntax lisp-syntax))
(with-slots (top bot) drei
(loop for child in (children parse-symbol)
- when (and (start-offset child)
+ when (and (start-offset child)
(mark> (end-offset child) top))
do (if (mark< (start-offset child) bot)
(display-parse-tree child stream drei syntax)
@@ -1850,9 +1856,9 @@
(defmethod display-parse-tree ((parse-symbol token-mixin) stream (drei drei) (syntax lisp-syntax))
(if (> (the fixnum (end-offset parse-symbol)) (the fixnum (start-offset parse-symbol)))
- (let ((string (token-string syntax parse-symbol)))
+ (let ((string (form-string syntax parse-symbol)))
(multiple-value-bind (symbol status)
- (token-to-object syntax parse-symbol :no-error t)
+ (form-to-object syntax parse-symbol :no-error t)
(with-output-as-presentation
(stream (if status symbol string)
(if status 'symbol 'unknown-symbol)
@@ -1881,7 +1887,7 @@
:id-test #'equal
:cache-value parser-symbol
:cache-test #'eql)
- (let ((object (token-to-object syntax parser-symbol)))
+ (let ((object (form-to-object syntax parser-symbol)))
(present object (presentation-type-of object) :stream stream))))
(defmethod display-parse-tree ((parser-symbol lisp-lexeme) stream (drei drei)
@@ -1900,15 +1906,15 @@
(with-slots (ink face) parser-symbol
(setf ink (medium-ink (sheet-medium stream))
face (text-style-face (medium-text-style (sheet-medium stream))))
- (let ((string (token-string syntax parser-symbol)))
+ (let ((string (form-string syntax parser-symbol)))
(present string 'string :stream stream))))))
-
+
(defmethod display-parse-tree :before ((parse-symbol lisp-lexeme) stream (drei drei)
(syntax lisp-syntax))
(handle-whitespace stream (buffer drei) *white-space-start* (start-offset parse-symbol))
(setf *white-space-start* (end-offset parse-symbol)))
-(define-presentation-type lisp-string ()
+(define-presentation-type lisp-string ()
:description "lisp string")
(defmethod display-parse-tree ((parse-symbol complete-string-form) stream (drei drei) (syntax lisp-syntax))
@@ -1980,7 +1986,7 @@
"The KEYWORD package.")
(defmethod eval-feature-conditional ((conditional token-mixin) (syntax lisp-syntax))
- (let* ((string (token-string syntax conditional))
+ (let* ((string (form-string syntax conditional))
(symbol (parse-symbol string :package +keyword-package+)))
(member symbol *features*)))
@@ -1996,7 +2002,7 @@
(remove-if
#'comment-p
children))))
- (type-string (token-string syntax type))
+ (type-string (form-string syntax type))
(type-symbol (parse-symbol type-string :package +keyword-package+)))
(case type-symbol
(:and (funcall #'every #'eval-fc conditionals))
@@ -2004,7 +2010,7 @@
(:not (when conditionals
[820 lines skipped]
--- /project/mcclim/cvsroot/mcclim/Drei/lisp-syntax-swine.lisp 2006/12/04 20:07:53 1.3
+++ /project/mcclim/cvsroot/mcclim/Drei/lisp-syntax-swine.lisp 2006/12/10 19:28:49 1.4
@@ -417,7 +417,7 @@
indexing-start-arg
operator-form))
(preceding-arg-obj (when preceding-arg-token
- (token-to-object syntax preceding-arg-token
+ (form-to-object syntax preceding-arg-token
:no-error t))))
(values preceding-arg-obj argument-indices))))
@@ -461,7 +461,7 @@
argument\" is defined as an argument that would be directly bound
to a symbol when evaluating the operators body, or as an argument
that would be a direct component of a &body or &rest argument."
- (let ((operator (token-to-object syntax operator-form)))
+ (let ((operator (form-to-object syntax operator-form)))
(and
;; An operator is not an argument to itself.
(not (eq arg-form
@@ -790,11 +790,11 @@
;; If we cannot find a form, there's no point in looking
;; up any of this stuff.
(,operator-sym (when (and ,form-sym (form-list-p ,form-sym))
- (token-to-object ,syntax (form-operator ,syntax ,form-sym))))
+ (form-to-object ,syntax (form-operator ,syntax ,form-sym))))
(,operands-sym (when (and ,form-sym (form-list-p ,form-sym))
(mapcar #'(lambda (operand)
(when operand
- (token-to-object ,syntax operand)))
+ (form-to-object ,syntax operand)))
(form-operands ,syntax ,form-sym)))))
(declare (ignorable ,form-sym ,operator-sym ,operands-sym))
(multiple-value-bind (,preceding-operand-sym ,operand-indices-sym)
@@ -1022,7 +1022,7 @@
(start-offset token)
(offset mark)))
(if useful-token
- (token-string syntax token)
+ (form-string syntax token)
""))
(if completions
(if (= (length completions) 1)
--- /project/mcclim/cvsroot/mcclim/Drei/lisp-syntax-commands.lisp 2006/12/04 20:07:53 1.3
+++ /project/mcclim/cvsroot/mcclim/Drei/lisp-syntax-commands.lisp 2006/12/10 19:28:49 1.4
@@ -98,7 +98,7 @@
(mark (point pane))
(token (this-form mark syntax)))
(if (and token (form-token-p token))
- (com-lookup-arglist (token-to-object syntax token))
+ (com-lookup-arglist (form-to-object syntax token))
(display-message "Could not find symbol at point."))))
(define-command (com-lookup-arglist :name t :command-table lisp-table)
@@ -189,7 +189,7 @@
(with-syntax-package (*current-syntax* *current-point*)
(let ((*read-base* (base *current-syntax*)))
(drei-commands::com-eval-expression
- (token-to-object *current-syntax* token :read t)
+ (form-to-object *current-syntax* token :read t)
insertp)))
(display-message "Nothing to evaluate."))))
--- /project/mcclim/cvsroot/mcclim/Drei/input-editor.lisp 2006/12/07 14:34:14 1.12
+++ /project/mcclim/cvsroot/mcclim/Drei/input-editor.lisp 2006/12/10 19:28:49 1.13
@@ -841,11 +841,19 @@
do (with-activation-gestures (nil :override t)
(stream-process-gesture stream gesture nil))
finally (unread-gesture gesture :stream stream)
- (let* ((object (drei-lisp-syntax::token-to-object syntax form
- :read t
- :package *package*))
- (ptype (presentation-type-of object)))
- (return-from control-loop
- (values object
- (if (presentation-subtypep ptype 'expression)
- ptype 'expression))))))))
+ (let* ((object (handler-case
+ (drei-lisp-syntax:form-to-object syntax form
+ :read t
+ :package *package*)
+ (drei-lisp-syntax:form-conversion-error (e)
+ ;; Move point to the problematic form
+ ;; and signal a rescan.
+ (setf (activation-gesture stream) nil)
+ (handle-drei-condition drei e)
+ (display-drei drei)
+ (immediate-rescan stream))))
+ (ptype (presentation-type-of object)))
+ (return-from control-loop
+ (values object
+ (if (presentation-subtypep ptype 'expression)
+ ptype 'expression))))))))