Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Author: James Walter Erardi
- * University of Massachusetts Lowell
- *
- * James_Erardi@student.uml.edu
- * © UMass Lowell 2015
- *
- * Created on September 8, 2015, 10:15 AM
- * Edited on September 11, 2015, 4:06PM
- * Edited on September 22, 2015, 4:00PM
- * Edited on September 24, 2015, 4:33PM
- * Edited on September 25, 2015, 11:38AM
- * Edited on October 1st, 2015, 11:00AM
- */
- #include <cstdlib> //the netbeans version of stdlib
- #include <iostream> //required lib for input/output stream functions
- #include <cstring> //required lib for c-strings
- #include <string> //required lib for strings
- #include <fstream> //required lib for reading in files
- #include <vector> //required lib for STL vector
- #include <algorithm> //supplies a few useful algorithms
- #include "Element.h" //header file containing functions
- #include <stack> //required lib for STL stack
- #include "Attribute.h" //header file containing attribute functions
- using namespace std; //standard namespace operation scope, so we don't need to put std:: before everything
- //add a new child element
- void elements::addChild(elements* child){
- children.push_back(child);
- }
- /**
- * This function is used during debugging to display the parser state.
- * @param ps the parser state
- * Code provided by Professor Jesse M Heines
- */
- //void ShowState(ParserState ps) {
- // cout << "ParserState = ";
- // switch (ps) {
- // case UNKNOWN: cout << "UNKNOWN"; break;
- // case STARTING_DOCUMENT: cout << "STARTING_DOCUMENT"; break;
- // case DIRECTIVE: cout << "DIRECTIVE"; break;
- // case ELEMENT_OPENING_TAG: cout << "ELEMENT_OPENING_TAG"; break;
- // case ELEMENT_CONTENT: cout << "ELEMENT_CONTENT"; break;
- // case ELEMENT_NAME_AND_CONTENT: cout << "ELEMENT_CONTENT"; break;
- // case ELEMENT_CLOSING_TAG: cout << "ELEMENT_CLOSING_TAG"; break;
- // case SELF_CLOSING_TAG: cout << "SELF_CLOSING_TAG"; break;
- // case STARTING_COMMENT: cout << "STARTING_COMMENT"; break;
- // case IN_COMMENT: cout << "IN_COMMENT"; break;
- // case ENDING_COMMENT: cout << "ENDING_COMMENT"; break;
- // case ONE_LINE_COMMENT: cout << "ONE_LINE_COMMENT"; break;
- // case ERROR: cout << "ERROR"; break;
- // default: cout << "UNKNOWN"; break;
- // }
- // cout << endl;
- //}
- /*
- * printVector function takes in a vector and prints it using
- * string iterators.
- *
- */
- void printVector(vector<elements> vec)
- {
- vector<elements>::iterator it;
- for (it = vec.begin(); it != vec.end(); ++it)
- {
- cout << it->get_Line() << ' ' << it->get_Name();
- cout << '\n';
- }
- }
- /*
- * This function handles almost all of assignment three's parsing.
- * I know this function is way, way, way too big. I tried making things like the print functions a bit more modular
- * but I was having pointer and run time crashes all over the place. I have a Logic Design exam this Friday and I just
- * don't really have the free time to fix this up, unfortunately. I understand if points will be deducted, I just figured
- * I should admit my programs glaring flaw before I get destroyed because of it.
- *
- * The function takes in an xml file's name. This was done for testing purposes, so I could implement Professor Heines XML file
- * easily in order to test mine the way he tested his.
- */
- void read_XML(string song_name){
- string line; //string variable used for the current line of XML being parsed
- ifstream songfile; //ifstream songfile, object used for the XML input file
- int intLinenum = 1; //an integer which represents the current line number on the XML file which we're parsing
- int startpos = 0, endpos = 0; //two integers which represent the designated starting and ending position
- //of the current line of XML which we're working with.
- //value of variables dependent on what kind of line it is
- int secondOpen; //an integer which I made on the fly to represent the second open brackets position.
- //a fairly ghetto fix, would try to re-vamp how I did this if I had the time.
- //string tag = "";
- elements* tag; //element pointer for the current XML file's tag, in order to initiate a new element
- vector<elements> song_to_be_parsed; //vector which was used for assignment 2, obsolete for this assignment
- stack<elements*> stack_of_elements; //stack of element pointers in which we'll push opening brackets onto
- vector<elements*> song;
- //bool to represent if we're on a parent
- bool parent = false;
- //elements* popped_element; //variable which was created to assign the popped element to. ended up being obsolete.
- //
- songfile.open(song_name); //assign ifstream object songfile by the passed in xml file
- while (getline(songfile, line))
- {
- //instantiate's integer startpos and endpos to the location of the current line
- //which is being read's open and end bracket
- //startpos = line.find("<");
- //endpos = line.find(">", startpos);
- ////tag = line.substr(startpos + 1, (endpos - startpos) - 1);
- //tag = new elements((line.substr(startpos + 1, (endpos - startpos) - 1)), intLinenum);
- //cout << "Line:" << line << endl;
- if (line.find("<!--") != string::npos) //looking comments
- {
- cout << intLinenum << ": Parser State - Starting comment: " << line << endl; //shows the first part of the comment
- intLinenum++; //increment for the starting comment
- getline(songfile, line); //gets next line
- while (line.find("-->") == string::npos) //searching for the end of the comment
- {
- intLinenum++; //important to increment the linenum now, because we will use getline() to move to the next line soon
- //and we would not count for this complete element if we don't increment an extra time
- cout << intLinenum << ": Parser State - Comment: " << line << endl;
- getline(songfile, line); //gets next line
- }
- cout << intLinenum << ": Parser State - Ending comment: " << line << endl << endl;
- getline(songfile, line); //gets next line
- intLinenum++; //counts the line again
- }
- //if loop that attempts to find complete lines, and move past them
- if (line.at((line.find("<")) + 1) != '/'){
- startpos = line.find("<");
- endpos = line.find(">", startpos);
- //figure out if this is a complete xml line on one line
- int temp2 = line.find('/'); //finds the slash, which would indicate a closing tag
- if (temp2 != string::npos&&line.at(temp2 - 1) == '<'){
- //if this is a child tag, ie parent is true, add to
- if (parent){
- //song.insert(addChild())
- }
- cout << intLinenum << ": Parser State - Complete line: " << line << endl;
- //force it to go onto the next line
- //getline(songfile, line);
- //cout << "Found complete line:" << line << endl;
- // boolTwoLines = true;
- getline(songfile, line);
- //i++;
- intLinenum++;
- }
- }
- //if loop that finds the opening bracket
- secondOpen = line.find("/");
- if ((line.at((line.find("<")) + 1) != '/')&&secondOpen==string::npos){
- startpos = line.find("<");
- endpos = line.find(">", startpos + 1);
- //tag = line.substr(startpos + 1, (endpos - startpos) - 1);
- tag = new elements(getOpen(line), intLinenum);
- //tag = new elements((line.substr(startpos + 1, (endpos - startpos) - 1)), intLinenum);
- cout << intLinenum << ": Opening tag is: " << tag->get_Name() << endl;
- parent = true;
- //pops current open tag into the stack. hopefully, next thing popped in will be the closing tag
- stack_of_elements.push(tag);
- //intLinenum++;
- //cout << "Top of the stack is: " << stack_of_elements.top()->get_Name() << endl;
- //cout << "Opening bracket - Top of stack is: " << stack_of_elements.top()->get_Name() << endl << endl;
- }
- //if loop to find where the closing brackets are
- if (line.at((line.find("<")) + 1) == '/'){
- startpos = line.find("/");
- endpos = line.find(">", startpos);
- tag = new elements((line.substr(startpos + 1, (endpos - startpos) - 1)), intLinenum);
- cout << intLinenum << ": Parser State - Closing tag is: " << tag->get_Name() << endl;
- //stack_of_elements.push(new elements(tag->get_Name(), tag->get_Line()));
- //intLinenum++;
- //cout << "stack_of_elements.top()->get_Name(): " << stack_of_elements.top()->get_Name() << endl;
- //if loop to look if the top of the stack is equal to this closing bracket
- // cout << "----------------------------------" << endl;
- //cout << "Top of the stack is: " << stack_of_elements.top()->get_Name() << endl;
- //cout << "This closing bracket is: " << tag->get_Name() << endl;
- //cout << "----------------------------------" << endl << endl;
- //if loop which should be a function (afraid of messing things up, though)
- //this if loop will check if the top of the stack's name (which is an opening bracket)
- //is equal to the current closing bracket's name.
- //if it is, we have found a match. print out success and pop the open bracket off the stack.
- if (stack_of_elements.top()->get_Name() == tag->get_Name()){
- //lines for well formed, distinct output
- cout << endl << "----------------------------------" << endl;
- cout << "Found closing bracket for open bracket: " << stack_of_elements.top()->get_Name() << endl;
- cout << "The closing bracket is: " << tag->get_Name() << endl;
- cout << "Popping the bracket off of the stack." << endl;
- stack_of_elements.pop();
- cout << "New top of the stack is: " << stack_of_elements.top()->get_Name() << endl;
- cout << "----------------------------------" << endl << endl;
- }
- //cout << "Closing bracket - Top of stack is: " << stack_of_elements.top()->get_Name() << endl << endl;
- }
- //increment the int which represents the current line of XML after we've finished parsing the line
- intLinenum++;
- //if (line.at((line.find(">"))))
- //if (line.at((line.find("<")) + 1) != '/'){
- //
- //
- // //cout << "This line is: " << line << endl;
- //
- //}
- //cout << "start:" << startpos << "end:" << endpos;
- //instantiate the string tag to a string located between the start pos and end pos, which is the full XML line
- //tag = line.substr(startpos, endpos);
- //cout << startpos << " tag: " << tag << " " << endpos << endl;
- //pushes the full XML tags into the vector
- //song_to_be_parsed.push_back(elements(tag, i));
- }
- //printVector(song_to_be_parsed);
- //prints the top of the stack. when all is said and done, the top of the stack should be the XML file directive.
- cout << intLinenum << ": Top of the stack is: " << stack_of_elements.top()->get_Name() << endl;
- if (stack_of_elements.top()->get_Name() == "xml"){
- cout << endl << "*****************" << endl << "The top of the stack is the xml directive." << endl <<
- "Congratulations, your xml file is well formed and has been parsed correctly."
- << endl << "*****************" << endl;
- }
- //return song_to_be_parsed;
- }
- /*function from prior assignment. this is obsolete for this program.*/
- /*
- vector<elements> parse_vector(vector<elements> song){
- //initialize a few new strings for final parsing
- string current;
- string fixed_string;
- string line1;
- //integer to represent the lines which contain opening tags
- int g = 0;
- //ints to represent the start and endpos in the current element being parsed
- int startpos = 0, endpos = 0;
- cout << "----------------------------------" << endl;
- printVector(song);
- //initialize a new, final vector for the parsed information
- vector<elements> fixed_song;
- //stack of elements to check for well formedness
- stack<elements> stack_tags;
- //in line iterator declaration to iterate through unparsed vector
- for (vector<elements>::iterator it = song.begin(); it != song.end(); ++it)
- {
- //set line1 string to the current vector element being iterated
- line1 = it->get_Name();
- // cout << "itr->get_Name() yields " << it->get_Name() << endl;
- //this if loop will ensure we will ONLY be working with opening tags
- if (line1.at((line1.find("<")) + 1) != '/'){
- //increment parsed, open bracket line number
- g++;
- //allows us to work on a new variable string instead of having to access the element inside
- //the vector of elements
- current = it->get_Name();
- //initializes startpos and endpos to bracket positions like before
- startpos = current.find("<");
- endpos = current.find(">");
- // cout << "Current is: " << current << endl;
- //creates a fixed string initialized to a substring without brackets, using endpos and startpos
- //the +1 for startpos increments past the first <, -1 de-increments before the >
- fixed_string = current.substr(startpos + 1, (endpos - startpos) - 1);
- //printing for testing purposes
- //cout << g << " fixed: " << fixed_string << endl;
- //this if loop applies same logic as before's to remove brackets, but this time to remove spaces
- //in order to address the id="..." tags
- if (fixed_string.find(" ") != string::npos){
- endpos = fixed_string.find(" ");
- fixed_string = fixed_string.substr(startpos, (endpos - startpos));
- }
- //creates a brand new vector with all parsed information
- fixed_song.push_back(elements(fixed_string, g));
- }
- }
- return fixed_song;
- }
- */
- /*
- * getOpen function takes in the current open bracket line
- * it will take the string line and clean up the line, evaluating it based on
- * what the line is.
- * Tyler Bainbridge helped me with the code/theory of this code for this function.
- */
- string getOpen(string line)
- {
- int startPos = 0, endPos = 0; //two integers which represent the designated starting and ending position
- //of the current line of XML which we're working with.
- //value of variables dependent on what kind of line it is
- string tag1, finalTag;
- startPos = line.find("<");
- endPos = line.find(">", startPos + 1); //goes through the current XML files open line and finds the ending bracket
- tag1 = line.substr(startPos + 1, (endPos - startPos) - 1); //creates a new string that for only what is in the brackets
- startPos = tag1.find("<");
- endPos = tag1.find(">", startPos + 1); //sets endPos now to the ending of the new, bracket-less string
- if (tag1.find(" ", startPos + 1) != string::npos) //checks for spaces in current, bracket-less tag
- {
- if (ispunct(tag1.at(startPos + 1))) //if theres punctuation, ie it's a self closing tag, skip over this punctuation
- {
- startPos++; //increment startPos to skip the punctuation
- }
- endPos = tag1.find(" ", startPos + 1); //sets the endPos to where the first instance of the space is
- finalTag = tag1.substr(startPos + 1, (endPos - startPos) - 1); //remove whatever is after the space (XML directive) and stores in final tag
- }
- if (tag1.find(" ", startPos + 1) == string::npos) //if there is no space in the tag
- {
- if (ispunct(tag1.at(startPos + 1))) //if theres punctuation, ie it's a self closing tag, skip over this punctuation
- {
- startPos++; //increment startPos to skip the punctuation
- }
- finalTag = tag1.substr(startPos + 1, (endPos - startPos) - 1); //stores whatever the tag1 is after the punctuation truncation
- }
- return finalTag;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement