Пример #1
0
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;	
}
Пример #2
0
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;
}