--- Internal description --- Andrés Gómez Casanova --- 2010-03-20 ---
The core of this application is described in this section. The first thing the application does is to load the grammar and create a graph that represents that grammar. Then, it could analyze the commands written by the user, by doing a lexical analysis and then a syntactic analysis.
This process has to be done before assisting the user. The GrammarReaderController will invoke the corresponding class, and that class, that is a GrammarReader implementation will create the graph. The grammar could be a XML file, where all the grammar is described. But also, it could be just a simple Java class, that has the grammar defined in it. Or it could be eventually a class that read files that describe the grammar in a BNF format.
The graph creation could be a little complex to understand. This process has many internal steps, that ease the grammar definition, but understand all the steps is a little difficult. For example, each command can be described in a separated file, and for each file, a graph will be created; then, these graphs have to be merged in just one, and simplified. Simplified means that different nodes could represent the same token, so the graph has to be modified in order to have just one node.
To conclude, the graph creation will have these steps:
The only important part for the analyzes is the StartingNode, because any node could be reached from this node. It is not necessary to know all the graph in the analyzes part.
The first thing the console does when it is executed, is to create a second thread that will read the grammar. This second thread is created and suspended. Then, the first thread loads the console components, like jLine, and shows the prompt to the user. Once the prompt is displayed and it is ready to receive orders from the user, the second thread (that was waiting for the first thread to finish the loading phase) will be awaken, and the grammar is loaded in background.
When using the XML grammar, the graph will be created following this process:
Assisting the user is the most important function of the application. A user writes part of a phrase that represents a command, and then it makes a call to the application in order to receive assistance.
The application takes the user's phrase, and divides it in tokens. This process is call Lexical analyzes. Each token could be:
And the words are separated by spaces, commas, quotes, or other symbol.
All these elements are defined in the delimiters section of the grammar file (If the grammar file is a XML file.)
Then, the list of tokens is passed to the syntactic analysis and each token is compared to a node to find a possible way in the graph.
Finally, the set of possible options at the end of the way is returned to the user.
This graph is just a simplified example of the real graph created for assistance.
In this graph, we can see that each node of the graph represents a token in the grammar. The connections between nodes represents the order of the tokens when writing a command.
This part takes the phrase written by the user and converts it into tokens. The criterion to select a token is the set of delimiters defined in the grammar file. Spaces are delimiters, but they cannot be tokens. All other characters can be delimiters and characters. Such an example are the quotes ( " ), comma ( , ), parenthesis ( ( ) ), etc.
Once, the phrase is converted into a list of token that will be sent to the syntactic analysis.
db2 create table t1(c1 int, c2 char(10)) CONVERTION PROCESS | db2 | create | table | t1 | ( | c1 | int | , | c2 | char | ( | 10 | ) | ) |
The received parameter is the list of tokens, and internally, it has access to a graph that represents the grammar defined in the grammar files. This graph has been built when the application was executed. This process was described before.
The process consists in taking the first element of the list of tokens, and see if one way from the first node corresponds to that token. The first node is called Starting node, and part of its options is the db2 command.
If an option was found, then, the position in the graph is moved to that node. Then, the process is done again for each member of the list of tokens.
The process stops if the list does not have more elements, meaning that the possible options of the current node will be returned to the user.
Also, the process stops, if there is not matching between the list and the graph. That means that the user is typing an invalid command (or the grammar does not have all the possible options.) Or, if the navigation in the graph has arrived to the Ending node.
If the user typed an invalid command, there is not options returned to the user. If the process has arrived to Ending node, there is not option, and the command can be executed. If the list of tokens is in the middle of the graph, the list of possibles ways in the graph, are returned as options to the user.
1) db2 StartingNode |--db2 <--< |--db2ilist 2) create db2 |--alter |--create <--< |--drop 3) table create |--index |--table <--< |--tablespace 4) t1 table |--<tableName> <--< 5) ( <tableName> |--( ...
As part of the assistance, the application evaluates 9 different cases for assistance. Before describing the cases, it is better to explain two concepts, phrases and options.
Well, now it is possible to explain the cases.
'db2' |- create, catalog, attach |- db2ilist, db2auto, db2fm, db2fmcu
TODO I don't have an example
'db2 c' |- create, catalog |- [EMPTY]
'db2fm' |- db2fmcu |- -i, -t
'db2 create table' |- tablespace |- <tableName>
'db2 create tables' |- tablespace |- [EMPTY]
'db2 create' |- [EMPTY] |- table, tablespace
'db2 create table ' |- [EMPTY] |- <tableName>
'db2 create table ' |- [EMPTY] |- [EMPTY]