Skip to content

Commit 65506d6

Browse files
committed
add docs for syntax-color/paren-tree
and also avoid allocating the shortcut paren structs for each object
1 parent 3669bc3 commit 65506d6

File tree

3 files changed

+133
-31
lines changed

3 files changed

+133
-31
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#lang scribble/manual
2+
@(require (for-label racket))
3+
4+
@title{Parenthesis Matching}
5+
6+
@defmodule[syntax-color/paren-tree]
7+
8+
Parenthesis matching code built on top of @racket[token-tree%].
9+
10+
@defclass[
11+
paren-tree% object% ()
12+
13+
@defconstructor/auto-super[([matches (listof (list/c symbol? symbol?))])]{
14+
Creates a @racket[paren-tree%] object that treats @racket[(map car matches)]
15+
as open parens and @racket[(map cadr matches)] as close parens,
16+
where each element of @racket[matches] is a matching pair of parens.
17+
18+
Each paren tree tracks a sequence of tokens (added with @method[paren-tree% add-token])
19+
and can respond to queries about the location of a paren that matches a paren
20+
at some specific location via @method[paren-tree% match-forward] and
21+
@method[paren-tree% match-backward]. The @racket[paren-tree%] also supports a notion of invisible
22+
parentheses that take up no space, where the opens exist only at the start of a token
23+
and the closes exist only at the end of a token.
24+
}
25+
26+
@defmethod[(add-token [type (or/c #f symbol?)]
27+
[length natural?]
28+
[#:invisible-opens invisible-opens natural? 0]
29+
[#:invisible-closes invisible-closes natural? 0])
30+
void?]{
31+
32+
Adds one token to the end of the current tree. If
33+
@racket[type] is a symbol, it is expected to be one of the
34+
symbols in @racket[matches]. If it is @racket[#f], then
35+
there are no visible parenthese in this token. The
36+
@racket[invisible-opens] and @racket[invsible-closes]
37+
indicate how many of each there are on this token (note that
38+
the invisible opens all exist at the start of the token and
39+
the invisible closes all exist at the end of the token).
40+
}
41+
42+
@defmethod[(match-forward [pos natural?]
43+
[#:invisible invisible (or/c #f natural? 'all) #f])
44+
(values (or/c natural? #f) (or/c natural? #f) (or/c natural? #f))]{
45+
Determines if there is a match for the paren at @racket[pos].
46+
47+
If @racket[invisible] is @racket[#f], then the invisible
48+
parens are ignored and the match considers only the
49+
parentheses that were explicit in the @racket[_token]
50+
argument to @method[paren-tree% add-token].
51+
52+
If @racket[invisible] is a natural number, then the
53+
matching starts outside of that many invisible parens. For
54+
example, if there are two invisible open parenthes on the
55+
token at @racket[pos], then passing @racket[1] as
56+
@racket[invisible] will find the match to only the inner
57+
invisible paren. If it is @racket[2], it will find the match
58+
to the outer invisible paren. If @racket[invisible] is
59+
@racket['all], then it is the same as passing the total
60+
number of invisible parens that are on the token at
61+
@racket[pos].
62+
63+
The first return is the starting position of the open paren
64+
The second return is the position of the matching close
65+
paren. If the third return is #f, then the first two returns
66+
represent a real match. If the third return is a number, it
67+
is the maximum position in the tree that was searched. If
68+
the third result indicates an error, the first two results
69+
give the starting and stopping positions for error
70+
highlighting. If all three are @racket[#f], then there was
71+
no tree to search, or the position did not immediately
72+
precede an open.
73+
}
74+
75+
@defmethod[(match-backward [pos natural?]
76+
[#:invisible invisible (or/c #f natural? 'all) #f])
77+
(values (or/c natural? #f) (or/c natural? #f) (or/c natural? #f))]{
78+
79+
Like @racket[paren-tree% match-forward], except matches
80+
backwards from the given paren.
81+
82+
The matching goes backwards from @racket[pos] to the
83+
matching paren; accordingly, the count of invisibles starts
84+
from the close parens and goes through the opens (unlike
85+
@racket[paren-tree% match-forward] which starts with the
86+
opens and goes through the closes).
87+
88+
The results are, however, identical to
89+
@racket[paren-tree% match-forward]. So, if the match is
90+
successful, the first result is the location of the open
91+
paren and the second is the close.
92+
}
93+
94+
@defmethod[(split-tree [pos natural?]) void?]{
95+
Splits the tree at @racket[pos], which must not be in the middle of a token.
96+
Everything following @racket[pos] is marked as invalid.
97+
}
98+
99+
@defmethod[(merge-tree [num-to-keep natural?]) void?]{
100+
Makes the @racket[num-to-keep] last positions that have been marked
101+
invalid valid again.
102+
}
103+
@defmethod[(truncate [pos natural?]) void?]{
104+
Removes the tokens after @racket[pos].
105+
}
106+
107+
@defmethod[(is-open-pos? [pos natural?]) (or/c #f symbol?)]{
108+
Returns @racket[#f] if the position does not have a visible paren. Returns the corresponding
109+
close if it does have an open.
110+
}
111+
@defmethod[(is-close-pos? [pos natural?]) (or/c #f symbol?)]{
112+
Returns @racket[#f] if the position does not have a visible paren. Returns the corresponding
113+
open if it does have a close.
114+
}
115+
116+
@defmethod[(get-invisible-count [pos natural?]) (values natural? natural?)]{
117+
Returns the number of invisible opens and invisible closes at @racket[pos].
118+
}
119+
]
120+
121+
122+

syntax-color-doc/syntax-color/syntax-color.scrbl

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,7 @@ structures and some helpful utilities for the @racket[color:text<%>]
2020
class of @racketmodname[framework].
2121

2222
@table-of-contents[]
23-
24-
@; ----------------------------------------------------------------------
25-
26-
@section{Parenthesis Matching}
27-
28-
@defmodule[syntax-color/paren-tree]
29-
30-
@defclass[paren-tree% object% ()]
31-
32-
Parenthesis matching code built on top of @racket[token-tree%].
23+
@include-section["paren-tree.scrbl"]
3324

3425
@; ----------------------------------------------------------------------
3526

syntax-color-lib/syntax-color/paren-tree.rkt

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@
2424
;; invisible-opens, invisible-closes : natural
2525
(define-struct paren (type length invisible-opens invisible-closes) #:transparent)
2626

27+
(define common-parens
28+
(list (make-paren '|(| 1 0 0)
29+
(make-paren '|)| 1 0 0)
30+
(make-paren '|]| 1 0 0)
31+
(make-paren '|[| 1 0 0)
32+
(make-paren '|}| 1 0 0)
33+
(make-paren '|{| 1 0 0)))
34+
(define false-zero-paren (make-paren #f 0 0 0))
35+
2736
(define paren-tree%
2837
(class object%
2938

@@ -67,15 +76,6 @@
6776
(define tree (new token-tree%))
6877
(define invalid-tree (new token-tree%))
6978

70-
(define common-parens
71-
(list (make-paren '|(| 1 0 0)
72-
(make-paren '|)| 1 0 0)
73-
(make-paren '|]| 1 0 0)
74-
(make-paren '|[| 1 0 0)
75-
(make-paren '|}| 1 0 0)
76-
(make-paren '|{| 1 0 0)))
77-
(define false-zero-paren (make-paren #f 0 0 0))
78-
7979
(define/private (build-paren type len invisible-opens invisible-closes)
8080
(cond
8181
[(or (not (zero? invisible-opens))
@@ -133,7 +133,7 @@
133133
(send good remove-root!))
134134
(insert-last! tree good)))
135135

136-
;; add-token: (->* ((or/c #f symbol invisible-paren?)
136+
;; add-token: (->* ((or/c #f symbol?)
137137
;; natural?)
138138
;; (#:invisible-opens (or/c #f natural?)
139139
;; #:invisible-closes (or/c #f natural?))
@@ -211,17 +211,6 @@
211211
d
212212
(is-close? (paren-type d)))))
213213

214-
;; match-forward: natural-number? -> (union #f natural-number)^3
215-
;; The first return is the starting position of the open-paren
216-
;; The second return is the position of the closing paren.
217-
;; If the third return is #f, then the first two returns
218-
;; represent a real match.
219-
;; If the third return is a number, it is the maximum position
220-
;; in the tree that was searched.
221-
;; If it indicates an error, the first two results give the
222-
;; starting and stoping positions for error highlighting.
223-
;; If all three return #f, then there was no tree to search, or
224-
;; the position did not immediately precede an open.
225214
(define/public (match-forward pos #:invisible [_invisible #f])
226215
(check-arguments 'match-forward pos _invisible)
227216
(send tree search! pos)

0 commit comments

Comments
 (0)