C++ code, please help! Troubleshooting and cannot for the life of me figure it out. I am using
Visual Studio Code.
Error message:
ld: Undefined symbols:
parseName(std::__1::basic_stringstream, std::__1::allocator>&), referenced from:
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SymbolTable::init(), referenced from:
_main in module-a187a7.o
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SymbolTable::insert(std::__1::basic_string, std::__1::allocator>, int), referenced from:
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SubExpression::parse(std::__1::basic_stringstream, std::__1::allocator>&), referenced from:
_main in module-a187a7.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[Done] exited with code=1 in 1.478 seconds
divide.h
class Divide : public SubExpression
{
public:
//define the default construtor
Divide(Expression* left, Expression* right) : SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//divide the value of left and value of the right
//and return the value.
return left->evaluate() / right->evaluate();
}
};
expression.h
// Expression
class Expression
{
public:
//declare a virtual function evaluate()
virtual int evaluate() = 0;
};
literal.h
//Operand
class Literal : public Operand
{
public:
//define the construtor
Literal(int value)
{
this->value = value;
}
//define the function evaluate()
//returns the value
int evaluate()
{
return value;
}
private:
int value;
};
minus.h
//define the class Minus subclass of the SubExpression
class Minus : public SubExpression
{
public:
//define the default construtor
Minus(Expression* left, Expression* right) : SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//subtract the value of right from the value of the left
//and return the value.
return left->evaluate() - right->evaluate();
}
};
module.cpp
#include
#include
#include
#include
#include
using namespace std;
#include "expression.h"
#include "subexpression.h"
#include "symboltable.h"
#include "parse.h"
//create an object of SymbolTable
SymbolTable symbolTable;
//prototype of the function
void parseAssignments(stringstream& in);
//define main function
int main()
{
// declare the variables
Expression* expression;
char paren, comma;
string line;
// create an input file stream
ifstream fin("input.txt");
// check, if the file is not opened
//then display a error message
if (!fin.is_open())
perror("error while opening file");
//use a loop, to read the content from the file
while (getline(fin, line))
{
symbolTable.init();
if (!fin)
break;
stringstream in(line, ios_base::in);
in >> paren;
cout << line << " ";
expression = SubExpression::parse(in);
in >> comma;
//call the function
parseAssignments(in);
//Display the result
int result = expression->evaluate();
cout << "Value = " << result << endl;
}
system("pause");
return 0;
}
/.
C++ code, please help! Troubleshooting and cannot for the life of me.pdf
1. C++ code, please help! Troubleshooting and cannot for the life of me figure it out. I am using
Visual Studio Code.
Error message:
ld: Undefined symbols:
parseName(std::__1::basic_stringstream, std::__1::allocator>&), referenced from:
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SymbolTable::init(), referenced from:
_main in module-a187a7.o
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SymbolTable::insert(std::__1::basic_string, std::__1::allocator>, int), referenced from:
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SubExpression::parse(std::__1::basic_stringstream, std::__1::allocator>&), referenced from:
_main in module-a187a7.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[Done] exited with code=1 in 1.478 seconds
divide.h
class Divide : public SubExpression
{
public:
//define the default construtor
Divide(Expression* left, Expression* right) : SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//divide the value of left and value of the right
//and return the value.
return left->evaluate() / right->evaluate();
}
2. };
expression.h
// Expression
class Expression
{
public:
//declare a virtual function evaluate()
virtual int evaluate() = 0;
};
literal.h
//Operand
class Literal : public Operand
{
public:
//define the construtor
Literal(int value)
{
this->value = value;
}
//define the function evaluate()
//returns the value
int evaluate()
{
return value;
}
private:
int value;
};
minus.h
//define the class Minus subclass of the SubExpression
class Minus : public SubExpression
{
public:
//define the default construtor
3. Minus(Expression* left, Expression* right) : SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//subtract the value of right from the value of the left
//and return the value.
return left->evaluate() - right->evaluate();
}
};
module.cpp
#include
#include
#include
#include
#include
using namespace std;
#include "expression.h"
#include "subexpression.h"
#include "symboltable.h"
#include "parse.h"
//create an object of SymbolTable
SymbolTable symbolTable;
//prototype of the function
void parseAssignments(stringstream& in);
//define main function
int main()
{
// declare the variables
Expression* expression;
char paren, comma;
string line;
// create an input file stream
ifstream fin("input.txt");
4. // check, if the file is not opened
//then display a error message
if (!fin.is_open())
perror("error while opening file");
//use a loop, to read the content from the file
while (getline(fin, line))
{
symbolTable.init();
if (!fin)
break;
stringstream in(line, ios_base::in);
in >> paren;
cout << line << " ";
expression = SubExpression::parse(in);
in >> comma;
//call the function
parseAssignments(in);
//Display the result
int result = expression->evaluate();
cout << "Value = " << result << endl;
}
system("pause");
return 0;
}
//definition of the function parseAssignments()
void parseAssignments(stringstream& in)
{
char assignop, delimiter;
string variable;
int value;
symbolTable.init();
do
{
variable = parseName(in);
in >> ws >> assignop >> value >> delimiter;
symbolTable.insert(variable, value);
5. }
while (delimiter == ',');
}
operand.cpp
#include
#include
#include
#include
using namespace std;
#include "expression.h"
#include "subexpression.h"
#include "operand.h"
#include "variable.h"
#include "literal.h"
#include "parse.h"
#include
//definition of the function parse()
Expression* Operand::parse(stringstream& in)
{
char paren;
double value;
in >> ws;
if (isdigit(in.peek()))
{
in >> value;
Expression* literal = new Literal(value);
return literal;
}
if (in.peek() == '(')
{
in >> paren;
return SubExpression::parse(in);
}
else
6. return new Variable(parseName(in));
return 0;
}
operand.h
//define the class Operand subclass of the Expression
class Operand : public Expression
{
public:
//declare a static function parse()
static Expression* parse(stringstream& in);
};
parse.cpp
#include
#include
#include
#include
using namespace std;
#include "parse.h"
//definition of the function parseName()
string parseName(stringstream &in)
{
char alnum;
string name = "";
in >> ws;
while (isalnum(in.peek()))
{
in >> alnum;
name += alnum;
}
return name;
}
parse.h
#include
7. #include
//declare a function parseName()
string parseName(stringstream &in);
plus.h
//define the class Plus subclass of the SubExpression
class Plus: public SubExpression
{
public:
//define the default construtor
Plus(Expression* left, Expression* right): SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//adds the value of left and value of the right
//and return the value.
return left->evaluate() + right->evaluate();
}
};
subexpression.cpp
subexpression.cpp
#include
using namespace std;
#include "expression.h"
#include "subexpression.h"
#include "operand.h"
#include "plus.h"
#include "minus.h"
#include "times.h"
#include "divide.h"
#include
//define the constructor
8. SubExpression::SubExpression(Expression* left, Expression* right)
{
this->left = left;
this->right = right;
}
//definition of the class parse()
Expression* SubExpression::parse(stringstream& in)
{
Expression* left;
Expression* right;
char operation, paren;
//read the Operand
left = Operand::parse(in);
//read the operation
in >> operation;
//read the Operand
right = Operand::parse(in);
//read the paren
in >> paren;
switch (operation)
{
case '+':
return new Plus(left, right);
case '-':
return new Minus(left, right);
case '*':
return new Times(left, right);
case '/':
return new Divide(left, right);
}
system("pause");
return 0;
}
subexpression.h
//define the class SubExpression subclass of the Expression
9. class SubExpression : public Expression
{
public:
//constructor
SubExpression(Expression* left, Expression* right);
//declare a static function parse()
static Expression* parse(stringstream& in);
protected:
//declare the variables
Expression* left;
Expression* right;
};
symboltable.cpp
#include
#include
using namespace std;
#include "symboltable.h"
//definition of the function insert()
void SymbolTable::insert(string variable, int value)
{
//push the symbol in to the vector
const Symbol& symbol = Symbol(variable, value);
elements.push_back(symbol);
}
//definition of the function lookUp()
int SymbolTable::lookUp(string variable) const
{
//search in the vector and return the value.
for (int i = 0; i < elements.size(); i++)
if (elements[i].variable == variable)
return elements[i].value;
return -1;
}
void SymbolTable::init()
{
10. elements.clear();
}
symboltable.h
//define the class SubExpression
class SymbolTable
{
public:
//constructor
SymbolTable() {}
//declare the function
void insert(string variable, int value);
int lookUp(string variable) const;
void init();
private:
//define the structure Symbol
struct Symbol
{
Symbol(string variable, int value)
{
this->variable = variable;
this->value = value;
}
string variable;
int value;
};
//create a vector of type Symbol
vector elements;
};
times.h
//define the class Minus subclass of the SubExpression
class Times : public SubExpression
{
public:
//define the default construtor
11. Times(Expression* left, Expression* right) : SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//multiple the value of right and value of the left
//and return the value.
return left->evaluate() * right->evaluate();
}
};
variable.cpp
#include
#include
using namespace std;
#include "expression.h"
#include "operand.h"
#include "variable.h"
#include "symboltable.h"
//create an object of SymbolTable
extern SymbolTable symbolTable;
//definition of the function evaluate()
int Variable::evaluate()
{
//return the name from the symbolTable
return symbolTable.lookUp(name);
}
variable.h
#include
#include
using namespace std;
//define the class Variable subclass of the Operand
class Variable : public Operand
{
12. public:
//define the construtor
Variable(string name)
{
this->name = name;
}
//define the function evaluate()
int Variable::evaluate();
private:
string name;
};
input.txt (file)
((a + 4) ~), a = 3;
((x * 2.6) + (y - 3)), x = 1.5, y = 6;
(( 7 / z_1) + (z_1 ^ 2)), z_1 = 2;
((6 % b) < 5), b = 4;
(c > d), c = 9, d = 7;
(e & 8), e = 5;
(f ? 1 2), f = 0;
(g # 1 2 3), g = 2;
(tt + ss), tt = 2;
(aa + 1), aa = 1, aa = 2;
The statements of that expression language consist of an arithmetic expression followed by a list
of assignments. Assignments are separated from the expression and each other by commas. A
semicolon terminates the expression. The arithmetic expressions are fully parenthesized infix
expressions containing integer literals and variables. The syntax of a single input file line is
described grammar below: statement expression ', ' assignments ' ' expression ' (' operand
operator operand ') ' operator '+' I '-' operand literal | variable | expression assignments
assignments ', ' assignment | assignment assignment variable '=' literal statement expression ', '
assignments ' ; ' expression ' (' operand operator operand ') ' operator '+' | '-' operand literal |
variable | expression assignments assignments ' ' assignment | assignment assignment variable
'=' literal In the above grammar, terminal symbols are upper case names or character literals
shown in blue and nonterminal symbols are lower case names shown in red. EBNF
metacharacters are shown in black. Tokens can be separated by any number of spaces. Tokens
can be separated by any number of spaces. Variable names begin with an alphabetic character,
13. followed by any number of alphanumeric characters. Variable names are case sensitive. The
regular expressions defining the variables and literal tokens are the following:
variableliteral[azAZ][azAZ09][09]+ The program reads in the arithmetic expression and encodes
the expression as a binary tree. After the expression has been read in, the variable assignments
are read in and the variables and their values of the variables are placed into the symbol table.
Finally the expression is evaluated recursively. Your first task is to modify the program so that it
will parse additional types of expressions defined by the expanded grammar shown below with
the additions to the grammar highlighted in yellow: statement expression ',' assignments ' ;'
expression '(' ') ' expressions unary_expression | binary_expression | ternary_expression |
quaternary_expression I operand unary_expression expression ' ' binary_expression expression
binary_operator expression ternary_expression expression '?' expression expression
quaternary_expression expression '#' expression expression expression operand literal |
variable | expression assignments assignments ',' assignment | assignment assignment variable
'=' literal The semantics of the additional binary arithmetic operators are as follows: *
Multiplication / Division Remainder Exponentiation Although two of the three additional
binary operators are customarily relational operators in most languages, that is not true in this
language. The semantics of all three of those operators are as follows: < Minimum (Evaluates to
the minimum of the left and right operand) > Maximum (Evaluates to the maximum of the left
and right operand) & Average (Evaluates to the average of the left and right operand) The single
unary operator is the negation operator. Unlike the unary minus in most languages, it is a postfix
operator rather than a prefix one. The single ternary operator? is the conditional expression
operator. Unlike the conditional expression operator in C++ and Java, no colon separates the
second and third operands. This expression is evaluated as follows. If the expression to the left of
the operator ? is not 0 , the value of the expression is the value of the first expression after the
operator ?. If it is 0 , the value of the expression is the value of the second expression after the
operator? The single quaternary operator # is a variation of the typical conditional expression
operator. Like the ternary conditional expression operator, the remaining three operands are
delimited only by whitespace. This expression is evaluated as follows. If the expression to the
left of the operator # is less than 0 , the value of the expression is the value of the first
expression after the operator #. If it is equal to 0 , the value of the expression is the value of the
second expression after the operator #. If it is greater than 0 , the value of the expression is the
value of the third expression after the operator #.
The second task is to modifier the variable token so that underscores are permitted in all but the
first character and modify the literal token so that it accepts unsigned floating point literals.
14. Assignments also should be modified to allow assignment to values that are should also floating
point rather than just integers. The final task is to make the following modifications: - The
symbol table should be initialized before each statement is evaluated, so that variables that are
reused do not contain the value from a previous statement - Statements containing uninitialized
variables should be reported as an error - A variable initialized more than once in a statement
should be reported as an error (Creating an exception class to accommodate this error and the
previous one is the recommended approach) You may assume that all input is syntactically
correct. No checks for syntax errors is required. Each new class must be in a separate.h and.cpp
pair of files. If all the functions in a class are one line functions, they can be implemented inline
in .h file and the .cpp file can be omitted.