In: Computer Science
3 Design
3.1 Token Class
The Token type, which is an enum type and used in the Token class, is defined as follows:
enum Token_type {ID, INT, OP, EQ, OpenBrace, CloseBrace, INVALID};
If string s, passed in to the constructor or set method, is an identifier then the token type is ID; is a nonnegative integer then the token type is INT; is one of +, -, *, / then the token type is OP; is = then the token type is EQ; is (, open parenthesis, then the token type is OpenBrace; is ), close parenthesis, then the token type is CloseBrace; is none of the above then the token type is INVALID. The constructor and set method are required to figure out the type of a token string.
Token class is used to store a “token”, which has three members and a few member functions. The members are:
type This field stores the type of the token. Its type is Token type whose definition is given earlier.
token This field stores the token. Its type is string.
priority This field stores the priority of the token when token is
an operator
or a parenthesis. Its type is int. The member functions are:
Token() This default constructor initializes type to INVALID, token to empty string, and priority to -1.
Token(string s) This constructor takes in a string and treats it as a token. It sets the type and token member accordingly. For the current project, it sets the priority member to -1.
void set(string s) This method takes in a string and treats it as a token. It sets the members based on the new token s. Again, for the current project, it sets the priority member to -1.
2
int value() const This method returns the value associated with the token when token type is integer or identifier. In this assignment, if the type is INT, the integer represented as a string stored in token member should be converted to int and returned; if the type is ID, it returns -1; for all other types, it returns -2.
In the future assignment, we will be able to process assignment statement such as x=5 and a symbol table is used to associate x with 5. In this case, for token x, the function returns 5.
void display() const This method outputs the values of the token members in three lines. Each line begins with the member name, followed by “=”, followed by the value. This method is mainly for debugging use. For example, if token string is a12, we have:
type = ID token = a12 (value is -1) priority = -1
Token type get type() const Getter for type member. string get
token() const Getter for token member.
int get priority() const Getter for priority member.
Typically during the tokenizing process of the input string, we get a sequence of characters stored in a string, which is a token. We then use Token class via its constructor or set method to figure out if the token is valid or not and what type of token it is and so on. That is perhaps the most challenging programming (algorithmic) task for the implementation of the Token class. Since an expression is really a sequence of tokens in an abstract sense, the Token class is used by the Expression class to be designed next.
Since none of the member of the Token class involves pointer type and mem- ory allocation, the default copy constructor and assignment operator provided by the compiler should work just fine. We do not need to implement them.
3.2 Expression Class
The Exp type type, which is an enum type and used in the Expression class, is defined as follows:
enum Exp_type {ASSIGNMENT, ARITHMETIC, ILLEGAL};
For the current assignment, we are not required to figure out the type of an expression. We will do that in a later assignment. For the current project, we treat an expression in two ways: 1) as a string and 2) as a sequence of tokens (Token objects stored in a vector) obtained from the string.
Expression class is used to store an “expression”, which has five members and a few member functions. The members are:
3
original This field stores the original or not yet processed “expression”. Its type is string.
tokenized This field stores the expression as a sequence of tokens. Its type is vector.
postfix This field stores the expression as a sequence of tokens in postfix nota- tion provided the expression has arithmetic type. Its type is vector. This member is not used for the current homework assignment but will be used for the last assignment. The set method or con- structors of this assignment should leave it as an empty vector, that is to do nothing.
valid This field indicates whether the expression is a valid expression (no syntax error). Its type is bool. It is not used for the current homework assignment but will be used for the last assignment. The set method or constructors of this assignment should simply set it to false.
type This field indicates whether the type of the expression is ASSIGNMENT or ARITHMETIC expression or ILLEGAL. Its type is Exp type. It is not used for the current homework assignment but will be used for the last assignment. The set method or constructors of this assignment should simply set it to ILLEGAL.
The member functions are:
Expression() This default constructor initializes all fields to empty or false or ILLEGAL.
Expression(const string& s) This constructor takes in a string and treats it as an expression. It tokenizes the input string and sets the original and tokenized members accordingly. And it sets the other members based on the description given earlier (refer to each member description).
void set(const string& s) This method takes in a string and treats it as an expression. It tokenizes the input string and sets the original and tok- enized members accordingly. And it sets the other members based on the description given earlier.
void display() const This method output the values of the expression fields, one field per line. This method is mainly for debugging use.
original=a12=1?ab + -a0123c(a+123)*(ab-(3+4 )) tokenized =
a12;=;1?ab;+;-;a;0123;c;(;a;+;12;3;);*;(;ab;-;(;3;+;4;);); number
of tokens = 24
postfix =
valid = false type = ILLEGAL
4
string get original() const Getter for original member.
vector get tokenized() const Getter for tokenized member.
other methods There are other methods such as to evaluate the expression, to transform the expression, and getters for other fields such as postfix, valid, or type. These methods will be needed for the last assignment. Since we have not studied the related concepts and algorithms, these member functions are omitted.
When we receive a string (maybe from a line of input or a hard coded value within the program), which would be an expression, we use Expression class to figure out if the expression is legal or not and what its type is and so on (use either the non default constructor or set method, and pass the string as its argument).
In order to do the above, the string (perhaps a line of input from the user) gets tokenized first by the Expression class via its constructor or set method. That is perhaps the most challenging programming (algorithmic) task for the current implementation of the Expression class.
Since none of the member of the Expression class involves pointer type and memory allocation, the default copy constructor and assignment operator pro- vided by the compiler should work just fine. We do not need to implement them.
4 Implementation
Please note the similarity between the constructor that takes a string parameter and the set method in Token class. We could implement the set method first. Then the constructor calls the set method to accomplish its tasks. The same can be said for the similarity between the non default constructor and set method in Expression class.
You should implement and test the Token class first. Then use it in the development of the Expresion class. The most challenging method to implement (develop the code for) is the set method of the Expression class. We need to figure out the right algorithm to tokenize. One of the reasons is that we cannot simply use space (a blank character) as a delimiter to tokenize. For instance, in (2+3)*4, we have 7 valid tokens. They are (, 2, +, 3, ), *, 4 and no space betweenthem. Butifitisgivenas( 2 + 3 ) * 4,wecouldusespace. Our method should work for any possible combination of spaces and tokens. You might first assume space is used to separate each token including special tokens and develop a solution. Then consider if you might add space to the given string to use your with space as delimiter solution earlier. This approach is perhaps less efficient than those algorithms that process the string once because it processes a string twice and might double its length. However, it is acceptable for this assignment.
5
For those students who would like a challenge, you might develop an efficient algorithm that tokenizes the string with one pass through the given string.
Token class implementation has .h and .cpp files and the same is true for Expression class. The homework3.cpp file contains the code for testing of both classes.
5 Test and evaluation
Have a main program to test the Token class by sending the constructor and set method many different “tokens” and display the results to see if they are correct or not. You may want to be creative and cover a wide range of possible “tokens” in your testing. Similarly, test the Expression class by sending the constructor and set method many different “expressions” and display the results to see if they are correct or not. You may want to be creative and cover a wide range of possible “expressions” in your testing.
main.cpp
#include <cstdlib>
#include <iostream>
#include <string>
#include <cstring>
#include "Expression.h"
#include "Token.h"
using namespace std;
//Variables
char action;
string in;
Expression input;
//FUNCTIONS USED BY MAIN
//Tests Input From User
bool inputTest(string testStr)
{
input.set(testStr);
if(input.get_valid() == false)
{
cout<<testStr<<" <-invalid input"<<endl;
cout<<"input:";
return false;
}
return true;
}
//Tests Action From User
bool actionSwitchTest(char trigger)
{
action = tolower(trigger);
switch(action)
{
case '=':
input.display_eval();break;
case '>':
input.display_prefix();break;
case '<':
input.display_postfix();break;
case 'f':
input.display_paren();break;
case 'q':
break;
case'c':
break;
case's':
break;
default:
cout<<trigger<<" <-invalid
action"<<endl;
cout<<"action:";
return false;
break;
}
return true;
}
//Prompt for Input
void promptIn()
{
if(action == 'c'){
string temp = in;
cout<<"input:";
do
{
getline(cin,in);
temp+=in;
in = temp;
}while(!inputTest(in));
}
else
{
in = "";
cout<<"input:";
do
{
getline(cin,in);
}while(!inputTest(in));
}
}
//Prompt for Action
void promptAct()
{
string act;
cout<<"action:";
do
{
getline(cin,act);
}while(!actionSwitchTest(act[0]));
}
//MAIN - The Composer of the Program
int main()
{
cout<<"=== expression evaluation program
starts ==="<<endl;
//Error Check and Worst Case Scenario
Reboot
try
{
do
{
promptIn();
do
{
promptAct();
}while(action!='c'&&action!='s'&&action!='q');
}while(action!='q');
cout<<"===
expression evaluation program ends ==="<<endl;
}
catch(...)
{
cout<<"===
expression evaluation program ends ==="<<endl;
cout<<endl
<< " ~An unexpected error
occurred~"<<endl<<"Check input for syntax errors before
Return"<<endl<<endl<<"\t ...Restarting
program..."<<endl;
main();
}
return 0;
}
=======================================================================================================
Expression.cpp
#include "Token.h"
#include "Expression.h"
using namespace std;
//TYPE DECLORATION
enum Exp_type {assignment, arithmetic, illegal};
//CONSTRUCTORS
//Default Constructor
Expression::Expression()
{
original = "";
valid = false;
type = illegal;
}
//Constructor for sending string Expression
Expression::Expression(const string& s)
{
original = s;
this->set(s);
}
//Copy Constructor
Expression::Expression(const Expression& orig)
{
valid = orig.valid;
runnable = orig.runnable;
type = orig.type;
eval = orig.eval;
original = orig.original;
parenthisized = orig.parenthisized;
prefix = orig.prefix;
tokenized = orig.tokenized;
postfix = orig.postfix;
expressionized = orig.expressionized;
assignments = orig.assignments;
}
//FUNCTIONS USED BY CONSTRUCTORS
//sets the whole expression
void Expression::set(const string& s)
{
original = "";
parenthisized.clear();
prefix.clear();
next.clear();
tokenized.clear();
postfix.clear();
expressionized.clear();
assignments.clear();
valid = true;
//chunk by ';'
valid = splitSemi(s);
for(int i = 0; i < next.size() &&
valid == true; i++)
{
//make each chunk an
expression and push it into expression vector
Expression chunk;
chunk.setNext(next[i]);
expressionized.push_back(chunk);
//if its an assignment
then push it into assignment vector for evaluation
if(chunk.type ==
assignment)
assignments.push_back(chunk);
else if(chunk.type ==
illegal)
{
valid = false;
}
}
//if the entire expression is valid then loop
through the chunks that are arithmetic and calculate them (sending
the assignments as a parameter)
if(valid)
{
for(int i = 0;
i<expressionized.size(); i++)
{
if(expressionized[i].get_type() == arithmetic)
expressionized[i].calc(assignments);
}
}
}
//sets the chunk
void Expression::setNext(const string& s)
{
//set chunk's original
original = s.substr(0, s.length()-1);
//tokenize chunk
tokenize(s);
//check chunk for syntax errors
syntaxCheck();
//if chunk is arithmetic then
postfix/prefix/parenthesize chunk
if(type == arithmetic)
{
postfixToken();
prefixToken();
paren();
}
//reset evaluation for chunk
eval = 0;
}
//FUNCTIONS USED TO SET PROPERTIES
//splits string by ';' and checks for missing ';'
bool Expression::splitSemi(const string& s)
{
int m = 0;
string build = "";
bool flag = false;
for(int i = 0; i < s.length(); i++)
{
flag = false;
if(s[i] == ';')
{
flag = true;
build = s.substr(m,i-m+1);
m=i+1;
if(build != "" and build != " ")
next.push_back(build);
}
}
if(!flag)
cout<<"error:
missing ';'"<<endl;
return flag;
}
//tokenizes sent string
void Expression::tokenize(const string& s)
{
string build="";
int k=0;
int j=0;
for(int i = 0; i<s.length() &&
s[i] != ';'; i++)
{
k++;
if(s[i] == '(' || s[i] == ')' || s[i] == '*' || s[i] == '/' || s[i]
== '+' || s[i] == '-' || s[i] == '=' || s[i]==' ')
{
build = s.substr(j, k-1);
if(build != "" and build != " ")
tokenized.push_back(Token(build));
build = s.substr(i, 1);
if(build != "" and build != " ")
{
tokenized.push_back(Token(build));
}
j=i+1;
k=0;
}
}
build =
s.substr(j,k);
if(build != " " and
build!="")
tokenized.push_back(Token(build));
}
//Sorts the tokens in postfix order for the expression its run
on
void Expression::postfixToken()
{
stack<Token> ops;
for(int i = 0; i <
tokenized.size();i++)
{
if(tokenized[i].get_type() == Token::ID || tokenized[i].get_type()
== Token::INT)
postfix.push_back(tokenized[i]);
else
if(tokenized[i].get_type() == Token::OpenBrace)
ops.push(tokenized[i]);
else
if(tokenized[i].get_type() == Token::CloseBrace)
{
while(ops.top().get_type() != Token::OpenBrace)
{
postfix.push_back(ops.top());
ops.pop();
}
ops.pop();
}
else
{
while(!ops.empty() && ops.top().get_priority() >=
tokenized[i].get_priority())
{
postfix.push_back(ops.top());
ops.pop();
}
ops.push(tokenized[i]);
}
}
while(!ops.empty())
{
postfix.push_back(ops.top());
ops.pop();
}
}
//Sorts the tokens into a string in prefix order for the expression
its run on
void Expression::prefixToken()
{
stack<string> s;
for(int i = 0; i < postfix.size(); i++)
{
if(postfix[i].get_type()
== Token::OP)
{
string op1 = s.top();
s.pop();
string op2 = s.top();
s.pop();
string temp = postfix[i].get_token() + " " + op2 +" " + op1;
s.push(temp);
}
else
{
string temp = postfix[i].get_token();
char tempt = temp[0];
s.push(string(1, tempt));
}
}
prefix = s.top();
}
//checks expression for syntax errors
bool Expression::syntaxCheck()
{
enum States {expect_operand, expect_operator,
done};
bool eqtrue = false; // set to true if = is
encountered
States state = expect_operand; // initial state
value
int pcount = 0; // for checking braces
valid = true; // a field in Expression
class
for(int i = 0; i<tokenized.size() &&
state != done; i++)
{
Token t =
tokenized[i];
switch(state)
{
case expect_operand:
if (t.get_type() == Token::OpenBrace)
pcount++;
else if(t.get_type() == Token::INT || t.get_type() ==
Token::ID)
state = expect_operator;
else
{
valid = false;
state = done;
}
break;
case expect_operator:
if(t.get_type() == Token::CloseBrace)
{
pcount--;
if(pcount<0)
{
valid = false;
state = done;
}
}
else if(t.get_type() == Token::EQ)
{
eqtrue = true;
state = expect_operand;
}
else if(t.get_type() == Token::OP)
state = expect_operand;
else
{
valid = false;
state = done;
}
break;
default:
break;
}
}
if(pcount != 0)
valid = false;
if(state == expect_operand)
valid = false;
if(valid)
{
if(eqtrue)
{
if(tokenized.size()==3 &&
tokenized[0].get_type()==Token::ID &&
tokenized[2].get_type()==Token::INT)
type = assignment;
else
valid = false;
}
else
type = arithmetic;
}
if(!valid||tokenized.size()<2)
type = illegal;
}
//fully parenthesizes expression
void Expression::paren()
{
stack<string> stack;
for(int i = 0; i < postfix.size();i++)
{
bool flag = false;
string testy =
postfix[i].get_token();
char test =
testy[0];
if(postfix[i].get_type()
== Token::ID ||postfix[i].get_type() == Token::INT)
stack.push(testy);
else
{
string first = stack.top();
stack.pop();
string second = stack.top();
stack.pop();
string temp = "";
switch(test)
{
case '+':
temp = "("+second+"+"+first+")";
stack.push(temp);
break;
case '-':
temp = "("+second+"-"+first+")";
stack.push(temp);
break;
case '*':
temp = "("+second+"*"+first+")";
stack.push(temp);
break;
case '/':
temp = "("+second+"/"+first+")";
stack.push(temp);
break;
}
}
}
parenthisized = stack.top();
}
//fully evaluates all arithmetic types and error checks for missing
assignments
void Expression::calc(vector<Expression> assign)
{
vector<string> postCheckCopy;
stack<string> notfound;
runnable = true;
for(int i = 0; i < postfix.size();i++)
{
if(postfix[i].get_type()
== Token::ID)
{
bool found = false;
for(int k = 0; k < assign.size(); k++)
{
string firsty;
string inty;
for(int j = 0; j <assign[k].original.size(); j++)
{
string st1(1,assign[k].original[j]);
char tes = st1[0];
if(isdigit(tes))
inty +=st1;
else if(isalpha(tes))
firsty =st1;
}
if(firsty==postfix[i].get_token())
{
postCheckCopy.push_back(inty);
found = true;
}
}
if(!found)
postCheckCopy.push_back(postfix[i].get_token());
}else
postCheckCopy.push_back(postfix[i].get_token());
}
for(int i = 0; i <
postCheckCopy.size();i++)
{
string testy =
postCheckCopy[i];
char test =
testy[0];
if(isalpha(test))
{
runnable = false;
notfound.push(testy);
}
}
stack<int> stack;
for(int i = 0; i < postCheckCopy.size()
&& runnable;i++)
{
string testy =
postCheckCopy[i];
char test =
testy[0];
if(isdigit(test))
stack.push(stoi(testy));
else
{
int first = stack.top();
stack.pop();
int second = stack.top();
stack.pop();
switch(test)
{
case '+': stack.push(second + first);break;
case '-': stack.push(second - first);break;
case '*': stack.push(second * first);break;
case '/': stack.push(second /
first);break;
}
}
}
if(!runnable)
{
cout<<"Cannot
evaluate assignments need for variables ";
while(!notfound.empty())
{
cout<<notfound.top()<<"; ";
notfound.pop();
}
cout<<endl;
}else
eval =
stack.top();
}
//DISPLAY FUNCTIONS:
//displays postfix for all chunks of expression
void Expression::display_postfix() const
{
for(int i = 0; i < expressionized.size();
i++)
{
if(expressionized[i].get_type() == arithmetic)
{
cout<<"postfix of "<< expressionized[i].original
<< " is: ";
for(int k = 0; k<expressionized[i].postfix.size(); k++ )
cout<<expressionized[i].postfix[k].get_token()<<"
";
cout<<endl;
}
else
if(expressionized[i].get_type() == assignment)
cout<<"no prefix of
"<<expressionized[i].original<<" which is not an
arithmetic expression, but assignment."<<endl;
}
}
//displays prefix for all chunks of expression
void Expression::display_prefix() const
{
for(int i = 0; i < expressionized.size();
i++)
{
if(expressionized[i].get_type() == arithmetic)
cout<<"prefix of "<< expressionized[i].original
<< " is: "<<expressionized[i].prefix<<endl;
else
if(expressionized[i].get_type() == assignment)
cout<<"no prefix of
"<<expressionized[i].original<<" which is not an
arithmetic expression, but assignment."<<endl;
}
}
void Expression::display_paren() const
{
for(int i = 0; i < expressionized.size();
i++)
{
if(expressionized[i].get_type() == arithmetic)
cout<<"fully parenthesizing
"<<expressionized[i].original << " results:
"<<expressionized[i].parenthisized<<endl;
else
if(expressionized[i].get_type() == assignment)
cout<<"no fully parenthesizing of
"<<expressionized[i].original<<" which is not an
arithmetic expression, but assignment."<<endl;
}
}
void Expression::display_eval() const
{
for(int i = 0; i < expressionized.size();
i++)
{
if(expressionized[i].get_type() == assignment)
cout<<"cannot evaluate
"<<expressionized[i].original<<" which is not an
arithmetic expression, but assignment."<<endl;
else
if(!expressionized[i].runnable)
cout<<expressionized[i].original << " = ? - More
Assignments Needed, Cannot Evaluate"<<endl;
else
if(expressionized[i].get_type() == arithmetic)
cout<<expressionized[i].original << " =
"<<expressionized[i].eval<<endl;
}
}
//ACCESOR
Expression::Exp_type Expression::get_type() const
{
return type;
}
bool Expression::get_valid() const
{
return valid;
}
//DECONSTRUCTOR
Expression::~Expression(){
original.clear();
parenthisized.clear();
prefix.clear();
next.clear();
tokenized.clear();
postfix.clear();
expressionized.clear();
assignments.clear();
}
===========================================================================
Expression.h
#ifndef EXPRESSION_H
#define EXPRESSION_H
#include "Token.h"
#include "Expression.h"
#include <cstdlib>
#include <string>
#include <cstring>
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
class Expression
{
public:
enum Exp_type {assignment, arithmetic,
illegal};
Expression();
Expression(const string& s);
Expression(const Expression& orig);
void set(const string& s);
void display_postfix() const;
void display_prefix() const;
void display_paren() const;
void display_eval() const;
Exp_type get_type() const;
bool get_valid() const;
~Expression();
private:
void setNext(const string& s);
bool splitSemi(const string& s);
void tokenize(const string& s);
void postfixToken();
void prefixToken();
bool syntaxCheck();
void paren();
void calc(vector<Expression>
assignments);
//Properties
Exp_type type;
int eval;
bool valid;
bool runnable;
string original;
string parenthisized;
string prefix;
vector<string> next;
vector<Token> tokenized;
vector<Token> postfix;
vector<Expression> expressionized;
vector<Expression> assignments;
};
#endif /* EXPRESSION_H */
============================================================================================
Token.cpp
#include "Token.h"
#include <cstdlib>
#include <string>
#include <cstring>
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
enum Token_type{ID, INT, OP, EQ, OpenBrace,
CloseBrace, INVALID};
Token::Token()
{
type = INVALID;
token = "";
priority = -1;
}
Token::Token(const Token& orig)
{
token =orig.token;
type = orig.type;
priority =
orig.priority;
}
Token::Token(string s)
{
token = s;
this->set(s);
}
Token::~Token(){
}
void Token::set(string s)
{
token = s;
bool frontIsLetter =
false;
bool buildID =
false;
bool buildINT =
false;
bool frontIsNumber =
false;
bool frontIsZero =
false;
int buildCount =
0;
if(isalpha(s.front()))
frontIsLetter = true;
if(isdigit(s.front()))
frontIsNumber = true;
if(s.front()=='0')
frontIsZero = true;
if(s.size()==1)
{
char t =
s[0];
if(t=='+'||t=='-')
{
type = OP;
priority = 1;
}
else if(t=='*'||t=='/')
{
type = OP;
priority = 2;
}
else if(t=='=')
{
type = EQ;
priority = -1;
}
else if(t=='(')
{
priority = 0;
type = OpenBrace;
}
else if(t==')')
{
type = CloseBrace;
priority = -1;
}
else if(isdigit(t))
{
type = INT;
priority = -1;
}
else if(isalpha(t))
{
type = ID;
priority = -1;
}
else
{
type = INVALID;
priority = -1;
}
}
else
{
for(int i=0; i<s.size(); i++)
{
char t = s[i];
if(frontIsLetter)
{
if(isalnum(t) and t!=' ')
{
buildID = true;
buildCount++;
}
else
buildID = false;
}
else if(frontIsNumber && !frontIsZero)
{
if(isdigit(t))
buildINT = true;
else
buildINT = false;
}
else
break;
}
if(buildID&&buildCount == s.size())
type = ID;
else if(buildINT)
type= INT;
else
type = INVALID;
}
}
int Token::value() const
{
int ret = -2;
if(type == INT)
ret = stoi(token);
else if(type ==
ID)
ret = -1;
return ret;
}
void Token::display() const
{
cout<<"type =
";
if(type==0)
cout<<"ID"<<endl;
if(type==1)
cout<<"INT"<<endl;
if(type==2)
cout<<"OP"<<endl;
if(type==3)
cout<<"EQ"<<endl;
if(type==4)
cout<<"OpenBrace"<<endl;
if(type==5)
cout<<"CloseBrace"<<endl;
if(type==6)
cout<<"INVALID"<<endl;
cout<<"token =
"<< token<< " (value is " <<value()<<
")"<<endl;
cout<<"priority =
"<< priority<<endl<<endl;
}
//Accessors
Token::Token_type Token::get_type() const
{
return type;
}
string Token::get_token() const
{
return token;
}
int Token::get_priority() const
{
return priority;
}
============================================================================================
Token.h
#ifndef TOKEN_H
#define TOKEN_H
#include "Token.h"
#include <cstdlib>
#include <iostream>
#include <cstring>
using namespace std;
class Token
{
public:
Token();
Token(const Token& orig);
Token(string s);
~Token();
enum Token_type {ID, INT, OP, EQ, OpenBrace,
CloseBrace, INVALID};
void set(string s);
int value() const;
void display() const;
//Accessors
Token_type get_type() const;
string get_token() const;
int get_priority() const;
private:
Token_type type;
string token;
int priority;
};
#endif /* TOKEN_H */