ParseTree parse(Symbol current_symbol, ParseTree root) { /*recursive function to parse the tokens*/ /*current_symbol: The symbol currently on top of the stack*/ /*root: The pointer to the root of the relevant subtree of the Parse Tree*/ int i; char id_or_num[50]; char temp_token[20]; ProductionTable prodtable; Production production; List prod_right; TreeNode tnode = (TreeNode)malloc(sizeof(struct tnode)); strcpy(tnode->name,current_symbol->name); tnode->type = current_symbol->type; tnode->line_num = line_num; //first check if current_symbol is a terminal if(current_symbol->type == TERMINAL) { //Check if the current_symbol is ε. If yes then simply continue if(strcmp(current_symbol->name, "ε")==0) { root->node = tnode; root->num_branches = 0; return root; } //Check if its TK_ID or TK_NUM to strip additional data if((strcmp(current_symbol->name, "TK_ID")==0)||(strcmp(current_symbol->name, "TK_NUM")==0)) { sscanf(current_token,"%*[^:]%*[:]%s",id_or_num); sscanf(current_token,"%[^:]",current_token); tnode->id_or_num = (char *)malloc(50*sizeof(char)); strcpy(tnode->id_or_num,id_or_num); } //check if current token is a match if(strcmp(current_symbol->name, current_token)==0) { root->node = tnode; root->num_branches = 0; //we can eat the current token and move ahead if(strcmp(current_token,"EOF")!=0) advance(token_file); return root; } else { //Error Handling. return NULL. fprintf(stderr,"ERROR at line %d:: Expected %s. Found %s.\n",line_num,current_symbol->name,current_token); exit(1); } } else { //this is a nonterminal. so we need to apply the appropriate production from the parsing table sscanf(current_token,"%[^:]",temp_token); prodtable = current_symbol->prodtable; production = findProduction(prodtable, temp_token); if(production==NULL) { //Error Handling. return NULL. fprintf(stderr,"ERROR at line %d:: Expected symbols are ",line_num); for(i=0;i<current_symbol->num_first;i++) printf("%s, ",current_symbol->first[i].symbol->name); if(current_symbol->nullable==YES) for(i=0;i<current_symbol->num_follow;i++) printf("%s, ",current_symbol->follow[i].symbol->name); printf("Found %s.\n",temp_token); exit(1); } //appropriate production found. add current symbol to tree. root->node = tnode; prod_right = production->prod_right; //now create as many branches at current root as symbols in prod_right. root->branches = (ParseTree *)malloc(sizeof(ParseTree)*(production->num_symbols)); root->num_branches = production->num_symbols; for(i=0;i<production->num_symbols;i++) { //applying rules for all symbols on right hand side of the rule. root->branches[i] = (ParseTree)malloc(sizeof(struct ptree)); root->branches[i] = parse(prod_right[i].symbol, root->branches[i]); } } return root; }
bool Parser::reduce(ParserActionReduce* const r) { if (r == 0) return false; const int productionID = r->getProductionID(); ProductionStub* prod = findProduction(productionID); if (prod == 0) { log_ << "fatal error: there is no production with ID = " << productionID << "!\n"; return false; } bool result = true; const std::list<int>& body = prod->getBodyIDs(); std::vector<ParserSymbol*> removedSymbols; for (std::list<int>::const_reverse_iterator it = body.rbegin(); it != body.rend(); ++it) { if (! states_.empty()) states_.pop(); else { log_ << "fatal error: stack is empty!\n"; result = false; } if (! symbols_.empty()) { if ((*(symbols_.top()) != *it) && (! isProxySymbol(*it, symbols_.top()->getSymbolID())) ) { log_ << "fatal error: top symbol ('" << symbolID2String(symbols_.top()->getSymbolID()); log_ << "') does not match the symbol in the production's body ('"; log_ << symbolID2String(*it) << "')\n"; log_ << "ProdcutionID = " << productionID << "\n"; result = false; } // Attention: this reverses the order of the symbols from the stack! // removedSymbols.push_back(symbols_.top()); symbols_.pop(); } } symbols_.push(new ParserSymbol(prod->getHeadID())); const int nextState = gotoState(states_.top(), prod->getHeadID()); if (nextState >= 0) states_.push(nextState); else { log_ << "fatal: no following state found for state "; log_ << states_.top() << " and symbol " << symbolID2String(prod->getHeadID()) << "\n"; result = false; } delete prod; if (result == true) expandParseTree(productionID, removedSymbols); for (size_t i = 0; i < removedSymbols.size(); ++i) delete removedSymbols[i]; return result; }