#include "stdstuff.h" #include "Iterator.h" #include "VarTreeNode.h" // globally accessible Iterator object. Iterator _iterator; // works even if tree incomplete (i.e. an operator node woth no children) // as long as pointers are null when children don't exist. this is // guaranteed by the node constructor. void deleteVarTree (VarTreeNode *root) { if (root -> left != NULL) { deleteVarTree (root -> left); } if (root -> right != NULL) { deleteVarTree (root -> right); } delete root; } void outputVariable (VarTreeNode *root) { switch (root -> type) { case VarTreeNode::SUBSCRIPT: outputVariable(root -> left); cout << "["; outputVariable(root -> right); cout << "]"; break; case VarTreeNode::NAME: cout << root -> varname; break; case VarTreeNode::NUMBER: cout << root -> value; break; case VarTreeNode::UNDEFINED: default: // should really throw an exception break; } } static void produceExpectedButFoundMessage (String2002 str) { char ch = _iterator.lastLook(); int index = _iterator.lastLookIndex(); cout << "** Error Detected **\n" << _iterator.getString() << endl; for (int i = 0; i < index; i++) { cout << ' '; } cout << "I\n"; if (ch == Iterator::EOS) { cout << "Expected " << str << " but found end of expression.\n"; } else { cout << "Expected " << str << " but found " << ch << ".\n"; } } static VarTreeNode *recognizeNumber () { int value; if (!isdigit(_iterator.look())) { produceExpectedButFoundMessage ("digit"); return NULL; } value = _iterator.get() - '0'; // consume as many digits as possible while (isdigit(_iterator.look())) { value = (value * 10) + (_iterator.get() - '0'); } return new VarTreeNode (VarTreeNode::NUMBER, value); } static VarTreeNode *recognizeName () { String2002 name; if (!isalpha(_iterator.look())) { produceExpectedButFoundMessage ("letter"); return NULL; } name = (char) _iterator.get(); // consume as many letters as possible while (isalpha(_iterator.look())) { name += (char) _iterator.get(); } return new VarTreeNode (VarTreeNode::NAME, 0, name); } static VarTreeNode *recognizeVariable (); static VarTreeNode *recognizeSubscript () { VarTreeNode *operNode; if (isdigit(_iterator.look())) { // must have number if ((operNode = recognizeNumber()) == NULL ) { return NULL; } } else { // must have variable if ((operNode = recognizeVariable()) == NULL ) { return NULL; } } return operNode; } static VarTreeNode *recognizeVariable () { VarTreeNode *leftExp, *operNode, *rightExp; // apply rule ::= name ... if ((leftExp = recognizeName()) == NULL) { return NULL; } // either done or have [ subscript ] if (_iterator.look() != Iterator::EOS) { // must have [ if (_iterator.look() != '[') { deleteVarTree(leftExp); produceExpectedButFoundMessage ("["); return NULL; } _iterator.get(); // cross off the [ if ((rightExp = recognizeSubscript()) == NULL) { deleteVarTree (leftExp); return NULL; } if (_iterator.get() != ']') { deleteVarTree(leftExp); deleteVarTree(rightExp); produceExpectedButFoundMessage ("]"); return NULL; } operNode = new VarTreeNode (VarTreeNode::SUBSCRIPT); operNode -> left = leftExp; operNode -> right = rightExp; return operNode; } else { operNode = leftExp; return operNode; } } // on success, returns reference to root node of the parse tree. // otherwise returns NULL after outputting an appropriate error message. VarTreeNode *createVarTree (String2002 str) { VarTreeNode *exp; _iterator.setup (str); if ((exp = recognizeVariable ()) == NULL) return NULL; if (_iterator.look() != Iterator::EOS) { produceExpectedButFoundMessage ("end of expression"); deleteVarTree(exp); return NULL; } return exp; }