Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Data Structure in C++ Parsing Page Ranges Here is my code below: pset.cc #includ

ID: 3839477 • Letter: D

Question

Data Structure in C++

Parsing Page Ranges

Here is my code below:

pset.cc

#include <iostream>
using std::cout;

struct pset {
virtual void evaluate() = 0;
};

struct pset_num : public pset {
pset_num (int value) {
v = value;
}

void evaluate() {
cout << v << ", ";
}

int v;
};

struct pset_range : public pset {
pset_range(int start, int end) {
s = start;
e = end;
}

void evaluate() {
for (int i = s; i <= e; i++) {
cout << i << ", ";
}

}

int s;
int e;
};

struct pset_r_odd : public pset {
pset_r_odd(int start, int end) {
s = start;
e = end;
}

void evaluate() {
for (int i = s; i <= e; i++) {
if (i % 2 == 1)
cout << i << ", ";
}
}

int s;
int e;

};

main.cc

#include "pset.cpp"
#include <vector>
#include <string>

using std::cin;
using std::vector;
using std::string;
using iter = vector<string>::iterator;


//checks to see if a string is a number
bool numbs(string s) {
return (s.at(0) >= '0' && s.at(0) <= '9');
}

//checks to see if a string is an operator "to" or "-" in this case
bool opps(string s) {
return (s == "to" || s == "-");
}

//checks to see if the string is a qualifier. "even" or "odd" in this case
bool is_qualifier(string s) {
return (s == "even" || s == "odd");
}

//function declarations
bool exprss(iter start, iter finish);
void parse_pset(iter start, iter finish);
vector<string> lex(string s);

//This is the global cariable where the regular expressions will get stored
//in the main loop, this expressions will be "evaluated" and printed out to
//the console
vector <pset*> ranges;

int main() {
string input;

while (true) {
//where the tokens will be stored after lexical analysis
vector<string> tokens;

cout << "> ";
std::getline(cin, input);
  
//storing the input as tokens
tokens = lex(input);

//printing out the tokens to the user
for (int i = 0; i < tokens.size(); i++)
cout << """ << tokens[i] << "", ";

cout << std::endl;
  
//checking to see if all the tokens in "tokens" vector are parseable
bool valid = exprss(tokens.begin(), tokens.end() -1);

if (valid) {
cout << "Valid!" << std::endl;
parse_pset(tokens.begin(), tokens.end() -1);
for (pset* exp : ranges) {
exp->evaluate();
}
ranges.clear();
  
} else {
cout << "Invalid input" << std::endl;
}
tokens.clear();
cout << std::endl;

}
}

/*
This function is a state machine that takes in an input string and divides
the string into tokens : space, numbers, words, operators.
*/
vector<string> lex(string s) {
const int SPACE = 0;
const int NUM = 1;
const int WORD = 2;
const int OP = 3;

int state = SPACE;
vector<string> words;
string word;

for (char c : s) {
if (state == SPACE) {
if (c == ' ' || c == ',')
continue;
else if (c >= '0' && c <= '9')
state = NUM;
else if (c >= 'a' && c <'z')
state = WORD;
else if (c == '-')
state = OP;
  
word.push_back(c);
}

else {
//Not in SPACE
int nstate = state;
if (c == ' ' || c == ',')
nstate = SPACE;
else if (c >= '0' && c <= '9')
nstate = NUM;
else if (c >= 'a' && c <= 'z')
nstate = WORD;
else if (c == '-')
nstate = OP;

if (nstate == SPACE) {
words.push_back(word);
word.clear();
state = SPACE;
continue;
}

if (nstate == state && state !=OP)
word.push_back(c);
else if (nstate != state || state == OP) {
words.push_back(word);
word.clear();
word.push_back(c);
}
  
state = nstate;
}

}

if (!word.empty())
words.push_back(word);

return words;
}


void parse_pset(iter start, iter finish) {

if (start > finish)
//if input is empty
return;
else if (start == finish) {
//if input is just one token. It has to be a number
if(numbs(*start))
ranges.push_back(new pset_num{ stoi(*start) });
} else {

//if the tokens follow the grammar <number><operator><number><modifier>
if (numbs(*start) && opps(*(start+1)) &&
numbs(*(start+2)) && is_qualifier(*(start+3))) {

if (*(start+3) == "odd") {
ranges.push_back(new pset_r_odd{stoi(*start),
stoi(*(start+2))});
  
//"recursive" call in order to keep looking through the input vector
parse_pset(start+4, finish);
}
else if (*(start+3) == "even") {
ranges.push_back(new pset_r_even{stoi(*start),
stoi(*(start+2))});

parse_pset(start+4, finish);
}
}
  
//if the tokens follow the grammar <number><operator><number>
else if (numbs(*start) && opps(*(start+1)) &&
numbs(*(start+2))) {
ranges.push_back(new pset_range{stoi(*start),stoi(*(start+2))});

parse_pset(start+3, finish);
}
  
//if the tokens follow the grammar <number><expression>+
else if (numbs(*start)){
ranges.push_back(new pset_num{ stoi(*start)});
  
parse_pset(start+1, finish);
}
}

return;
}

/*
This function goes through the token vector and makes sure
all the tokens make valid expressions.
*/
bool exprss(iter start, iter finish) {
if (start > finish)
return true;
else if (start == finish) {
if(numbs(*start))
return true;
else
return false;
}
else {
if (numbs(*start) && opps(*(start+1)) &&
numbs(*(start+2)) && is_qualifier(*(start+3))) {
return exprss(start+4, finish);
} else if (numbs(*start) && opps(*(start+1)) &&
numbs(*(start+2))) {
return exprss(start+3, finish);
} else if (numbs(*start)) {
return exprss(start+1, finish);
}
  
}

return false;
}

----------------------------------------------------------------------

2-5 should print 2,3,4,5, not 2, -, 5

Please fix my code

You know how when you go to print a document theres an option to print "pages In some applications its just two boxes, "from and "too. but other programs are more flexible, allowing you to write things like 1,2,4,5 1 to 10 1,3 5,8 1 10 odd and so forth. In this assignment. youre going to build an expression tree type and a parser for these "page set expressions The grammar of page sets Looking at the above. we can begin to form an idea of what a valid "page set expression looks like A comma-separated list with at least one item where each item is either a single page number or a range of pages where a range of pages is two page numbers. separated by either a dash or the word "to. and optionally followed by the words "odd" or "even (Printing only odd/even pages is useful for duplexing.) A grammar for this looks like this: pset range pset range pset range NUM range NUM to NUM range NUM to NUM qualifier to to to qualifier "odd" qualifier even The start symbol. as is our custom. is the first symbol defined: pset.

Explanation / Answer

pset.cc

#include <iostream>
using std::cout;

struct pset {
virtual void evaluate() = 0;
};

struct pset_num : public pset {
pset_num (int value) {
v = value;
}

void evaluate() {
cout << v << ", ";
}

int v;
};

struct pset_range : public pset {
pset_range(int start, int end) {
s = start;
e = end;
}

void evaluate() {
for (int i = s; i <= e; i++) {
cout << i << ", ";
}

}

int s;
int e;
};

struct pset_r_odd : public pset {
pset_r_odd(int start, int end) {
s = start;
e = end;
}

void evaluate() {
for (int i = s; i <= e; i++) {
if (i % 2 == 1)
cout << i << ", ";
}
}

int s;
int e;

};

main.cc

#include "pset.cpp"
#include <vector>
#include <string>

using std::cin;
using std::vector;
using std::string;
using iter = vector<string>::iterator;


//checks to see if a string is a number
bool numbs(string s) {
return (s.at(0) >= '0' && s.at(0) <= '9');
}

//checks to see if a string is an operator "to" or "-" in this case
bool opps(string s) {
return (s == "to" || s == "-");
}

//checks to see if the string is a qualifier. "even" or "odd" in this case
bool is_qualifier(string s) {
return (s == "even" || s == "odd");
}

//function declarations
bool exprss(iter start, iter finish);
void parse_pset(iter start, iter finish);
vector<string> lex(string s);

//This is the global cariable where the regular expressions will get stored
//in the main loop, this expressions will be "evaluated" and printed out to
//the console
vector <pset*> ranges;

int main() {
string input;

while (true) {
//where the tokens will be stored after lexical analysis
vector<string> tokens;

cout << "> ";
std::getline(cin, input);
  
//storing the input as tokens
tokens = lex(input);

//printing out the tokens to the user
for (int i = 0; i < tokens.size(); i++)
cout << """ << tokens[i] << "", ";

cout << std::endl;
  
//checking to see if all the tokens in "tokens" vector are parseable
bool valid = exprss(tokens.begin(), tokens.end() -1);

if (valid) {
cout << "Valid!" << std::endl;
parse_pset(tokens.begin(), tokens.end() -1);
for (pset* exp : ranges) {
exp->evaluate();
}
ranges.clear();
  
} else {
cout << "Invalid input" << std::endl;
}
tokens.clear();
cout << std::endl;

}
}

/*
This function is a state machine that takes in an input string and divides
the string into tokens : space, numbers, words, operators.
*/
vector<string> lex(string s) {
const int SPACE = 0;
const int NUM = 1;
const int WORD = 2;
const int OP = 3;

int state = SPACE;
vector<string> words;
string word;

for (char c : s) {
if (state == SPACE) {
if (c == ' ' || c == ',')
continue;
else if (c >= '0' && c <= '9')
state = NUM;
else if (c >= 'a' && c <'z')
state = WORD;
else if (c == '-')
state = OP;
  
word.push_back(c);
}

else {
//Not in SPACE
int nstate = state;
if (c == ' ' || c == ',')
nstate = SPACE;
else if (c >= '0' && c <= '9')
nstate = NUM;
else if (c >= 'a' && c <= 'z')
nstate = WORD;
else if (c == '-')
nstate = OP;

if (nstate == SPACE) {
words.push_back(word);
word.clear();
state = SPACE;
continue;
}

if (nstate == state && state !=OP)
word.push_back(c);
else if (nstate != state || state == OP) {
words.push_back(word);
word.clear();
word.push_back(c);
}
  
state = nstate;
}

}

if (!word.empty())
words.push_back(word);

return words;
}


void parse_pset(iter start, iter finish) {

if (start > finish)
//if input is empty
return;
else if (start == finish) {
//if input is just one token. It has to be a number
if(numbs(*start))
ranges.push_back(new pset_num{ stoi(*start) });
} else {

//if the tokens follow the grammar <number><operator><number><modifier>
if (numbs(*start) && opps(*(start+1)) &&
numbs(*(start+2)) && is_qualifier(*(start+3))) {

if (*(start+3) == "odd") {
ranges.push_back(new pset_r_odd{stoi(*start),
stoi(*(start+2))});
  
//"recursive" call in order to keep looking through the input vector
parse_pset(start+4, finish);
}
else if (*(start+3) == "even") {
ranges.push_back(new pset_r_even{stoi(*start),
stoi(*(start+2))});

parse_pset(start+4, finish);
}
}
  
//if the tokens follow the grammar <number><operator><number>
else if (numbs(*start) && opps(*(start+1)) &&
numbs(*(start+2))) {
ranges.push_back(new pset_range{stoi(*start),stoi(*(start+2))});

parse_pset(start+3, finish);
}
  
//if the tokens follow the grammar <number><expression>+
else if (numbs(*start)){
ranges.push_back(new pset_num{ stoi(*start)});
  
parse_pset(start+1, finish);
}
}

return;
}

/*
This function goes through the token vector and makes sure
all the tokens make valid expressions.
*/
bool exprss(iter start, iter finish) {
if (start > finish)
return true;
else if (start == finish) {
if(numbs(*start))
return true;
else
return false;
}
else {
if (numbs(*start) && opps(*(start+1)) &&
numbs(*(start+2)) && is_qualifier(*(start+3))) {
return exprss(start+4, finish);
} else if (numbs(*start) && opps(*(start+1)) &&
numbs(*(start+2))) {
return exprss(start+3, finish);
} else if (numbs(*start)) {
return exprss(start+1, finish);
}
  
}

return false;
}