bool group_tokens_into_statements(evl_statements &statements, evl_tokens &tokens) { for (; !tokens.empty();) { // generate one statement per iteration evl_token token = tokens.front(); evl_token token = tokens.front(); if (token.type != evl_token::NAME) { std::cerr << "Need a NAME token but found '" << token.str << "' on line " << token.line_no << std::endl; return false; } if (token.str == "module") // MODULE statement { evl_statement module; module.type = evl_statement::MODULE; if (!move_tokens_to_statement(module.tokens, tokens)) return false; statements.push_back(module); } else if (token.str == "endmodule") // ENDMODULE statement { evl_statement endmodule; endmodule.type = evl_statement::ENDMODULE; endmodule.tokens.push_back(token); tokens.erase(tokens.begin()); statements.push_back(endmodule); } else if (token.str == "wire") // WIRE statement { evl_statement wire; wire.type = evl_statement::WIRE; if (!move_tokens_to_statement(wire.tokens, tokens)) return false; statements.push_back(wire); } //ASSIGN statement else if (token.str == "assign"){ evl_statement assign; assign.type = evl_statement::ASSIGN; if (!move_tokens_to_statement(assign.tokens, tokens)) return false; statements.push_back(assign); } else // COMPONENT statement { evl_statement component; component.type = evl_statement::COMPONENT; if (!move_tokens_to_statement(component.tokens, tokens)) return false; statements.push_back(component); } } return true; }
// This function iterates through the vector and display a formatted line for each token void display_tokens(ostream &out, const evl_tokens tokens) { for (evl_tokens::const_iterator iter = tokens.begin(); iter != tokens.end(); ++iter) { if(iter->type == evl_token::SINGLE) { out << "SINGLE " << iter->name << endl; } else if(iter->type == evl_token::NAME) { out << "NAME " << iter->name << endl; } else { out << "NUMBER " << iter->name << endl; } } }
bool group_tokens_into_statements(evl_statements &statements, evl_tokens &tokens) { assert(statements.empty()); for(; !tokens.empty();) { //generates one statement per iteration evl_token token = tokens.front(); if (token.type != evl_token::NAME) { std::cerr << "Need a NAME token but found '" << token.str << "' on line" << token.line_no << std::endl; return false; } if ((token.str == "INPUT") || (token.str == "OUTPUT") || (token.str == "AND") || (token.str == "NAND") || (token.str == "OR") || (token.str == "NOR") || (token.str == "DFF") || (token.str == "NOT")) { evl_statement component; component.type = evl_statement::COMPONENT; if(!move_comp_to_statement(component.tokens, tokens)) { return false; } //INPUT and OUTPUT are both components and wires; if ((token.str == "INPUT") || (token.str == "OUTPUT")) { evl_statement wire; wire.type = evl_statement::WIRE; wire.tokens = component.tokens; statements.push_back(wire); } statements.push_back(component); } else { evl_statement wire; wire.type = evl_statement::WIRE; if(!move_wire_to_statement(wire.tokens, tokens)) { return false; } statements.push_back(wire); } } return true; }
bool move_wire_to_statement(evl_tokens &statement_tokens, evl_tokens &tokens) { assert(statement_tokens.empty()); assert(!tokens.empty()); for (; !tokens.empty();) { statement_tokens.push_back(tokens.front()); tokens.erase(tokens.begin()); if (statement_tokens.back().str == "=") break; //exit if the ending "=" is found } if (statement_tokens.back().str != "=") { std::cerr << "Look for '=' but reach the end of file" << std::endl; return false; } return true; }
void display_tokens(std::ostream &out, const evl_tokens &tokens) { for (evl_tokens::const_iterator iter = tokens.begin(); iter != tokens.end(); ++iter){ if (iter->type == evl_token::SINGLE){ out << "SINGLE " << iter->str << std::endl; } else if (iter->type == evl_token::NAME) { out << "NAME " << iter->str << std::endl; } else if (iter->type == evl_token::NUMBER) { out << "NUMBER " << iter->str << std::endl; } else { out << "LINE " << iter->line_no << ": invalid character" << std::endl; } } }
bool extract_tokens_from_file(std::string file_name, evl_tokens &tokens) { // use reference to modify it std::ifstream input_file(file_name.c_str()); if (!input_file){ std::cerr << "I can't read " << file_name << "." << std::endl; return false; } tokens.clear(); std::string line; for (int line_no = 1; std::getline(input_file, line); ++line_no){ if (!extract_tokens_from_line(line, line_no, tokens)) { return false; } } return true; }
bool move_tokens_to_statement(evl_tokens &statement_tokens, evl_tokens &tokens) { for (; !tokens.empty();) { statement_tokens.push_back(tokens.front()); tokens.erase(tokens.begin()); // consume one token per iteration if (statement_tokens.back().str == ";") break; // exit if the ending ";" is found } if (statement_tokens.back().str != ";") { std::cerr << "Look for ';' but reach the end of file" << std::endl; return false; } return true; }
// This function extracts a line at a time from the input file and passes it to the function "extract_tokens_from_Line(); bool extract_line_from_File(string filename, evl_tokens &tokens) { ifstream infile(filename.c_str()); // This checks whether the input file can be opened. It returns an error if not. if (!infile) { cerr << "This file cannot be opened!" << endl; return false; } tokens.clear(); string line; //This for loop extracts a line from the input file with each iteration. for (int line_index = 1; getline(infile, line); line_index++) { if(!extract_tokens_from_Line(line_index,line,tokens)) { return false; } } return true; }
bool read_tokens_file(evl_tokens &tokens, int argc, std::string file_name) { if (argc < 2) { std::cerr << "You should provide a file name." << std::endl; return false; } std::ifstream input_file(file_name.c_str()); if (!input_file) { std::cerr << "I can't read " << file_name.c_str() << "." << std::endl; return false; } std::string line; for (int line_no = 1; std::getline(input_file, line); ++line_no)//read a file { for (size_t i = 0; i < line.size();)//read a line { evl_token token; token.line_no = line_no; //first word // spaces if (line[i] == ' ') { std::cerr << "wrong in .tokens file at line: " << line_no << std::endl;; // skip this space character return false; // skip the rest of the iteration } // type if ((line[i] == 'N') || (line[i] == 'S')) { size_t type_begin = i + 1; for (++i; i < line.size(); ++i) { if (line[i] == ' ') { ++i; break; // [name_begin, i) is the range for the token } } if (line[type_begin] == 'I') token.type = evl_token::SINGLE; else if (line[type_begin] == 'A') token.type = evl_token::NAME; else if (line[type_begin] == 'U') token.type = evl_token::NUMBER; else { std::cerr << "Wrong Type in line: " << line_no << std::endl; return false; } } //second word // SINGLE if ((line[i] == '(') || (line[i] == ')') || (line[i] == '[') || (line[i] == ']') || (line[i] == ':') || (line[i] == ';') || (line[i] == ',')) { token.str = line[i]; ++i; } // NAME or NUMBER else { size_t str_begin = i; for (++i; i < line.size(); ++i) { if (line[i] == ' ') { break; // [name_begin, i) is the range for the token } } token.str = line.substr(str_begin, i - str_begin); } tokens.push_back(token); } } return true; }
//This function extracts individual tokens from each line and stores them in the vector "tokens" bool extract_tokens_from_Line(int line_index, string line, evl_tokens &tokens) { for (size_t i =0; i < line.size(); i++) { // COMMENT if(line[i] == '/') { i++; if(line[i] != '/' || i==line.size()) { cerr << "a single '/' is not allowed" <<endl; return false; } break; } //SPACE else if (isspace(line[i])) { continue; } //SINGLE else if ((line[i] == '(') || (line[i] == ')') || (line[i] == '[') || (line[i] == ']') || (line[i] == ':') || (line[i] == ';') || (line[i] == ',')) { evl_token token; token.lineNumber = line_index; token.name = string(1, line[i]); token.type = evl_token::SINGLE; tokens.push_back(token); continue; } //NAME else if (isalpha(line[i]) || line[i] == '_' || line[i] == '.' || line[i] == '\\') { size_t name_begin = i; for (i++; i < line.size(); i++) { if (!(isalpha(line[i]) || line[i] == '_' || line[i] == '.' || line[i] == '\\' || isdigit(line[i]))) { break; // [name_begin, i) is the range for the token } } evl_token token; token.lineNumber = line_index; token.name = line.substr(name_begin, i-name_begin); token.type = evl_token::NAME; tokens.push_back(token); i--; continue; } //NUMBER else if (isdigit(line[i])) { size_t num_begin =i; for (i++; i<line.size(); i++) { if (!isdigit(line[i])) { break; } } evl_token token; token.lineNumber = line_index; token.name = line.substr(num_begin, i-num_begin); token.type = evl_token::NUMBER; tokens.push_back(token); i--; continue; } else { std::cerr << "LINE " << line_index << ": invalid character" << std::endl; return false; } } return true; }
bool extract_tokens_from_line(std::string line, int line_no, evl_tokens &tokens) { // use reference to modify it for (size_t i = 0; i < line.size();) { // comments if (line[i] == '/') { ++i; if ((i == line.size()) || (line[i] != '/')) { std::cerr << "LINE " << line_no << ": a single / is not allowed" << std::endl; return false; } break; // skip the rest of the line by exiting the loop } // comments part 2 else if (line[i] == '#') { break; //Comment Detected, skip to next line } // spaces else if (isspace(line[i])) { ++i; // skip this space character continue; // skip the rest of the iteration } // SINGLE else if (issingle(line[i])) { evl_token token; token.line_no = line_no; token.type = evl_token::SINGLE; token.str = std::string(1, line[i]); tokens.push_back(token); ++i; // we consumed this character continue; // skip the rest of the iteration } // NAME else if (isname(line[i])) { size_t name_begin = i; for (++i; i < line.size(); ++i) { if (!(isname(line[i]) || isdigit(line[i]))) { break; } } evl_token token; token.line_no = line_no; token.type = evl_token::NAME; token.str = std::string(line.substr(name_begin, i-name_begin)); tokens.push_back(token); } // NUMBER else if (isdigit(line[i])){ size_t number_begin = i; for(++i; i < line.size(); ++i) { if (isname(line[i])){ std::cerr << "LINE " << line_no << ": invalid character" << std::endl; return false; } else if (issingle(line[i]) || !((line[i]) || isname(line[i]))) { break; } } evl_token token; token.line_no = line_no; token.type = evl_token::NUMBER; token.str = std::string(line.substr(number_begin, i-number_begin)); tokens.push_back(token); } else { std::cerr << "LINE " << line_no << ": invalid character" << std::endl; return false; } } return true; }