Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

C++, Parsing Page Ranges, Please fix my code!! Hello there, I made a program for an expression tree type and a parser for page set

C++, Parsing Page Ranges, Please fix my code!!

Hello there, I made a program for an expression tree type and a parser for page set expressions.

Requirements are:

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.)

For example, it should do things like:

> 1,2,4,5 1,2,4,5 > 1 to 10 1,2,3,4,5,6,7,8,9,10 > 1,3 - 5,8 1, 3, 4, 5, 8 > 1 - 10 odd 1,3,5,7,9 

However, my program doesnt do

> 1 to 10.

> 1 - 10.

> 1 - 10 odd

but, it does

> 1, 2, 3, 1 - 10, 3 to 9 odd

the "to" and "-" command does not work when its used in the first sequence.

My instructor said,

"The problem is in your exprss function, when you do if (numbs(*start) && opps(*(start+1)) && numbs(*(start+2)) && is_qualifier(*(start+3))) { you haven't checked to make sure that finish >= start+3. I.e., there might not be four elements in the input sequence, in which case you'll read off the end."

But I still can't figure out how to fix my code.

If you think you can help me out with this, please copy the code below and fix the code.

======================================================

#include #include #include

using std::cin; using std::cout; using std::vector; using std::string; using it = vector::iterator;

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; };

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

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

int s; int e; };

//checks to see if a string is a number bool is_num(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 is_op(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 is_expr(it start, it finish); void parse_pset(it start, it finish); vector 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 ranges;

int main() { string input;

while (true) { //where the tokens will be stored after lexical analysis vector 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 = is_expr(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 lex(string s) { const int SPACE = 0; const int NUM = 1; const int WORD = 2; const int OP = 3;

int state = SPACE; vector words; string word;

for (char c : s) { if (state == SPACE) {

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 newstate = state; if (c == ' ' || c == ',') newstate = SPACE; else if (c >= '0' && c <= '9') newstate = NUM; else if (c >= 'a' && c <= 'z') newstate = WORD; else if (c == '-') newstate = OP;

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

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

state = newstate;

}

}

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

return words; }

void parse_pset(it start, it 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(is_num(*start)) ranges.push_back(new pset_num{ stoi(*start) }); } else {

//if the tokens follow the grammar if (is_num(*start) && is_op(*(start+1)) && is_num(*(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

else if (is_num(*start) && is_op(*(start+1)) && is_num(*(start+2))) { ranges.push_back(new pset_range{stoi(*start),stoi(*(start+2))});

parse_pset(start+3, finish); }

//if the tokens follow the grammar + else if (is_num(*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 is_expr(it start, it finish) { if (start > finish) return true; else if (start == finish) { if(is_num(*start)) return true; else return false; } else { if (is_num(*start) && is_op(*(start+1)) && is_num(*(start+2)) && is_qualifier(*(start+3))) { return is_expr(start+4, finish); } else if (is_num(*start) && is_op(*(start+1)) && is_num(*(start+2))) { return is_expr(start+3, finish); } else if (is_num(*start)) { return is_expr(start+1, finish); }

}

}

return false; }

======================================

trolls will be reported...

Thank you in advance!

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Modern Database Management

Authors: Jeff Hoffer, Ramesh Venkataraman, Heikki Topi

13th Edition Global Edition

1292263350, 978-1292263359

More Books

Students also viewed these Databases questions

Question

7. Discuss the implications of a skill-based pay plan for training.

Answered: 1 week ago

Question

4. Make recommendations on steps to take to melt the glass ceiling.

Answered: 1 week ago