help with symbol table C++

Started by
6 comments, last by swiftcoder 14 years, 5 months ago
Here I have a simple parser program, and I am trying to add a symbol table to it so basically when it reads int, double or char it will store that as a tokenType and then I want it to read the name afterwords so say i then it will store that in tokenName. I have it storing the type, but I can't seem to wrap my head around having it read the next token without making it hardcoded to be a certain name like how I did int, double and char... any input would be very helpful, thank you. Here is my code so far:

int main(int argc, char* argv[])
{
	//input object
	ifstream source;

	//variables to store line, token, and
	//boolean to determine end of line read
	string myline;
	string token = "";
	bool done = false;

	//Structure for symbol table
	struct item
	{
		string tokenType;
		string tokenName;
	}table[1000];

	//position in line read
	int pos = 0;
	int i = 0;

	//Open source file
	//source.open(argv[0]);
	source.open("input.txt");
	if(!source.is_open())
	{
		cout << "cant open file!";
		return 0;
	}

	//Read til end of file
	do
	{
		done = false;
		
		//get line from input file
		getline(source, myline);

		if(!source.eof())
		{
			//do... while until line is read
			do
			{
				char c = myline[pos++];
				if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
				{
					token = token + c;
				}
				else if(c == '(' || c == ')' || c == '{' || c == '}' || c == ';'
					|| c == '=' || c == '+' || c >= 0 || c <= 0)
				{
					if(token == "int" || token == "double" || token == "char")
					{
						table.tokenType = token;
						i++;
					}
					cout << token << endl;
					token = "";
					cout << c << endl;
				}
				if (pos >= myline.length())
				{
					done = true;
					pos = 0;
				}
			}while(!done);
		}
	}while(!source.eof());

	//close input file
	source.close();

	//table format
	cout << "Type      Variable Name\n";

	//loop to display each of the symbol tables data
	for(int j = 0; j < i; j++)
	{
		cout << table[j].tokenType << "        " << table[j].tokenName << endl;
	}

	system("pause");

	return 0;
}

Advertisement
After you read the token type, assuming there's some sort of whitespace following, can't you just read in the remainder of the line (or until ';' or some other terminator is reached, etc.) and store whatever occurs?

FYI, if you have it, you may want to look at some of the "is" routines in the C run-time library: isalpha, isalnum, etc.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I thought that something like this would work, but nothing seems to be happening or at least that I see... anyone have any ideas here?

Here is my code so far:

int main(int argc, char* argv[]){	//input object	ifstream source;	//variables to store line, token, and	//boolean to determine end of line read	string myline;	string token = "";	string tName = "";	bool done = false;	//Structure for symbol table	struct item	{		string tokenType;		string tokenName;	}table[1000];	//position in line read	int pos = 0;	int i = 0;	//Open source file	//source.open(argv[0]);	source.open("input.txt");	if(!source.is_open())	{		cout << "cant open file!";		return 0;	}	//Read til end of file	do	{		done = false;				//get line from input file		getline(source, myline);		if(!source.eof())		{			//do... while until line is read			do			{				char c = myline[pos++];				if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))				{					token = token + c;				}				else if(c == '(' || c == ')' || c == '{' || c == '}' || c == ';'					|| c == '=' || c == '+' || c >= 0 || c <= 0)				{					if(token == "int" || token == "double" || token == "char")					{						table.tokenType = token;						c = myline[pos++];						if(c == ' ')						{							if(c != ';')							{								c = myline[pos++];								tName = tName + c;							}						}						table.tokenName = tName;						i++;					}					cout << token << endl;					token = "";					cout << c << endl;				}				if (pos >= myline.length())				{					done = true;					pos = 0;				}			}while(!done);		}	}while(!source.eof());	//close input file	source.close();	//table format	cout << "Type      Variable Name\n";	//loop to display each of the symbol tables data	for(int j = 0; j < i; j++)	{		cout << table[j].tokenType << "        " << table[j].tokenName << endl;	}	system("pause");	return 0;}
What's up with:
	else if(c == '(' || c == ')' || c == '{' || c == '}' || c == ';'		|| c == '=' || c == '+' || c >= 0 || c <= 0)
and..
	if(c == ' ')	{		if(c != ';')
?

That said, I might have misunderstood your intentions, but does this help:
#include <string>#include <iostream>#include <fstream>#include <algorithm>#include <vector>#include <iterator>#include <cctype>struct Item{	std::string tokenType, tokenName;	Item(std::string tokenType, std::string tokenName)	: tokenType(tokenType), tokenName(tokenName) {}};std::ostream& operator<<(std::ostream& os, const Item& item){	return os << item.tokenType << "\t" << item.tokenName;}typedef std::vector<Item> Table;bool DelimPred(char c){    return !std::isalpha(c);}int main(){	Table table;	//Open source file	std::ifstream source("input.txt");	if(!source)	{		std::cerr << "cant open file!" << std::endl;		return 0;	}	//Read til end of file	while(source.good())	{		//get line from input file		std::string line;		std::getline(source, line);		std::string::iterator it = std::find_if(line.begin(), line.end(), DelimPred);		if(it == line.end())		{			std::cerr << "Malformed line: " << line << std::endl;			continue;		}		table.push_back(Item(std::string(line.begin(), it), std::string(it + 1, line.end())));	}	//table format	std::cout << "Type\tVariable Name" << std::endl;	// display each of the symbol tables data	std::copy(table.begin(), table.end(), std::ostream_iterator<Item>(std::cout, "\n"));}
All those are the characters I want to read only. All of that reads fine the ' ' and ';' are ones I want to cancel the reading on the type and variable name. Basically what I want the symbol table to look like would be this, if I input a file that has
main(){int num;return 0;}


Aside from the parser it would output the following...
Type   Variable Nameint      num


so far I got it doing all but the num part, any ideas on this?
Okay I got it reading the variable name after the type and displaying it properly except for one minor problem it is adding the ; in there as well, I have to look at my confusing jumble of mess to see if I can find the problem, if you see it please feel free to point it out to me, thank you.

Here is my code now:
int main(int argc, char* argv[]){	//input object	ifstream source;	//variables to store line, token, and	//boolean to determine end of line read	string myline;	string token = "";	string tName = "";	bool done = false;	//Structure for symbol table	struct item	{		string tokenType;		string tokenName;	}table[1000];	//position in line read	int pos = 0;	int i = 0;	//Open source file	//source.open(argv[0]);	source.open("input.txt");	if(!source.is_open())	{		cout << "cant open file!";		return 0;	}	//Read til end of file	do	{		done = false;				//get line from input file		getline(source, myline);		if(!source.eof())		{			//do... while until line is read			do			{				char c = myline[pos++];				if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))				{					token = token + c;				}				else if(c == '(' || c == ')' || c == '{' || c == '}' || c == ';'					|| c == '=' || c == '+' || c >= 0 || c <= 0)				{					if(token == "int" || token == "double" || token == "char")					{						table.tokenType = token;						while(c != ';')						{							c = myline[pos++];							tName = tName + c;						}						table.tokenName = tName;						i++;					}					cout << token << endl;					if(tName != "")					{						cout << tName << endl;					}					token = "";					tName = "";					cout << c << endl;				}				if (pos >= myline.length())				{					done = true;					pos = 0;				}			}while(!done);		}	}while(!source.eof());	//close input file	source.close();	//table format	cout << "Type      Variable Name\n";	//loop to display each of the symbol tables data	for(int j = 0; j < i; j++)	{		cout << table[j].tokenType << "        " << table[j].tokenName << endl;	}	system("pause");	return 0;}


This is what my output looks like for the symbol table now,

Type   Variable Nameint        num;


**EDIT figured out that semi-colon problem so far it is running almost perfect, I need it to loop that process if a ',' is found.
You should really really tokenize your input _before_ you parse it. That'll simplify your code considerably. Your code as it is demonstrates a rather weird and incorrect idea of what a token is.
Quote:Original post by wicked357
*** Source Snippet Removed ***
mattd's point was that your else condition is always true:

else if(c == '(' || c == ')' || c == '{' || c == '}' || c == ';' || c == '=' || c == '+' || c >= 0 || c <= 0)

Note the last two clauses - c must always be either <= or >= zero (because those two cases include all possible numbers). Thus, you can replace that massive else if(...) with a simple else statement.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement