The remainder of this chapter covers how to implement an imperative language, focusing on Sling for its examples. The internal representation of an imperative language script is a command. The following two sections cover
Imperative languages often allow the user to create new functions, such as cartesian(x, sin(4*x)) . A pair of sections cover
After showing you how to capture Sling commands and functions, this chapter wraps up with a discussion of the Sling target class and covers the remaining tasks for building a Sling parser:
Write a grammar.
Write assemblers to build Sling commands.
Generate a Sling parser from the grammar, plugging in the assemblers.
The package sjm.examples.sling provides an environment for Sling, including a collection of classes that implement the language and make it available to a user. Figure 16.13 shows a high-level view of the sequence of methods that produce a Sling plot.
Figure 16.13. A Sling environment sequence. The objects in this diagram collaborate to recognize a user's program and create a corresponding command.
The classes in sjm.examples.sling include a user interface. Like other user interfaces in this book, the Sling environment divides user interface tasks between an IDE class and a mediator class. The IDE class organizes and displays visual Swing components , and the mediator class handles component interaction. This separation makes it easier to understand, extend, and debug the user interface.
The action buttons in the class SlingIDE register a SlingMediator object as their event listeners. When a Sling user clicks the Go button, the object receives an actionPerformed() call. The mediator checks the user's program to see whether the program text has changed since the last time the mediator parsed it. If it has, the mediator uses a SlingParser object to parse the text.
When a SlingParser object completes its recognition of a user's program, the result is a collection of commands on an Assembly object's stack. These commands correspond to the assignment statements and the plot and for commands of the user's program. The mediator pops these commands, builds a composite command from them, and executes the command. When plot commands execute, they create Sling functions and add them to a RenderableCollection object (not shown in Figure 16.13). After the mediator executes the command, it sends the function collection to the SlingIDE object's display panel, and the plot displays.
The following sections describe how to build commands and how to build runtime functions.