[climacs-devel] cl-syntax symbol cleverness
Andreas Fuchs
asf at boinkor.net
Mon May 9 12:37:05 UTC 2005
Hi,
I just hacked on cl-syntax.lisp a bit. now it can correctly render the
first screenful of cl-syntax.lisp, and a few other files that I tried
it on. (-:
Changes:
* Add support for qualified symbols (via : and ::)
* Add support for keyword symbols
* Add support for lambda list keywords
* Fix the lexer's neutralcharp a bit to support the above (#\-,
#\+, and #\. should all be read as part of the symbol name).
Index: cl-syntax.lisp
===================================================================
RCS file: /project/climacs/cvsroot/climacs/cl-syntax.lisp,v
retrieving revision 1.12
diff -u -r1.12 cl-syntax.lisp
--- cl-syntax.lisp 29 Apr 2005 20:10:32 -0000 1.12
+++ cl-syntax.lisp 9 May 2005 12:36:28 -0000
@@ -53,6 +53,8 @@
(defclass paren-close (cl-lexeme) ())
(defclass comma (cl-lexeme) ())
(defclass quote-symbol (cl-lexeme) ())
+(defclass colon (cl-lexeme) ())
+(defclass ampersand (cl-lexeme) ())
(defclass double-quote (cl-lexeme) ())
(defclass hex (cl-lexeme) ())
(defclass pipe (cl-lexeme) ())
@@ -78,6 +80,8 @@
(#\, (fo) (make-instance 'comma))
(#\" (fo) (make-instance 'double-quote))
(#\' (fo) (make-instance 'quote-symbol))
+ (#\: (fo) (make-instance 'colon))
+ (#\& (fo) (make-instance 'ampersand))
(#\# (fo) (make-instance 'hex))
(#\| (fo) (make-instance 'pipe))
(#\` (fo) (make-instance 'backquote))
@@ -115,7 +119,7 @@
(defun neutralcharp (var)
(and (characterp var)
(not (member var '(#\( #\) #\, #\" #\' #\# #\| #\` #\@ #\; #\\
- #\/ #\. #\+ #\- #\Newline #\Space #\Tab)
+ #\: #\/ #\Newline #\Space #\Tab)
:test #'char=))))
@@ -783,6 +787,98 @@
(display-parse-tree start syntax pane))
(display-parse-tree item syntax pane)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Qualified symbols
+
+;; XXX: There's a bit of duplication going on here. I'm not sure if
+;; that could be reduced by clever inheritance. But then, it's only
+;; OAOOM.
+
+(defclass qualified-symbol (cl-entry)
+ ((package-name :initarg :package-name)
+ (colon1 :initarg :colon1)
+ (colon2 :initarg :colon2)
+ (symbol-name :initarg :symbol-name)))
+
+(defclass qualified-exported-symbol (cl-entry)
+ ((package-name :initarg :package-name)
+ (colon :initarg :colon)
+ (symbol-name :initarg :symbol-name)))
+
+(add-cl-rule (qualified-symbol -> ((package-name default-item)
+ (colon1 colon (= (end-offset package-name)
+ (start-offset colon1)))
+ (colon2 colon (= (end-offset colon1)
+ (start-offset colon2)))
+ (symbol-name default-item (= (end-offset colon2)
+ (start-offset symbol-name))))
+ :package-name package-name
+ :colon1 colon1
+ :colon2 colon2
+ :symbol-name symbol-name))
+
+(add-cl-rule (qualified-exported-symbol -> ((package-name default-item)
+ (colon colon (= (end-offset package-name)
+ (start-offset colon)))
+ (symbol-name default-item (= (end-offset colon)
+ (start-offset symbol-name))))
+ :package-name package-name
+ :colon colon
+ :symbol-name symbol-name))
+
+(defmethod display-parse-tree ((entity qualified-symbol) (syntax cl-syntax) pane)
+ (with-slots (package-name colon1 colon2 symbol-name) entity
+ (with-drawing-options (pane :text-style (make-text-style :fix :bold nil) :ink +purple+)
+ (display-parse-tree package-name syntax pane)
+ (display-parse-tree colon1 syntax pane)
+ (display-parse-tree colon2 syntax pane))
+ (display-parse-tree symbol-name syntax pane)))
+
+(defmethod display-parse-tree ((entity qualified-exported-symbol) (syntax cl-syntax) pane)
+ (with-slots (package-name colon symbol-name) entity
+ (display-parse-tree package-name syntax pane)
+ (with-drawing-options (pane :ink (make-rgb-color 0.0 0.0 1.0))
+ (display-parse-tree colon syntax pane))
+ (display-parse-tree symbol-name syntax pane)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Keyword symbols
+
+(defclass keyword-symbol (cl-entry)
+ ((start :initarg :start)
+ (item :initarg :item)))
+
+(add-cl-rule (keyword-symbol -> ((start colon)
+ (item identifier))
+ :start start :item item))
+
+(defmethod display-parse-tree ((entity keyword-symbol) (syntax cl-syntax) pane)
+ (with-slots (start item) entity
+ (with-text-face (pane :bold)
+ (display-parse-tree start syntax pane)
+ (display-parse-tree item syntax pane))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Lambda list Keywords
+
+(defclass lambda-list-keyword (cl-entry)
+ ((start :initarg :start)
+ (item :initarg :item)))
+
+(add-cl-rule (lambda-list-keyword -> ((start ampersand)
+ (item default-item (and
+ (= (end-offset start)
+ (start-offset item))
+ (member item
+ '( ;; ordinary LLs
+ "optional" "rest" "key" "aux" "allow-other-keys"
+ ;; macro LLs
+ "body" "whole" "environment")
+ :test #'default-item-is))))
+ :start start :item item))
+
+(defmethod display-parse-tree ((entity lambda-list-keyword) (syntax cl-syntax) pane)
+ (with-slots (start item) entity
+ (with-drawing-options (pane :ink +blue+)
+ (display-parse-tree start syntax pane)
+ (display-parse-tree item syntax pane))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Backquoted expr
@@ -850,6 +946,10 @@
(add-cl-rule (cl-terminal -> (balanced-comment) :item balanced-comment))
(add-cl-rule (cl-terminal -> (cl-string) :item cl-string))
(add-cl-rule (cl-terminal -> (quoted-expr) :item quoted-expr))
+(add-cl-rule (cl-terminal -> (keyword-symbol) :item keyword-symbol))
+(add-cl-rule (cl-terminal -> (lambda-list-keyword) :item lambda-list-keyword))
+(add-cl-rule (cl-terminal -> (qualified-symbol) :item qualified-symbol))
+(add-cl-rule (cl-terminal -> (qualified-exported-symbol) :item qualified-exported-symbol))
(add-cl-rule (cl-terminal -> (backquoted-expr) :item backquoted-expr))
(add-cl-rule (cl-terminal -> (char-item) :item char-item))
(add-cl-rule (cl-terminal -> (unquoted-expr) :item unquoted-expr))
@@ -925,19 +1025,21 @@
(defun handle-whitespace (pane buffer start end)
(let ((space-width (space-width pane))
(tab-width (tab-width pane)))
- (loop while (< start end)
- do (ecase (buffer-object buffer start)
- (#\Newline (terpri pane)
- (setf (aref *cursor-positions* (incf *current-line*))
- (multiple-value-bind (x y) (stream-cursor-position pane)
- (declare (ignore x))
- y)))
- (#\Space (stream-increment-cursor-position
- pane space-width 0))
- (#\Tab (let ((x (stream-cursor-position pane)))
- (stream-increment-cursor-position
- pane (- tab-width (mod x tab-width)) 0))))
- (incf start))))
+ (loop while (and (< start end)
+ (whitespacep (buffer-object buffer start)))
+ do (ecase (buffer-object buffer start)
+ (#\Newline (terpri pane)
+ (setf (aref *cursor-positions* (incf *current-line*))
+ (multiple-value-bind (x y) (stream-cursor-position pane)
+ (declare (ignore x))
+ y)))
+ (#\Space (stream-increment-cursor-position
+ pane space-width 0))
+ (#\Tab (let ((x (stream-cursor-position pane)))
+ (stream-increment-cursor-position
+ pane (- tab-width (mod x tab-width)) 0)))
+ (#\Page nil))
+ (incf start))))
(defmethod display-parse-tree :around ((entity cl-parse-tree) syntax pane)
(with-slots (top bot) pane
That was fun. (-:
Cheers,
--
Andreas Fuchs, <asf at boinkor.net>, asf at jabber.at, antifuchs
More information about the climacs-devel
mailing list