The Happy Hands Java Speech Editor written by Sean W Hennessy.
He was a virtuosic piano player. He wrecked his hands because he was
programming software at least 10 hours a day, then going home and banging
on a piano for 2 hours a day. He wrote this program to try to salvage his
career as a programmer, his piano, and hopefully make a significant
contribution to the world.
Happy Hands relies on an external speech recognition engine. We have tested
IBM ViaVoice and the Microsoft speech engine. IBM's seems to be better.
At all the times Happy Hands in a set of speech handlers that are in a
waiting state. A speech handler is an internal mechanism that may not seem
important to the user, however since Happy Hands is a ground-breaking
program in computer science, we feel that some technical explanation of
these mechanisms is important. A speech handler is a collective set of
behaviors and states that defines both the grammar to listen for and how
to respond to the user's speech when it matches that grammar. It is the
logical equivalent to the graphical dialog box that presents an input
mechanism and handles input. In Happy Hands, a speech handler can be in
an active or a waiting state. In the waiting mode, the handler is listening
for speech that has a very simple grammar that's main purpose is to
activate the handler. When it is activated, it changes its available
grammars according to the context at hand. This two-stage mechanism
is employed because it makes recognition easier on the underlying speech
recognizer engine. Generally the activation grammars are simple and
not context sensitive, however the grammars and the activated state may
be very complex, containing thousands of alternative recognitions.
We call the speech handlers concerned with generating Java code transcribers.
Other speech handlers do things like opening files, selecting text, moving
about, operating on the source code, etc. These often do not have a
distinct active state.
If you are considering trying Happy Hands and you have no recognizer installed
at all, we sugest getting the Microsoft recognizer from their web site for free.
This will enable you to try out Happy Hands without spending any money at all.
On the other hand, Happy Hands works beautifully, so you might as well get Via Voice.
Via Voice is generally a more conservative recognizer. It requires a greater
confidence level to respond than the Microsoft recognizer. This means you get
fewer false positives. The Microsoft recognizer is eager to respond, and is
faster in deciding what you said, but sometimes responds to utterances it seems
to imagine. Via Voice has the advantage of having a formal training system that
makes you read it stories, so it will already know your voice when you
start using Happy Hands. If you have already trained Via Voice for dictating
letters, it is ready for Happy Hands.
If you have purchased a recognizer not mentioned here it is possible that Happy Hands
can use this recognizer just as well. Before you go out and buy a new recognizer
we recommend you simply run Happy Hands and consult this list to find out
if the recognizer you already have will work. When choosing the recognizer
from this list, try to pick one that includes
"Command and Control", or sounds like it is intended for limited grammars
rather than letter writing.
A project consists
of a single file that has information regarding what source directories
should be considered in the project, what compiler to use, the class path
setting, and other various settings needed to run the compiler. The
list of available projects is found by reading the file "settings/workspace.xml"
in installation directory. This file is so simple and readable that it
should be possible to create projects by editing this file instead of
using the user interface, however one is provided.
The syntax colors may be changed by editing the file settings/settings.xml.
There are four basic types of elements in a Happy Hands grammar. These elements
are each rendered in a different way in the grammar view.
The project file setting controls the name of the
file where project information is stored. When you create the new project,
a file chooser appears to set this value. The value will also be added
to the "settings/workspace.xml" file.
The source code directories setting is a list of directories where the
source code of the project should be found. Each directory should go up
to and including the first directory of the package. For example, if
you have a package tree that goes pac_x.pac_y.pac_z, it is not necessary
to make the directory end at the package root, pac_x. You could stop it
at pac_y, and only these files will be included.
The "classpath" setting effects the following:
The "lib path" setting controls the dynamic link libraries or shared object
libraries used by the Java virtual machine, when testing.
The "test class" setting is used when testing. It is the class you want the Java virtual
machine to enter.
The "arguments" setting is used when testing. These are the arguments are given to Java
program being tested.
The "vm arguments setting is used when testing. These are the arguments given to the VM.
Please note that in these descriptions we refer to specific utterances
that they have since changed either because of implementation changes,
or changes in user settings. The exact words that may be spoken at any
point maybe discovered by looking at the grammar views.
Before this phrase is uttered, the package declaration transcriber is in
a waiting state in the "Transcribers" grammar view. The grammar view shows
that "append package declaration" is one of the grammars that the package
listens for. Upon uttering the phrase, the package transcriber is moved
to the active grammar view.
When the package declaration is inserted into the document, the first element
of the package is selected. The package specifier defaults to "no_value".
The package name is spoken in it's entirety. For example, to declare your
file a member of the java.awt package, say "java a w t" in one utterance.
An incremental specification system may be used as well. Note that this
feature has come and gone but may come back. When first element of the
package specifier is selected, the transcriber is listening for any one
of the root package specifiers found in the class path. Examples of root
package specifiers are "java" and "javax". Upon recognition of one of
these alternatives, another "no_value" package specifier is appended. The
recognizer is now listening for package specifiers that are found in with
in the first package specifier, for example "awt". Once you have
spoken the last element of a package specifier, you need to manually
delete the last element with the backspace key.
Please note the Happy Hands specially prepares symbol names for the recognizer so
they will be easy to speak. Because "awt" is not an English word it will be broken
up into its component letters, so you say "a - w - t". See the section on symbol
renaming for details.
For example to generate the import statement "import java.awt.*;" say
"java a w t" in one utterance. Like the package transcriber, and incremental
ability has come and gone. In this mode, if you choose to enter a package
specifier by typing it, after the new text is parsed the import transcriber
will change the available grammar to the set of package specified within
the name of the name you just typed.
The red square around the class definition means the class definition
transcriber is waiting for speech. The red square around the class name
means that the naming transcriber is also waiting for speech. In
Happy Hands, a transcriber may be assisted by a sub transcriber.
In this case, the class definition transcriber is assisted by the
naming transcriber.
It is also possible to give the name by speaking. The naming transcriber
is started automatically when a new class is started. (The naming transcriber
will start automatically only if the "auto name" option is enabled. It is
disabled by default.) This transcriber
accepts is a sequence of English words, or letters using the alpha-bravo-charlie
alphabet. For example, to name your class
"Sean", say "capital sierra echo alpha november". If the naming transcriber
is not active, activate it by saying "class name", or click the mouse on the
class name.
Example of how to create this class definition:
Example of how to create this field declaration:
Notice it does not matter what order you specify the parts of the declaration,
because Happy Hands has a broad view. To change the null value, select the null
element and use the expression transcriber.
Example of how to create this method definition:
The expression statement transcriber itself has no abilities other than creating new
expression statement. It simply hands control to the expression transcriber.
The expression transcriber is by far the most sophisticated transcriber
in the Happy Hands system. It handles the transcription of all elements
that may occur within an expression, including references to variable
names, field names, method invocations, and object instantiations, binary
operators, unary operators, tertiary operators, type casts, array
initializations, anonymous classes, and more.
The expression transcriber is very context sensitive. You may notice a
pause (of maybe a second) as the expression transcriber starts, because
it is preparing the grammars speakable within the expressions context.
The length of the pause will vary according to how much the context
changed since the last time the expression transcriber was used.
The basic insert mode of the expression transcriber is replacement.
Expressions are for the most part binary trees, with some lists too.
When you utter an expression grammar, the currently selected expression
element is usually replaced by what you have said. The exception to this
rule is the utterance of operators, such as "addition", which adds
siblings to the expression tree, and the grammars related to building
method argument lists or array initialization lists. New expression
parts requiring specification are called "no_value".
Expression utterances can be as short or as long as you like. It is
not necessary to pause between different clauses in the utterance.
To make the expression a = b + c(d) you could pause frequently,
saying: "variable a, assignment, variable b, addition, method c, variable d",
or you could say it all together: "variable a assignment variable b addition
method c variable d". Saying sentences as long as you can will enable you
to code faster, and improve recognition.
If the local variable has a class type it is possible to also speak a member
name of the class after the variable name, in one utterance. (This behavior
is available only if the "variable members" setting is enabled. The default is true.)
Example: if the variable is called filename and it is of type String, you
could say: "variable file name sub string", or "variable file name length".
If the member is a function, default arguments are added automatically.
Example: the expression is formerly "[a]".
Example: the expression is formerly "[a]".
Example: the expression is formerly "a + [b]".
Example: the expression is formerly "a + [b]".
Example: the expression is formerly "[a + b]".
Example: the expression is formerly "a * [b]".
To get a full list of binary operators, look under the operator tree node
in the expression grammar, under the "Active" panel, while an expression
transcriber is active.
Example: the expression is formerly "[i]".
Example: the expression is formerly "[a && b]".
To get a full list of unary operators, look under the operator tree node
in the expression grammar, under the "Active" panel, while an expression
transcriber is active.
Example: if there is a field declared within the class being edited called
nCount, say "field n count". Like variable identifiers, if a field that has
a class type it is possible to speak a member name of the class after the
field name, in one utterance. (This behavior is enabled with the "field members"
option. It is true by default.)
Example: the expression is formerly "[a]".
As with every other transcriber in Happy Hands, the method invocation transcriber
pulls as much information as it can from the context of the code, rather than
keeping track of the events that got it to its current state. This means that
the overload switching grammars can be used even if the method was not just
recently named.
After the method to invoke is identified, the first argument
of the method is selected. (If the method has no arguments the method name
element is selected.) A value can be uttered as in the standard expression
transcription. To move to the next argument, say "next argument". To move
to the previous argument, say "previous argument". You can also use the
mouse or move the keyboard caret to do this.
Example: the expression is formerly "g.drawString(no_value, no_value, no_value)".
Example: the expression is formerly "g.drawString(no_value, no_value, no_value)".
Within method argument lists, there is a
special convenience that lets you move to the next argument automatically when
the current argument is fully specified. If you say "sequence" at any time during
an expression utterance, this puts the transcriber into a mode that automatically
moves to the next argument when the current argument is fully specified. The special
mode ends at the end of the utterance. Of course, it is not completely clear
when an expression is fully specified. The transcriber uses the following
rule: if the expression has no "no_value" elements in it, it is fully specified.
Another value uttered after this, in sequence mode, will be applied to the next
argument list element.
Example: the expression is formerly "g.drawString(no_value, no_value, no_value)".
Example: the expression is formerly "g.drawString(no_value, no_value, no_value)".
It is possible too add arguments with "add argument". This appends to the
argument list. To insert an argument before the argument of the selected
element, say "insert argument". To remove an argument, say "delete selection".
This function removes the selected list element.
Example: "new type dimension sequence integer two integer three" gives "new Dimension(2, 3)".
Example: if the recognizer is having trouble understanding "type Dimension" you could
say "new type java a w t dimension sequence integer two integer three",
giving "new java.awt.Dimension(2, 3)".
Example: "new type one dimensional floating point array" gives "new float[[no_value]]".
Example: the expression is formerly: "[lines]".
Example: the expression is formerly: "String text = [textVector.elementAt(i)]".
You can use the normal expression grammar within a string by saying "append text"
first.
Example: the expression is formerly: "".
You might be able to enable English dictation
for strings by saying "use English". This feature is tentative. The majority
of strings are short debugging print outs, making English dictation involving
long sentences inappropriate most of the time.
Examples of expressions......
The context:
Example: apple = orange*banana
Example: apple = (orange+banana)*5
Example: apple =orange+banana*5
Example: kiwiFruit = new Fruit()
Example: kiwiFruit = new Fruit("kiwi", 10)
Example: kiwiFruit.size = 20
Example: kiwiFruit.size = 20
Example: fruitArray = new Knife().cut(kiwiFruit, 0.5f)
Example: fruitArray[0].size = banana
That explains the transcription of expressions. The rest of the Happy Hands
language is a cinch.
The element filling in the test expression is selected. Speak an expression to fill in the value.
Example: if(a != b){...}
All of the transcribers that generate a block offer an additional insert
prefix: "enclose with". Using this prefix will cause the selected element(s) to
be enclosed with the block element.
Example: the expression is formerly: [System.out.println("debugging string")]
Example:
Example: Opening the file demo.sorting.Sort
To define your own macro, you need to write a small Java class the uses the small
macro API. You then put the fully qualified class name in the file settings/macros,
and change the class path in the Happy Hands start up script to include your macro.
The macro API is this:
Happy Hands comes with some factory defined macros, described below.
Introduction
The Happy Hands Java Speech Editor is an elaborate text editor designed to
convert speech input into perfect Java code. This is accomplished as the user
speaks on the level of their thoughts, not Java syntax. The Happy Hands Java Speech Editor
changes the state of mind of the programmer by enabling him to rise above
the details of entering text into a document.
Document conventions
Code elements enclosed are like this, [code element], to indicate the red
selection square is around the element in the Happy Hands editor.
Technical Overview
Requirements
Happy Hands is a Java program. We assume you have a Java virtual machine
if you are doing Java coding. Version 1.4.1 or greater is required.
Speech Input
Happy Hands uses a rule based speech input. It builds grammars based on what
you are trying to do, and the current insert point in the code. There
grammars are submitted to the speech recognizer engine. The engine will
recognize only these grammars. This means Happy Hands is 100% accurate
if the recognizer property matches what you are saying. Possible responses
to your speech are:
The first case is the most common. On a good day this is what will happen 90% of the
time. The second case is the next most common. It can be frustrating, but just try
to relax and its not a big deal, since its harmless aside from the wasted time. The
last two cases happen about equally, not often enough to worry about. As you practice,
using a consistent microphone position and tone of voice, especially if you tend
to edit code that makes use of the same libraries (with the same symbol names) consistently,
your results will improve.
Choosing a recognizer
When Happy Hands starts, it queries the system about what recognizers are
available. At this time Happy Hands can use only recognizers that implement
the SAPI4 specification. This includes IBM's ViaVoice and the Microsoft
recognizer. To find the what
recognizer are availible, use the "Recognizer Controls" function under the
"File" menu. This gives you a list of usable recognizers on your system.
From this panel is also possible to change the recognizer that Happy Hands
is using on the fly. Select the recognizer a from the list and hit the
"Use the Recognizer" button. Then use the "Reinit speech" function to
make the change take effect.
Context Sensitivity
Happy Hands keeps lists of alternative speech tokens that are submitted
to the recognizer for uttering the name variable, a field, a method, a target,
a type, or a package. These lists of alternatives, which are usually
implemented practice as a more highly developed grammar than a simple list,
maybe inspected in the "Types", "Vars", "M.Fld", "M.Meth", "S.Fld", and
"S.Meth" grammar views. Inspecting the will convince you that the context
reflects the current insert point in the source code. The symbol lists,
however, are not used as stand-alone grammars. They are part the grammars
offered by the transcribers specific to the type of lexical element being
editing at the time. The context sensitivity varies by not only the list
of alternatives symbols offered for certain point to the source code, but
also by the transcriber that defines speech grammars intended to edit the
specific type of lexical element at that point. In other words, Happy
Hands understands the target of your speech at every point, and the
options at that point.
Symbol renaming and remapping
Happy Hands specially prepares symbol names for the recognizer to make them
easy to speak. For example, because "awt" is not an English word,
it will be broken up into its component letters, so you will say "a - w - t".
Other renaming rules Happy Hands applies to symbols include breaking up
compound words that are notated as in "setClipRect" into phrases such as
"set clip rect". The renaming rules it applies are applied recursively to
each sub part of the new phrase, so that "rect" will become "r - e - c - t",
because rect is not an English word. However, whenever words are broken
to component letters, the original unchanged word is offered as an
alternative, so that saying "set clip rect" and "set clip r e c t" will
both map to the same result. Another renaming that Happy Hands applies replaces
all underscores with spaces, unless the underscores appear at the
beginning or end of the symbol, in which case is represented by saying
"underscore", so _getGraphics becomes "underscore get graphics". The list
of words Happy Hands considers to be English is read from a file "settings/words"
in the installation directory. You may add words to this file and if you wish.
Before symbols are coerced, a remap table is consulted to find out if the
word should be spoken in some completely different way. The remapping table
is built by reading the file "remap" in the Happy Hands installation
directory. If you inspect this file, you will see that the symbol "Integer"
has been remapped to "capital integer", and "javax" has been remapped to
"java x". For maximum versatility, the remapping is done before the renaming,
and also to generated sub words.
Syntax Tree
When you open a file and Happy Hands Java code transcriber, a file is parsed
and converted into syntax tree, and the tree is then rendered to text and
presented in the text editor. The syntax tree has the same information as
the tree handed to the Java byte code generator, with the addition of comments.
The tree is composed of pieces each with an easily understandable meaning,
and therefore easier to work with for either a person or a computer. It is
not simply an engineering solution, but a feature of the Happy Hands system.
Tree to text conversion
As the tree is modified, a tree to text generator updates the text in the
editor. We cannot emphasize enough that when you use Happy Hands you do not
have to worry about detailed syntax elements such as semicolons, braces and
parentheses, because it generates these for you in converting from the tree
to text. This fact, combined with the context sensitivity, means that most
causes of compiler errors are eliminated. Often when you compile a text file
generated with Happy Hands, it compiles with no errors the first time.
The tree to text conversion takes place incrementally. The smallest group
of tree elements that needs to be updated is run through the tree to text
generator, resulting in a snappy response.
Text to tree conversion
Although speech is more humane than typing, it is also essential for the user
to be able to simply type, because sometimes Happy Hands, despite its greatness,
cannot always understand you. Therefore Happy Hands can convert the text to
the tree (and then back to text). It does this in an incremental way for
speed. As you type it assumes the probable type of lexical element of the
insert point is unchanged since the previous time, and submits this text to
a general Java parser in the section of the parser logic designed for
parsing that type of grammar. If this parsing fails, it gives a larger
section of text to the parser, and so on until it achieves a successful
re-parse. Because it does this in an incremental manner, the size of the
document is not a factor in re-parsing to the tree, or rendering of the
syntax tree to text. Happy Hands is usually able to convert from text to
tree and to text in a fraction of a second.
As you type, your typed text is a light gray color indicating it has not been
generated from the syntax tree. The text will not be re-parsed with every
keystroke - it is re-parsed after you finished typing for half a second. In
the event of a syntax error, the unparsed the text will remain until the
problem is fixed.
File opening
Upon the opening of the Java source code file, the file is parsed and
converted into the syntax tree that Happy Hands keeps. The file must
be free of syntax errors. If there are any syntax errors they will be
highlighted and the file will be displayed as originally on disk, and
keyboard entry mode will be started. Once all the syntax errors have been
fixed, simply exit keyboard entry mode and the file will be re-parsed.
The file does not have to be able to compile without errors, but the simply
able to parse without errors. This means the braces and semicolons need to
be in the right places, but the symbols do not have to be resolvable. In
practice this requirement does not seem to be hard to achieve.
File saving
When Happy Hands saves a file, it is saving the text generated by its tree
to text generator. This means the file will be saved in the current coding
style Happy Hands is using. At the time this document was written, only
one coding style is offered, but this will become customizable. The upside
of this is that the files run through Happy Hands are very neat and regular.
The downside of this is the any special formatting that that has special
meaning to the developer is lost.
Undo system
Happy Hands has an undo system that tracks changes made either by
speaking or typing. To save memory an undo limit is imposed, which
defaults to 10.
Projects
Although Happy Hands is not intended to be an integrated development
environment that provides a universal solution for all your coding
needs, it does have some rudimentary bookkeeping that keeps track of
your project. These abilities simply make it easier to use and will
not interfere with your projects from other development environments.
Happy Hands does not try to run the whole show.
Compiling
Happy Hands can run the compiler on single files or directories. The compiler
to use is set in "settings/workspace.xml". Settings such as the class
path are set in the file specific to the current project. These can be controlled
from the projects panel. Compiler errors are listed in the box on the right.
Clicking on an element in the list takes you to the error. It is also possible
to say "next error" and "previous error" to iterate through without using your
hands at all. The top file in the editor can be compiled by saying "compile top file"
or hitting the button for it.
Testing
Happy Hands can run a Java program and capture the programs output in the
box labeled "Testing". To start the test, say "test program". To stop the
test, say "stop test".
Tips and Tricks
Editing of existing elements
Existing code elements can be modified by selecting them with the red
selection box. This starts a transcriber designed to edit this type of
element. In fact, the editing of existing elements is what Happy Hands
is doing most of the time. After a new element is created it is treated
the same as any other element and editing begins as if an existing element
was selected. There is scarcely any difference between creating a new
code and editing old code. We will admit that creating new code is generally
faster because you are saying expressions in big streams of thought instead
of short utterances. For making tiny changes sometimes it is best to simply
use the keyboard.
Grammar stringing
Most transcribers have several independent grammars they are listening for.
These may strung together in one utterance, without pausing to see the text
update. The effect of each rule will be applied in the order they were
spoken. As long as the speech keeps coming, no text will be updated, because
the recognizer is waiting to find out if an as yet unspoken rule could be matched.
Reparsing and keyboard mode (the Esc key)
A mode of operation is available that allows you to enter text using the keyboard
with the incremental reparsing and transcription disabled. You can always enter text
with the keyboard, and normally this causes an automatic local reparse. However,
if you switch to keyboard only mode, the reparsing will not happen, nor will
you be able to enter code by speaking. Happy Hands becomes a normal text editor
in this mode. To switch to keyboard mode, hit the Esc key. To switch back,
hit it again. When you switch back to transcription mode, the entire file is
reparsed and regenerated, in one or two tenths of a second. Note that hitting
the Esc key twice is a handy way to cause a full reparse in the unlikely event
that the Happy Hands incremental reparse has become confused. This mode is especially
useful for entering comments, and doing big pastes and deletes.
A transcriber is finished by starting another
There is no need to explicitly end an active transcriber. Simply by starting
another, either by invoking its waiting state grammar to append an element, or
by selecting an existing element, the active transcriber is be ended and replaced
with the new one.
Single utterance functions will not interfere
Using a non transcription speech function will not stop the active transcriber,
unless the function requires additional speech input. This enables one to
say things like "save top file" in the middle of transcription.
Always a waiting handler
When a transcriber is moved from the waiting state to the active state, it
is copied, the copy is placed in the waiting state. This enables the creation
of an element while another element of the same type is being edited.
Long names are better
Long names are more likely to be recognized, because they have a more distinctive
profile. Try to use longer names when naming new symbols. You will never have
to type them again, so there is no reason for brevity.
Room noise
Happy Hands only responds to certain specific grammars. It will not be confused
by conversations, frustrated muttering, or the radio.
Default values
In several cases, optional language elements are offered as place holders in
the text while the owning element is selected. For example, a for-loop does
not require expressions in the header, but they are offered so that they may
be selected while the for-loop is selected.
User Interface Components
Text editor component
The text editor component is the large white if box located in the upper left
corner. It is a traditional text editor that does some fancy graphics to
indicate the state of the user's input. As you move the mouse over the
source code, a green rectangle appears over various elements in the source
code. The green rectangle shows you which element is currently selected.
The green rectangle selection sets the insertion point for new elements,
and the target for operations such as deleting or copying an element. If
you click the mouse on an element (it will already have the green selection
rectangle around it), it is further selected for transcription, acquiring a
red square. A transcriber appropriate for editing the selection is started
and the context is updated. If the "auto edit" switch is enabled, element
is selected for transcription after half of second of no mouse movement.
Grammar views
The grammar views describe what it is possible to say. The grammar
view is organized into a tree in which some sets of children run horizontally
and others run vertically. All non leave elements are expanded and contracted
by pressing them once with a mouse. (We have made every effort in the
development of Happy Hands to avoid requiring the use of the mouse and
especially mouse button presses, however the mouse's utility as a geometrical
picking tool is unparalleled, so we continue to target it for this.)
There are several grammar views that each describe a grammar that is used
for a different purpose. These are:
Syntax tree view
The syntax tree component is a rendition of the internal tree data structure
that is the principle target of the user's input. This component is provided
mostly to satisfy the user's curiosity. It was used during the development of
Happy Hands.
Undo history view
This shows a list of undoable actions.
Files view
The project files component has a listing of files known to be part of the
current project. The primary purpose of this component is the fast opening
of files. Later we will describe is not necessary use this component if you
can remember and speak the file's name. The project files component is
drawn like a traditional file browser. At the top level there is a list
of available projects. The list of available projects is found by reading
the file "settings/workspace.xml" in the Happy Hands installation directory.
Under each project node in the project files component is a list of
directories. Under each directory are the Java packages arranged in a
hierarchical manner. The list of directories in the project is a user
setting, however the Java source files of the project are found by looking
on the disk. Every Java file under one of the project directories is
assumed to be a file in the project. You do not have to explicitly add
every Java file to the project. Maybe this behavior could be a problem
if you have some files not intended to be the project, but are in the
project directory. However since we believe that it is bad coding
practice to keep such stray files in with the good ones, these files
should be moved to different directory in order to not appear here and not
be subject to compilations.
Projects component
The project component has a list of projects and a gui for assigning
the project settings.
Note the CLASSPATH environment variable is not included. The classpath setting
is a set of files and directories. The files need to be .jar or .zip files.
Menus
Happy Hands has conventional graphical function launcher menus, although
every function in the menu is accessible via speech. Happy Hands has only the basics:
a "File" menu, a "Edit" menu, and a "Build" menu. The functions are described below,
in the speakable functions section.
Standard Grammars
Type grammar
Many of the transcribers in Happy Hands make use of the standard type
grammar within their specialized grammars. The first word of the standard
type grammar is always "type". This convention avoids ambiguity in recognition.
If the type is a non array type, the next word is the either the type name
or the fully specified type name. For example, "type string" and "type java
Lang string" will generate the text "String". Primitive types use slightly
modified names to aid recognition: "integer" means into, "floating point"
means float, "double" means double, "long integer" means long, "character"
means char, "byte" means byte, "Boolean" means Boolean, and "void" means void.
The expression for an array type is done as follows: For the type String[],
say "one-dimensional string array", or "one-dimensional java lang string
array". For the type int[][], say "two dimensional integer array".
The available type names in the grammar are determined by the import
statements of the file. If the type you are trying to speak is not
being recognized, make sure you importing that type in the import
statements. Note that the ambiguity between the type names integer
and Integer is solved by remapping the name Integer to "capital
integer", as defined in the remapping file. All of the other class
types in java.lang that are proxies for primitive types follow the
same convention.
Insert prefixes
Many of the transcribers in Happy Hands that insert statements into the code
offer several prefixes that come before their particular grammar. These
prefixes specify where the insert will happen.
The Transcribers
The transcribers are the devices in Happy Hands that translate speech to
code. They are the raison d'etre of the program.
Package transcriber
To create a new package statement, say "insert prefix package declaration".
(The usual utterance is "append package declaration"). This
tells the waiting package transcriber that you would like to append a
package declaration. It does this and then changes to the active
state grammars. The default looks like:
package no_name;
Import transcriber
To create import statement, say "insert prefix import statement". The import
transcriber works much like the package transcriber, with the additional
ability to add a star. The default import statement looks like:
import no_name;
Class definition transcriber
To create a new class definition, say "insert prefix class definition".
(The phrase "append class definition" appends after the current element,
"insert class definition" inserts before the current element. Also try
"insert in block class definition", "replace with class definition", and
"enclose with class definition".) The default class definition element
looks like:
class [no_name]{
}
Class name
The easiest way to name the class is to simply type it. This is usually the
best way to supply any new symbol name. The class name text is highlighted
and ready to be replaced when the new class element is created. When you
have finished typing the syntax tree will be regenerated reflecting the
new name. With Happy Hands, once the name is typed once, you will be able
to refer to it with speech. It is always possible to tell when a piece of
text has not been generated from the syntax tree when is a light gray color.
This means the parser has not been run on this text, or it has been run but
did not succeed because of a syntax error.
Access Modifier
To change the access modifier of the class you may say "public", "protected",
"private", or "package".
Memory Modifier
To change the memory modifier of the class you may say "static" or "non static".
The memory modifier, of course, has application only to an inner class.
Base Class
To specify the class's base class, say "extends standard type grammar".
The available type names are affected by the import statements of the file.
For example, to make the class extend JPanel, make sure javax.swing.* is
imported, and say "extends type j panel".
Interfaces
To specify that the class implements an interface, say "implements
standard type grammar". For example, to implement ActionListener, make
sure java.awt.event.* is imported and say "implements type action listener".
Multiple interfaces may be specified. To remove a interface from implements
list, move the mouse over to and say "delete selection". The "delete
selection" function is a general function that removes the selected
element from the list it is in.
Inner elements
To enter any element in the class body, select the class definition with
the red square and use the "insert in block" prefix before the type of
element to insert. For example, to insert a method definition, say
"insert in block method definition".
public class SubButton extends JButton implements ActionListener{
}
Field declaration transcriber
To create a new field declaration, say "insert prefix field declaration".
To insert the field within the class definition, say "insert in block field declaration".
To insert after an existing class member, say "append field declaration".
Note that either phrase might work because Happy Hands attempts to insert
elements in reasonable places. It will never insert a field declaration
at the file scope; if "append field declaration" is said while a class
definition selected, the field will appear within the class. The default
field declaration looks like:
int [no_name] = 0;
Field Name
To name the field, notice that the red square is already surrounding the
name of the field, allowing you speak or type in its name immediately. With
the name element selected, you have the option of speaking to the name
transcriber, although it is usually easier to type new names. Longer names
are easier for Happy Hands to recognize. The naming transcriber can be
started by clicking the field name with the mouse, or by speaking "field name".
Access Modifier
To change the access modifier of the field you may say "public", "protected",
"private", or "package".
Memory Modifier
To change the memory modifier of the field you may say "static" or "non static".
Constant Modifier
To change the constant modifier the field you may say "final" and "non final".
Field Type
To change the type of the field, speak "standard type grammar". When you
change the type of field declaration, the field is given a default
initializing value corresponding to the type, unless the field is already
initialized to some non-default value. In this case the initializer value
is not changed.
static protected Component defaultView = null;
Method definition transcriber
To create a new method definition, say "insert prefix method definition".
To insert the method within the class definition, say
"insert in block method definition". To insert after an existing class
member, say "append method definition". The default method definition looks like:
void [no_name] (){
}
Method Name
To name the method, notice that the name of the method is already selected,
allowing you to type in its name immediately, or use the naming transcriber.
Return Type
The method return type is set by saying "type grammar". For example, to
make the method return a String, say "type string". To make the method return
an integer array, say "type one dimensional integer array".
Access Modifier
The access modifier of the method is set by saying "public", "protected",
"private", or "package".
Memory Modifier
The memory modifier of the method is set by saying "static" or "non static".
Thread Modifier
The thread modifier to the method is set by saying "synchronized" and "non synchronized".
Adding an argument
To add an argument to the method, say "add argument type grammar" to
append to the argument list, or "insert argument type grammar" to
insert before the currently selected argument.
Adding a throws declaration
To add a throws declaration, say "add throws type grammar"
Base class override
To make the method automatically override a method in a base class, say "override
base class method name". This handy feature will change the method name, the
method return type, and the arguments to match the method in the base class.
If the method in the base class has multiple overloaded arguments, you may say
"next overload" to cycle through them.
Constructor
To make the method a constructor, simply say "constructor". This will remove
the type specification and change the method name to the
name of the enclosing class.
public synchronized int arraySet(int[] src, int[] dst)
throws ArrayLengthException{
}
Variable declaration transcriber
To start a variable declaration, say "insert prefix variable declaration".
The variable declaration transcriber is just like the field declaration
transcriber. The only difference is the absence of access modifiers and
memory modifiers.
Expression statement transcriber
To create a new expression statement, say "insert prefix executable".
The expression statement transcriber starts and then starts an expression
transcriber to transcribe the expression element. The default expression
statement looks like:
[no_value];
Expression transcriber
The expression transcriber is what is used to dictate expressions, such
as a = b+c, which is said as "variable a, assignment, variable b, addition,
variable c". Pauses are optional. The expression transcriber is always
started as a child of another transcriber, like the if test transcriber
or the return statement transcriber. It is not in the waiting
transcriber group, so you cannot say "append expression". It never
adds an element to a block. The expression transcriber can also be started
by selecting an expression with the mouse or keyboard.
Variable identifiers
Variable identifiers are spoken by saying "variable variable name". The
variable name alternatives are found by examining the current method body for
variable declarations, from within the current block up to the method block.
Example: "variable i".
Binary operator
There is another group in the expression grammar called binary operators.
The utterance of any one of the binary operators will put the operator on
the right side of the currently selected value, create the right hand side
element of the operator and select it. Inspecting these elements in the
syntax tree view or waving the mouse over an expression and observing
how the selection rectangle changes shows that the expression is mostly
a tree grouped by binary operators.
Say "addition" and it becomes "a + [no_value]".
To attach a binary operator to the left side of the currently selected value,
say "left side
Say "left side addition" and it becomes "[no_value] + a".
To replace the currently selected value with a binary operator with default
left and right values, say "replace with
Say "replace with addition" and it becomes "a + [no_value] + no_value".
Operator precedence is inferred from the selection state when operators are added.
Say "multiplication" and it becomes "a + b*[no_value].
Say "multiplication" and it becomes "(a + b)*[no_value].
Say "addition" and it becomes "a * (b+no_value)".
Unary operator
There is another group and the expression grammar called unary operators.
The utterance of a unary operator will append the operator either on the
right or left side of the currently selected value, depending on the type
of the operator. The currently selected value actually becomes the
operator's child, and the operator takes its place.
Say "post increment" and it becomes "[i++]".
Say "pre increment" and it becomes "[++i]".
Say "logical not" and it becomes "[!(a && b)]".
Tertiary operator
The single tertiary operator is spoken as "tri graph".
Example: the expression is formerly "[a]".
Say "tri graph" and it becomes "[no_value] ? no_value : no_value".
Field identifier for this object
Field identifiers belonging to the current class are spoken by saying
"field
Continuing a dot selection
As described above, the variable and field grammars have the capability of adding
one member of the variable or field after a dot, in one utterance, enabling
a one dotted member selection, such as: "a.length", "b.toString()", "c.setClip(null)".
But sometimes you need to select an existing element and add a dotted member
selection after it. Sometimes you need more than one dot. To do this, select
the element to add the dot after, and say "chose member". This adds the code
".no_selection" and updates the expression grammar to include members for the
element before the dot. You then select members with "select field field name",
and "select method method name". The expression grammar then reverts back
to normal.
Say "chose member".
The expression becomes: "a.[no_selection]".
Say "select method get graphics".
The expression becomes: "a.getGraphics()".
In this case it would have also been possible to say "variable a get graphics"
in one utterance.
Field identifier selected after a dot
To add a field identifier after a dot, say "select field method name".
The field alternatives are found by identifying the type of the object before
the dot and offering the fields that are accessible from within the local
access privileges.
Method invocation for this object
Method invocations belonging to the current class are spoken by saying
"method method name". This indicates a method preceded by the "implicit this".
The method alternatives are found by examining the current class body for method
definitions, as well as any super classes. This system also applies to methods
added in a continued utterance from another value, as in "variable g draw string".
Also, this system applies to methods added via "variable g chose member, select
method draw string". Happy Hands adds fake values within the method arguments
list to remind you how many and what types of arguments the method requires.
(The fake values are expression roots called "no_value"). These fake values are
replaced as the arguments are filled in. To change to a different overload, say
"next overload" or "previous overload", or say "one argument", "two arguments,"
"three arguments", etc. The overloads are offered sorted by argument count.
Say "variable text next argument variable x next argument variable y".
The expression becomes "g.drawString(text, x, y)".
Say "variable text next argument, variable x addition integer two, next argument
variable y multiplication integer negative one".
The expression becomes "g.drawString(text, x*2, y*-1)".
Say "sequence variable text variable x variable y".
The expression becomes "g.drawString(text, x, y)".
Say "sequence variable text variable x addition integer two variable y
multiplication integer negative one".
The expression becomes "g.drawString(text, x, y)".
After the "addition", the second argument was
"x + [no_value]". When "integer two" was processed, the current list element
was not fully specified so the 2 was applied here rather than to the next argument.
Method invocation selected after a dot
To add a method invocation after a dot, say "select method method name".
The method alternatives are found by identifying the type of the object before
the dot and offering the methods that are accessible from within the local
access privileges. The standard method argument grammars apply.
Object instantiation
To instantiate an object, say "new type grammar". Instantiation is just
like a method call. The standard method argument grammars apply.
Array instantiation
To instantiate an array, say "new type grammar", using a type grammar that means
an array. The array brackets with default to dimension values are added automatically.
Array indexing
To index an array, say "index array". Brackets are added after the current value,
which is required to be an array type. The indexing value is selected automatically.
Say "index array variable i", the expression becomes "lines[i]".
Type cast
To make a type case, say "type cast". A type cast is inserted before the current
element. The current selected element is now a type identifier, and type can be
specified.
Say "type cast".
The expression becomes "String text = ([no_type])textVector.elementAt(i)".
Say "type string".
The expression becomes String text = ([String])textVector.elementAt(i)".
Usually it is easier to say it all in one utterance: "type cast type string".
Numeric constant
To add a numeric constant, say "primitive type name numeric value".
For example to add the integer 5, say "integer five". To add a long integer
1,211,262 say "long integer one million two hundred and eleven thousand two
hundred and sixty two". To add 3.14f, say "floating point three point one four".
To make the number negative, say "negative" before the number expression.
To add -273 say "floating point negative two hundred and seventy three".
String constant
To add a string constant, say "string constant". This creates an empty string.
Say "append text variable apple"
The expression becomes "apple"
Create the expression "apple="+apple, type the =, then say "addition variable apple".
This, super, null, true, and false
These are spoken as follows: "this object", "super object", "null constant",
"true constant", "false constant"
Anonymous class
To define a class within an expression, say "new anonymous type grammar".
The class implements or extends the type given type grammar.
Example: the expression is formerly: "new Thread([no_value])".
Say "new anonymous type runnable".
The expression becomes "new Thread(new Runnable(){ ... })".
Removing expression elements
Happy Hands does not have a good way to remove elements from expressions,
other than using the backspace key. Since the expression is quickly re-parsed
and active transcribers are updated, this is perfectly valid the result is
no different.
import java.awt.*;
public class FruitBowl extends Jpanel{
static class Fruit{
int size;
String name;
Fruit(){
}
Fruit(String name, int size){
this.name = name;
this.size = size;
}
}
int banana = 30;
static class Knife{
Fruit[] cut(Fruit fruit, float where){
Fruit a = new Fruit();
Fruit b = new Fruit();
a.size = fruit.size*where;
b.size = fruit.size*(1.f-where);
return new Fruit[]{a, b};
}
}
void makeFruits(){
int apple = 10;
int orange = 20;
Fruit kiwiFruit;
Fruit[] fruitArray;
...........
}
}
Speak: "variable apple assignment variable orange multiplication field banana"
Speak: "variable apple assignment variable orange addition field banana" (pause anytime)
Select the addition element by moving the mouse over the +.
Speak: "multiplication integer 5". The () are added automatically.
Speak: "variable apple assignment variable orange addition field banana" (pause anytime)
Leave banana selected
Speak: "multiplication integer 5"
Speak: "kiwi fruit assignment new type fruit"
Speak: "kiwi fruit assignment new type fruit two arguments"
Speak: "string constant"
Type: kiwi
Speak: "integer 10"
Speak: "kiwi fruit chose member" (required pause)
Speak: "select field size assignment integer 20"
Speak: "kiwi fruit size assignment integer 20"
Speak: "fruit array assignment new type knife chose member" (required pause)
Speak: "select method cut" (good time to pause)
Speak: "sequence variable kiwi fruit floating point zero point five"
Speak: "variable fruit array index array integer zero"
Move selection to hold [fruitArray[0]]
Speak: "chose member" (require pause)
Speak: "select field size assignment variable banana"
If test transcriber
To create an if test, say "insert prefix if test". The default if test looks like:
if([no_value]){
}
Speak: "append if test" (Required pause)
Speak: "variable a is not equal to variable b"
Speak: "enclose with if test" (Required pause)
Speak: "variable b debug"
The code becomes:
if(bDebug){
System.out.println("debugging string")
}
Else if test transcriber
To create an else if test, say "insert prefix else if test". The
default else if test looks like:
The element filling in the test expression is selected. Speak an expression to
fill in the value.
else if([no_value]){
}
Else block transcriber
To create an else block, say "insert prefix else block". The default
else block looks like:
else{
}
While loop transcriber
To create a while loop, say "insert prefix while loop". The default
while loop looks like:
The element filling in the test expression is selected. Speak an expression to
fill in the value.
while([no_value]){
}
Do while loop transcriber
To create a do while loop, say "insert prefix do while loop". The
default do while loop looks like:
The element filling in the test expression is selected. Speak an expression to
fill in the value.
do {
} while(no_value);
For loop transcriber
To create a for loop, say "insert prefix for loop". The default for loop looks like:
To declare a variable in the initialization section, say "declare initializer". To
simply enter an expression in the initialization section, "enter initializer", or
just move the mouse over the initializer and start speaking the expression. To enter
expression in the condition section, say "enter condition", or move there with the
mouse or the arrow keys. To enter an expression in the incrementation section,
say "enter incrementer". The default values in the for loop header are optional
to the tree to text render. They are only rendered if the for loop or any of its
children are selected. They will not be saved to a file.
for(no_value; no_value; no_value){
}
Switch block transcriber
To create a switch block, say "insert prefix switch block". The default the switch block
looks like:
The element filling in the switch value is selected. Speak an expression to fill
in the value.
switch([no_value]){
}
Case block transcriber
To create a case block, say "insert prefix case block". The default
case block looks like:
To add a case with no block, say "insert prefix case label". The case value is selected. Speak
an expression to fill in the value.
case [no_value]:{
}
Return transcriber
To create a return statement, say "insert prefix return". The default looks like:
A default return value is selected. This default value only be added if the function
declares a return value.
return [no_value];
Throw transcriber
To create throw statement, say "insert prefix throw". The default looks like:
A default throw value is selected. Speak the expression to throw.
throw [no_value];
Break transcriber
To create a break statement, say "insert prefix break". The default looks like:
A default target is selected. Speak the target to break to. The default target
value is optional and appears only if the break statement is selected.
break [no_target];
The continue transcriber
To create a continue statement, say "insert prefix continue". The default looks like:
A default target is selected. Speak a target to continue to. The default
target value is optional and appears only if the continue statement is selected.
continue [no_target];
The label transcriber
To create a label declaration say "insert prefix target block".
The default looks like:
The target name is selected. Fill in the name typing it in, or use the naming transcriber.
Adding a target block is a very good use for the "enclose with" prefix.
[no_name]{
}
The try catch block transcriber
To create try-catch block, say "insert prefix try catch block". The default looks like:
Both the try block and catch block are appended together, because only a try block
would be invalid Java grammar. A variable declaration is automatically added in the
catch block header. Use the variable declaration transcriber (which is already active)
to fill in the type of the exception to catch, and is name.
try{
}
catch(no_type [no_name]){
}
Speak: "append try catch block"
try{
}
catch(FileNotFoundException ex){
}
Speak: "type FileNotFoundException"
Type: ex
Catch block transcriber
To create a catch block, say "insert prefix catch block". The default looks like:
A variable declaration is automatically added in the catch block header. Use the
variable declaration transcriber (which is already active) to fill in the type of
the exception to catch, and is name.
catch(no_type [no_name]){
}
Finally block transcriber
To create a finally block, say "insert prefix finally block". The default looks like:
finally{
}
Synchronized block transcriber
To create a synchronized block, say "insert prefix synchronized block". The default
looks like:
The value to wait on is automatically selected. You may now speak the expression
to wait on.
synchronized([no_value]){
}
The doc comment transcriber
To create a doc comment, say "insert prefix doc comment". The default doc comment
looks like:
The keyboard insert point is after the * in the middle line. By default English
dictation is not enabled. To enable it, say "use English". This starts the English
dictation transcriber, which can be used in conjunction with typing to form the comment.
/**
*
*/
The star comment transcriber
To create a start comment, say "insert prefix star comment". The default star comment
looks like:
This works just like the doc comment transcriber
/*
*
*/
The line comment transcriber
To create a line comment, say "insert prefix line comment". The default line comment
looks like:
This works just like the doc comment transcriber.
//
Other speech activated functions
Open file
Spoken as "open file
Speak: "open file demos sorting sort"
or "open file sort"
New file
Spoken as "new unnamed file". This create a new text editor component.
Save top file
Spoken as "save top file". This saves the top file in the text component.
The file is saved with the text that currently appears in the text component.
If the text editor has no known file name, Happy Hands attempts to guess the
name by looking at the first public class and the file and the package
specifier, and presents the save as dialog box with these defaults.
The file is saved exactly as it appears in the editor at the time of the
save. The tree to text generator is not run when saving the file, in order
to preserve any non parseable text of the document. When the file is reopened,
any non parse able text will still be there.
Save file as
Spoken as "save file as". This shows a file chooser dialog box and saves the
top file of the text component to a given file name. The file you have open
keeps the same name it had before.
Close top file
Spoken as "close top file". This saves the top text editor, and removes the
text editor. To close the top file without saving it first, say "close without
saving".
Save and close top file
Spoken as "save and close top file". Saves the top file and closes it.
Save all files
Spoken as "save all files". Save all files.
Revert to auto save file
Spoken as "revert to auto save file". This replaces the content of the top
text editor to the information in the most recent auto save file. This is a
way to do an undo without using the undo system. (The auto save file is beside
the regular file on disk, with the additional extension ".autosave".)
Revert file
Spoken as "revert file". This changes the content of the top text editor to
the information on disk. This is a way to do an undo without using the undo system.
Compile top file
Spoken as "compile top file". This run the compiler on the file of the top
text editor. Any errors are printed out in the build window and highlighted
in the text.
Compile directory
Spoken as "compile directory directory specifier". The directory specifier
is the the Java package of the directory, within the current project. Note any
compiler errors that result may point to the wrong line numbers in the editor when
the file is opened, if the files on disk are not formatted in the Happy Hands style.
Use the Format Directory function to solve this problem.
Cancel Build
Spoken as "cancel build". Stops the compiler.
Format Directory
Spoken as "format directory directory specifier". If you are beginning work
on a directory that has files not formatted in the Happy Hands style, it may be a
good idea to use this function on the files. It opens all the files in the directory,
formats them, and saves them. This ensures the line number output by the compiler
matches the line number in the Happy Hands editor.
Start test
Spoken as "test program". Starts the test process. The project settings control the class to test. The standard
output and standard error from the test process taken up in the "Testing" window.
Stop test
Spoken as "stop test". Stops the test process.
Goto line
Spoken as "go to line line number". Makes the specified line visible in the
editor and highlights it.
Show methods
Spoken as "show methods". Shows the member methods of the type of the current element, in the right panel.
Show fields
Spoken as "show fields". Shows the member fields of the type of the current element, in the right panel.
Show methods of type
Spoken as "show methods of type grammar". Shows the member methods of the given type
in the right pane.
Show fields of type
Spoken as "show fields of type grammar". Shows the member fields of the given type
in the right pane.
Use speech entry
Spoken as "use speech entry". Enables the transcribers and the element selection
system. If you are in keyboard entry mode, hitting the esc key will switch too
speech entry mode too.
Use keyboard entry
Spoken as "use keyboard entry". Disables the transcriber and the element selection
system. This can be useful for making large edits with the keyboard. The keyboard
is enabled at all times in any case. Normally if you use the keyboard, the changed
elements are re-parsed when you're finished typing. In keyboard entry mode this
will not happen. When you exit keyboard entry mode the entire file is re-parsed
and transcription is enabled.
Reinitialize speech
Spoken as "re-initialize speech". This re-initializes the recognizer engine. If you
think it has become bogged down, and it just doesn't seem to be understanding you, use
this function to restart the recognizer. Happy Hands normally does this automatically.
The active grammars become available again after the re-initialization completes, after
about 15 seconds.
Add to selection
Spoken as "add to selection". The currently selected element is added to the
selection set.
Add to selection range
Spoken as "add selection range". The currently selected element is added to
the selection set. Additionally, every element in between this element and
the current selection set is selected.
Clear selection
Spoken as "clear selection". Clears the selection set.
Code to comments
Spoken as "code to comments". Converts the currently selected elements to a comment.
Comments to code
Spoken as "comments to code". Converts the currently selected elements (they
should be comments) to regular code.
Delete selection
Spoken as "delete selection". Removes the currently selected elements from
the syntax tree. This function examines the currently selected elements,
moving up the syntax tree hierarchy, until it finds an element that is within
a variable size list, such as a block, or a method argument list. It then
removes this element. This mean you don't have to be very precise in selecting
the element you really want to remove.
Copy selection
Spoken has "copy selection". Makes a copy of the elements in the selection
set and set them aside.
Paste copy
Edit element
To move to a method definition: say "edit method definition method name"
To move to a field declaration: say "edit field declaration field name"
Undo
Spoken as "undo change". Happy Hands tracks changes made either by speaking or typing.
To undo the last change, say "undo change". To save memory an undo limit is imposed,
which defaults to 10.
Parse file
Spoken as "parse file". This the re-parses the text of the entire file, rebuilding
the syntax tree.
Parse element
Spoken as "parse element". This the re-parses the text of the currently selected
element, rebuilding the syntax tree for this element.
Regenerate file
Spoken as "regenerate file". This regenerates the text of the file based on the
syntax tree. Normally this happens automatically and should be called only of
some other behavior has gone wrong.
Page up
Spoken as "page up". Moves one page up in the editor.
Page down
Spoken as "page down". Moves one page down in the editor.
Exit Happy Hands
Spoken as "exit happy hands". Ends the Happy Hands program.
User Defined Macros
Happy Hands has a macro facility that enables common pieces of code to be
generated easily. The macro text is inserted by saying insert-prefix macro-name.
Once the macro is inserted, it is possible to use the expression grammar to
specify the macros parameters. If the macro only has one parameter, the
expression grammar alone is all that is required. If it has multiple parameters,
you say: paramter-name expression-grammar.
package lde;
public class Macro{
public static final String VALUE = "Value";
/**
* Makes a macro
* @param name The macro name that is spoken
*/
public Macro(String name);
/**
* Add an argument to collect with a grammar appropriate to the type.
* Only type==VALUE is supported now.
*/
public void addArgument(String name, String type);
/**
* Add an argument to collect with a grammar appropriate to the type.
* Only type==VALUE is supported now.
*/
public void setMacroName(String name);
/**
* Retrieves the value of the argument of the given name
*/
public String getArgument(String name);
/**
* Called by the macro manager to get the current macro text. This should be
* overridden to build the text based on some constants and the argument values.
* This is called when the macro is inserted the first time and every time a value
* is specified by the user.
*/
public String makeText();
}
Print out
Inserts the text: System.out.println(no_value);
Example: "append print out".
Debug print out
Inserts the text: System.out.println("no_value: " + no_value);. Then the expression
grammar is then availible to specify the value.
Example: "append debug print out" ... "variable lexer next token"
Loop over length
Inserts the text:
The the expression grammar is then availible to specify the array name.
for(int i = 0; i < no_value.length; i++){
}
Example: "append loop over length" ... "variable line array"
Loop over size
Inserts the text:
The the expression grammar is then availible to specify the container name.
for(int i = 0; i < no_value.size(); i++){
}
Example: "append loop over size" ... "variable line vector"