Dynamic Browsing Of Curry's Diagrams

 

Submitted To:

Dr. Sergio Antoy

Portland State University

Submitted By:

Sushma Kumar

Date:

Spring 1998

 

 

Introduction

This project is an extension of the work done by three other graduate students, Hazel Morgan, summer 1997, Vijayasree Krishnaprasad, fall 1997 and Phillip R. Neff, Winter 98. Hazel's project, written in Java, implemented a diagrammatic representation of the syntax of a language. Within the init() method of the applet, class CurryDiagram, the setup()method was called to construct all the diagrams of the target language by calling a diagram-specific method for each of the non-terminals of the target language.

For an example, createStart() method created the Start diagram and entered it into a java.util.Hashtable container called "diagrams" under the key "start". Each diagram of the target language was created in a similar way and put into the Hashtable for easy access.

The init() method displayed the Start diagram, which is the initial diagram. As in any language grammar, the non-terminals could be expanded further in terms of other non-terminals and terminals. Hence, the non-terminals displayed,would respond to mouse clicks. On sensing a mouseDown event on a non-terminal, the appropriate diagram was located in the hash table, using the appropriate key, and displayed.

The init() method of the applet class CurryDiagram called the method setup(). This method built the diagrams for each of the non-terminals of the target language by calling methods specific to each non-terminal. Hence the code that built these diagrams was dependent on the syntax of the target language.

To overcome this problem, the diagram creating functions were moved into a separate class called Grammar class, with all the diagrams being declared as public fields in the class. This class created all the necessary diagrams. Then using java.lang.reflect class available in JDK 1.1, the applet class CurryDiagram used the reflection methods to add all the diagrams into the hashtable. The Field class was used to query the fields and the 'get' method was used to reference the diagrams created in class Grammar. The original code was in JDK 1.0 and in order to use the Reflect class, JDK 1.1 was used. This made the code less useful since many popular browsers e.g. Netscape 3, and Explorer 3 do not fully support Java 1.1.

Goals

The goals of this project were to:

    1. Make the Java code independent of the syntax without using Reflection class. This would make it possible to view the applet through many popular browsers.
    2. Verify that the Format Converter works for another sample grammar.

Current Work

To avoid using Reflect, it was necessary to find a way to access the diagrams created in class Grammar from class CurryDiagram just by creating an instance of class Grammar. The diagrams to be accessed, were defined as fields in class Grammar and were initialized in the constructor routine. Hence, two vectors, one diagramList and other diagramNames were added to the Grammar class. diagramList was used to store all diagrams created in the contructor routine and diagramNames stored the names of the diagrams created. After initializing all the diagrams, they were added to diagramList and their names to diagramNames.

 

public Vector diagramList = new Vector();

public Vector diagramNames = new Vector();

diagramList.addElement(start);

diagramNames.addElement("start");

diagramList.addElement(PragmaDeclaration);

diagramNames.addElement("PragmaDeclaration");

.....

 

The class GrammarConverter creates the Grammar.java as output file. Hence to add the above lines of code to Grammar.java the following lines of code had to be added to the GrammarConverter class:

 

output("public Vector diagramList = new Vector(); \n");

output("public Vector diagramNames = new Vector(); \n");

...

...

...

enum = diagNames.elements();

while(enum.hasMoreElements()) {

currentElement = (String)enum.nextElement();

output("diagramList.addElement(" + currentElement + ");\n");

output("diagramNames.addElement(\"" + currentElement + "\"); \n");

}

 

The first two lines add the definition for the two vectors to the output file i.e. Grammar.java. In the remaining half, the vector diagNames, which is a local variable, created in routine parseFile() in class GrammarConverter, contains the names of the diagrams that need to be created in class Grammar. This vector (diagNames) is used, as shown above, to create the code in Grammar which would add all the diagrams to the vectors diagramList and the names to diagramNames

 

This achieved the first goal i.e. the Java code is made independent of the syntax without using reflections. As mentioned before, the Format Converter had been tested only with the syntax of Curry, hence it was essential that it be tested with some other sample syntax in order to ensure that the Format Converter can handle any grammar. A grammar was selected for this purpose, it was then manually converted to the format which would be accepted by GrammarConverter. The applet was then tested using this grammar. An example of how this conversion is done is shown below.

Start ::= ( PragmaDeclaration )? ( FixityDeclarationList )*

(DataOrFunctionDeclarationList )* EOF

Would be converted to:

(diagram start

(sequence

(optional (nonterminal PragmaDeclaration))

(zero-or-more (nonterminal FixityDeclaration))

(zero-or-more (nonterminal DataOrFunctionDeclarationList))

(terminal EOF)))

 

On executing the applet for the new grammar, a couple of bugs were found. Hence, besides the changes mentioned above, some small fixes had to be made. The first of these was to check if all nonterminals appearing in the syntax file (excepted by GrammarConverter.java) also have their own productions defined. Currently if a user wishes to see the production for a nonterminal in the syntax diagram, he needs to click on the "box" for the nonterminal. On detecting a mouse click, the diagram for this nonterminal is displayed by calling cardlayout(this,nonterminal) in CurryDiagram.java. However if no such diagram exists, no action is taken. Hence if a nonterminal was not defined (i.e. if it did not have it's own production) a user would discover it only when he clicks on the nonterminal diagram in the applet.

It is appropriate that this error be caught at an earlier stage and also to avoid a manual check of all nonterminal diagrams to catch such an error.

The following lines of code were added in order to achieve the above:

private static Vector _nonTerminalNames = new Vector();

private static Vector _nonTerminalDefined = new Vector();

Vector _nonTerminalNames would contain all the nonterminals obtained while reading the input file and Vector _nonTerminalDefined would contain those nonterminals that had productions.

public void checkNonTerminalDefinitions(){

while(!(_nonTerminalDefined.isEmpty()))

{

_nonTerminalNames.removeElement(_nonTerminalDefined.firstElement());

_nonTerminalDefined.removeElementAt(0);

}

if(!(_nonTerminalNames.isEmpty()))

System.out.println("Error in input file: The following nonterminals have not been defined" + _nonTerminalNames.toString()+"\n" );

}

This new method called checkNonTerminalDefinitions() removed all elements that existed in Vector _nonTerminalDefined from Vector _nonTerminalNames. This ensured that all nonterminals who had their own productions were remove from _nonTerminalNames thus leaving behined only those without a definition. These would be printed as errors.

The second fix was required because of a subtle bug in GrammarConverter.java. GrammarConverter.java used hashtable _vectors that stored the constructed statements/lines of code to be written to Grammar.java. The keys used to store these lines of code in the hashtable were strings e.g. "Vector1", "Vector2", etc. The reason this was done, was because the lines of code corresponding to the keys were created 'out of order' but they had to written to Grammar.java in a descending order i.e. "Vector8" followed by "Vector7" followed by "Vector6" etc. Hence the hashtable was created, lines of code added, finally an enumaration was obtained. This enumaration accessed the hashtable based on the keys and hence the required descending order of output was obtained. But there was a small bug, if the production considered was very large, it would create many more vectors. Consider the case where we hav! e more than nine vectors created, the order obtained by enumaration would no longer be descending i.e. it would be "Vector9" followed by "Vector8", "Vector7", ....., "Vector1", "Vector10", "Vector11", "Vector12" ... etc. Hence to fix this problem the keys were changed from strings to integers

static void addVector(String name, String value) {

_vectors.put(name,value);

}

was changed to:

static void addVector(String name, String value) {

_vectors.put(new Integer(name.substring(_index)),value);

}

Thus a key of the form "Vector#" was converted to an integer by extracting the substring representing the number and converting it to an Integer. Hence _index was set to 6. Similar change was made in the removeVector() method.

The class Grammar was created for this syntax using GrammarConverter. On running the applet CurryDiagram the diagrammatic representation obtained was found to be as required. However, there was a small problem. The 'Start' sequence of the new grammar being tested was longer than that of Curry, thus the width of the applet had to be increased. Besides this small problem the Format Converter had worked well for this sample grammar.

Future Work

The method of displaying a sequence has to be slightly changed. As mentioned above, if the sequence is too long, the width of the applet has to be changed for the whole sequence to be displayed. One way of avoiding this problem is by checking the width of the sequence before it is displayed. If the sequence happens to be longer than the width of the applet, the sequence can be broken into parts before being displayed. Another alternative would be to resize the applet, hence the user would have to use the scroll bars to view the whole sequence.

Conclusion

The changes to Vijayasree Krishnaprasad's design made it possible to view the applet with many popular browsers. This wasn't possible earlier due to the inclusion of Reflect which needs JDK 1.1. After testing the applet with another sample garmmar, some minor bugs were found and fixed. One can conclude that the Format Converter can handle any grammar.