Main
The main function drives the whole program. Its overall structure hasn't changed much since our last iterationexcept for the addition of the function table, the symbol table, and the store.
const int maxBuf = 100; const int maxSymbols = 40; void main () { // Notice all these local objects. // A clear sign that there should be // a top level object, say, the Calculator. // Back to the drawing board! char buf [maxBuf]; Status status; SymbolTable symTab (maxSymbols); FunctionTable funTab (symTab, funArr); Store store (maxSymbols, symTab); do { std::cout << "> "; // prompt std::cin.getline (buf, maxBuf); Scanner scanner (buf); Parser parser (scanner, store, funTab, symTab); status = parser.Eval (); } while (status != stQuit); }
Notice that for every line of input we create a new scanner and a new parser, but we keep the same symbol table, function table, and store. This is important because we want the values assigned to variables to be remembered as long as the program is active. The parser's destructor is called after the evaluation of every line. This call plays the important role of freeing the parse tree.
Let's have another look at the structure of the project (see Table 1). You can see that most classes have their own file pairsthe header file and the implementation file. A few files contain more than one class. Closely related groups of classes and data structures are sometimes combined. The main function is usually put in a separate file, whose name is either main.cpp, or is derived from the name of the application, as it is in our case.
Table 1Project Files and Their Contents
Files |
Contents |
Calc.cpp |
main |
Parser.h, Parser.cpp |
Parser |
Scan.h, Scan.cpp |
Etoken, Scanner |
FunTab.h, FunTab.cpp |
FunctionEntry, funArr, FunctionTable |
SymTab.h, SymTab.cpp |
SymbolTable |
StrBuf.h |
StringBuffer |
List.h, List.cpp |
Link, List |
HTab.h, HTab.cpp |
HTable |
Store.h, Store.cpp |
Store |
Tree.h, Tree.cpp |
Node and its children |