I had to implement a parser according to a given grammar as part of a school project. However, only the program execution was graded and I want to know if my code adheres to best practices. I would really appreciate it if you could give me pointers on how to improve my code.
Search conditions are of the form: a + b < 10 OR c = 1. The following code parses the search condition into an expression tree. The input to the function is a vector of the tokens in the search condition.
void recursiveSplit(node *parent, vector<string> const &tokens, string delimiter) {
/* Given a string, parse it into an expression tree with nodes as the
* operators and the children as the operands */
if (tokens.size() == 1) {
/* Base case for the recursion, the leaf nodes are either strings or
* integers */
node *mathNode;
mathNode = new node(tokens[0]);
parent->subTree.push_back(mathNode);
return;
} else {
vector<string>::const_iterator it;
for (it = tokens.begin(); it != tokens.end(); it++) {
if (*it == delimiter) {
break;
}
}
if (it != tokens.end()) {
/* Case 1 :delimiter was found */
node *delimNode;
delimNode = new node(delimiter);
parent->subTree.push_back(delimNode);
vector<string> leftTokens(tokens.begin(), it), rightTokens(it+1, tokens.end());
string newDelimiter = switchDelimiter(delimiter);
recursiveSplit(delimNode, leftTokens, newDelimiter);
/* In rightTokens, we still need to search for the current
* delimiter since we may have multiple instances of the delimiter
* */
recursiveSplit(delimNode, rightTokens, delimiter);
} else {
// delimiter is not found
string newDelimiter = switchDelimiter(delimiter);
recursiveSplit(parent, tokens, newDelimiter);
}
}
}
string switchDelimiter(string delimiter) {
/* Return the next delimiter based on the priority. The priority of
* operations is : OR, AND, <, >, =, +, -, * */
char delim;
if (delimiter == "OR") {
delim = '|';
} else if (delimiter == "AND") {
delim = '&';
} else {
delim = delimiter[0];
}
switch(delim) {
case '|':
return "AND";
case '&':
return "<";
case '<':
return ">";
case '>':
return "=";
case '=':
return "+";
case '+':
return "-";
case '-':
return "*";
case '*':
return " ";
}
}
node *createTree(const string& searchStrBuf) {
string buf;
stringstream ss(searchStrBuf);
vector<string> tokens;
while(ss >> buf) {
if ((buf != ")") && (buf != "(")) {
tokens.push_back(buf);
}
}
node *root = new node("searchTreeRoot");
recursiveSplit(root, tokens, "OR");
return root;
}
class node {
public:
string nodeType;
vector<node *> subTree;
node(string strNodeType) {
nodeType = strNodeType;
}
};