I admittedly am an extreme C++ novice, so please forgive me for my probably very naive question.
I am writing code that should parse an assembly language file in its fundamental parts, to be translated into machine language at a second stage.
I have built a parser
class, but I am not having success in opening the external assembly .asm
textfile, and in feeding it to the various functions that compose my parser
class.
More in particular, there are problems with the constructor. I attach the full code I wrote below:
// parses .asm assembly files
#include <iostream>
#include <fstream>
#include <varargs.h>
#include <string>
using namespace std;
class parser
{
private:
istream inputfile;
char inputname[30];
string line;
bool endfile;
bool a_command, l_command, c_command;
string parsedLine, destParsedLine, compParsedLine, jumpParsedLine;
public:
// default parser constructor
parser()
{
}
//parser(char* argv[])
//{
// reader(argv[]);
//}
// opens input file
string reader(char* argv[])
{
strcpy(inputname,argv[1]);
strcat(inputname,".asm");
// opens input .asm file
ifstream inputfile(inputname);
// reads first line
getline(inputfile,line);
if (line[0] == '/' || line.empty())
inputfile.ignore(line.length(),'\n');
return line;
}
// checks if at end file
bool hasMoreCommands()
{
a_command = false;
l_command = false;
c_command = false;
endfile = false;
if (inputfile.eof())
endfile = true;
return endfile;
}
// advances read of inputfile
void advance()
{
if (line[0] == '/' || line.length() == 0)
inputfile.ignore(line.length(),'\n');
getline(inputfile,line);
}
/* function for labelling the type of command (address,computation,label) */
bool commandType()
{
if (line[0] == '@')
a_command = true;
else if (line[0] == '(')
l_command = true;
else
c_command = true;
return a_command, l_command, c_command;
}
// function to select parsing function
string selector()
{
if (a_command || l_command)
symbol();
else if (c_command)
{
dest();
comp();
jump();
string parsedLine = destParsedLine + compParsedLine + jumpParsedLine;
}
return parsedLine;
}
// function returning address or label symbol
string symbol()
{
if (a_command)
string parsedLine = line.substr(1);
else if (l_command)
string parsedLine = line.substr(1,line.length()-1);
return parsedLine;
}
// functions returning computation destination
string dest()
{
size_t equal = line.find('='); //no '=' found = returns 'npos'
string destParsedLine = line.substr(0,equal);
return destParsedLine;
}
string comp()
{
size_t equal = line.find('=');
size_t semicolon = line.find(';');
string compParsedLine = line.substr(equal,semicolon);
return compParsedLine;
}
string jump()
{
size_t semicolon = line.find(';');
string jumpParsedLine = line.substr(semicolon);
return jumpParsedLine;
}
};
// main program
int main (int argc, char *argv[])
{
bool endfile = false;
string parsedLine;
int count = 0;
if ((argc != 2) || (strchr(argv[1],'.') != NULL))
{
cout << argv[0] << ": assembly .asm file argument should be supplied, without .asm extension\n";
return 1;
}
parser attempt1 = parser();
attempt1.reader(argv[]);
while (!endfile)
{
attempt1.hasMoreCommands();
if (endfile)
return 0;
if (count > 0)
attempt1.advance();
attempt1.commandType();
attempt1.selector();
cout << parsedLine << endl; //debugging purposes
count++;
}
}
I provide the name of the .asm
textfile to be opened, from the command line (.asm
file located in the same folder of this cpp
file).
Hence I need to use varargs.h
which I suppose may be part of the problem.
When I try to build this, visual studio 2008 gives me the following 2 errors:
1 error C2512: 'std::basic_istream<_Elem,_Traits>' : no appropriate default constructor available line 21
2 error C2059: syntax error : ']' line 137
Help appreciated, and insults tolerated, thanks :)
Following @Remy Lebeau suggestions, the modified code below at least compiles correctly (still does not do what it is supposed to do though)
// parses .asm assembly files
#include <iostream>
#include <fstream>
#include <varargs.h>
#include <string>
using namespace std;
class parser
{
private:
istream inputfile;
char inputname[30];
string line;
bool endfile;
bool a_command, l_command, c_command;
string parsedLine, destParsedLine, compParsedLine, jumpParsedLine;
public:
// default parser constructor
parser()
{
}
// ignores inputfile line if comment or empty
void ignoreline()
{
if (line[0] == '/' || line.empty())
inputfile.ignore(line.length(),'\n');
}
// composes inputfile name and opens input file
void reader(char* argv[])
{
strcpy(inputname,argv[1]);
strcat(inputname,".asm");
// opens input .asm file
inputfile.open(inputname, fstream::in);
// reads first line
getline(inputfile,line);
ignoreline();
}
// checks if at end file
bool hasMoreCommands()
{
a_command = false;
l_command = false;
c_command = false;
endfile = false;
if (inputfile.eof())
endfile = true;
return endfile;
}
// advances read of inputfile
void advance()
{
ignoreline();
getline(inputfile,line);
}
/* function for labelling the type of command (address,computation,label) */
bool commandType()
{
if (line[0] == '@')
a_command = true;
else if (line[0] == '(')
l_command = true;
else
c_command = true;
return a_command, l_command, c_command;
}
// function to select parsing function
string selector()
{
if (a_command || l_command)
symbol();
else if (c_command)
{
dest();
comp();
jump();
string parsedLine = destParsedLine + compParsedLine + jumpParsedLine;
}
return parsedLine;
}
// function returning address or label symbol
string symbol()
{
if (a_command)
string parsedLine = line.substr(1);
else if (l_command)
string parsedLine = line.substr(1,line.length()-1);
return parsedLine;
}
// functions returning computation destination
string dest()
{
size_t equal = line.find('='); //no '=' found = returns 'npos'
string destParsedLine = line.substr(0,equal);
return destParsedLine;
}
string comp()
{
size_t equal = line.find('=');
size_t semicolon = line.find(';');
string compParsedLine = line.substr(equal,semicolon);
return compParsedLine;
}
string jump()
{
size_t semicolon = line.find(';');
string jumpParsedLine = line.substr(semicolon);
return jumpParsedLine;
}
};
// main program
int main (int argc, char *argv[])
{
bool endfile = false;
string parsedLine;
int count = 0;
if ((argc != 2) || (strchr(argv[1],'.') != NULL))
{
cout << argv[0] << ": assembly .asm file argument should be supplied, without .asm extension\n";
return 1;
}
parser attempt1 = parser();
attempt1.reader(argv);
while (!endfile)
{
attempt1.hasMoreCommands();
if (endfile)
return 0;
if (count > 0)
attempt1.advance();
attempt1.commandType();
attempt1.selector();
cout << parsedLine << endl;
count++;
}
return 0;
}