Syntax-Browser: Graphical Syntax Display
_Syntax-Browser: Graphical Syntax Display_
By Ryan Culpepper (ryanc at ccs dot neu dot edu)
Keywords: _syntax_, _syntax-browser_, _hygiene_,
_referential transparency_, _lexical context_
There are two common ways to view syntax objects. One is to call
syntax-object->datum and inspect the underlying S-expression with all
additional information removed. The other is to use DrScheme's
built-in syntax viewer, which shows additional properties of the
syntax object. However, neither solution shows the different lexical
contexts of subterms and identifiers within the syntax object. This
library graphically displays this information, critical for debugging
There is a single public module in the syntax-browser collection.
Use the following require form to use the library:
> (require (planet "syntax-browser.ss" ("ryanc" "syntax-browser.plt" 1)))
This provides two procedures:
> (browse-syntax syntax) -> void
Creates a frame with the given syntax object shown. More information
on using the GUI is available below.
> (browse-syntaxes list-of-syntax) -> void
Like browse-syntax, but shows multiple syntax objects in the same
frame. The primary coloring partition is shared between the two,
showing the relationships between subterms in different syntax
> (make-syntax-browser) -> (is-a?/c syntax-controller<%>)
Creates a frame with an empty syntax browser control. The syntax
browser can be scripted using the methods of the syntax-browser<%>
> (syntax-snip syntax) -> (is-a?/c snip%)
> (syntaxes-snip list-of-syntax) -> (is-a?/c snip%)
Like 'browse-syntax' and 'browse-syntaxes' above, but creates a snip
that can be displayed in an editor. In particular, evaluating
(syntax-snip (expand #'(lambda (x) x)))
in DrScheme's interactions window will insert a syntax browser into
the interactions window.
> syntax-browser<%> : interface
Contains the following methods:
> add-syntax : syntax [(list-of syntaxes) string] -> void
Adds the given syntax to the browser.
If a list of syntax objects and a string are provided, then
the display highlights every subterm of the first syntax object
that is a member (eq?) of the list, using the color named by
the string argument.
> add-separator : -> void
Adds a horizontal line to the syntax browser.
The User Interface
The syntax-browser contains a frame with a few controls and an editor
canvas for displaying syntax objects.
The *primary partitioning* always assigns two syntax subterms the same
color if they have the same marks. In the absence of unhygienic
macros, this means that subterms with the same foreground color were
either present in the original pre-expansion syntax or generated by
the same macro transcription step.
Note that syntax colored in black always corresponds to unmarked
syntax. Such syntax may be original, or it may be produced by the
expansion of a nonhygienic macro.
The drop-down list allows the user to select a *secondary
partitionin*, applied only to identifiers. When the user clicks on a
syntax subterm, that term is highlighted in grey, and all terms in the
same equivalence class as the selected term are highlighted in blue.
Clicking on a syntax object *selects* it. The clicked subterm is
highlighted in grey, and every identical (eq?) subterm in any syntax
object displayed in the same browser is also highlighted in
grey. Syntax objects in the same *secondary partition* as the selected
subterm are highlighted in light blue---see the next section for more
The "Clear" button clears the selection.
The "Properties" button displays a property window that shows
additional information about the selected syntax object. See the
Properties section for more information.
The Secondary Partitionings
See the documentation for these predicates in the MzScheme manual.
Two identifiers are symbolic-identifier=? if discarding all lexical
context information yields the same symbol.
* same marks
Two identifiers have the same marks iff using both as the first
argument to datum->syntax-object on the same symbol yields two
In other words, they are almost bound-identifier=?, but they may have
different symbolic names.
* same source module
The bindings of the two identifiers come from definitions in the same
* same nominal module
The bindings of the two identifiers were imported into the current
context by requiring the same module.
When the properties pane is shown, it displays properties of the
selected syntax object. The properties pane has three tabbed pages:
If the selection is an identifier, shows the binding information
associated with the syntax object.
*Note: See the warning in the section below.
For more information, look up 'identifier-binding',
'identifier-template-binding' in the Help Desk.
Displays source location information about the syntax object.
Displays properties (see 'syntax-property') of the selection
when it has properties it knows the keys for.
Warnings about interpreting syntax
* The binding information of a *syntax object* may not be the same as
the binding structure of the *program* it represents. The binding
structure of a *program* is only determined after macro expansion is
Example: (browse-syntax #'(lambda (foo) foo))
The syntax browser will report that the inner 'foo' is unbound, even
though in the *program* that this syntax represents, the inner 'foo'
is bound to the outer 'foo'.
Notes and Limitations
The syntax browser does not have a way of extending the set of
available secondary partitions.
The syntax browser does not have a way of extending the set of known
The syntax browser does not preserve the distinction between
parentheses and square brackets.