Skip to content

Instantly share code, notes, and snippets.

@Romain-P
Created March 2, 2018 20:10
Show Gist options
  • Select an option

  • Save Romain-P/45a603df6f9f4117ba514b4e9df5d77e to your computer and use it in GitHub Desktop.

Select an option

Save Romain-P/45a603df6f9f4117ba514b4e9df5d77e to your computer and use it in GitHub Desktop.
# Admiral Business Machines 1954-2042
# Six inverter gate
.chipsets:
input i0
input i1
input i2
input i3
input i4
input i5
output o0
output o1
output o2
output o3
output o4
output o5
4069 gate
.links:
i0:1 gate:1
i1:1 gate:3
i2:1 gate:5
i3:1 gate:9
i4:1 gate:11
i5:1 gate:13
o0:1 gate:2
o1:1 gate:4
o2:1 gate:6
o3:1 gate:8
o4:1 gate:10
o5:1 gate:12
//
// EPITECH PROJECT, 2018
//
// File description:
//
//
#include "Parser.hpp"
#include "Exceptions.hpp"
#include <iostream>
#include <fstream>
namespace nts {
//static const references
char constexpr Parser::CONFIG_KW_CHIPSETS[];
char constexpr Parser::CONFIG_KW_LINKS[];
//constants init
std::regex const Parser::REGEX_COMMENTS("^([^#]+)");
std::regex const Parser::REGEX_CHIPSETS("^(\\S+)\\s+([^\\s(]+)(?:\\(([^\\s]+)\\))?$");
std::regex const Parser::REGEX_LINKS("^(\\S+):(\\d+)[^\\S]*(\\S+):(\\d+)$");
void Parser::run() {
std::ifstream stream(_file);
if (!stream.is_open())
throw ParsingError("Can't open the file " + _file);
std::smatch matcher;
std::string line;
while (std::getline(stream, line)) {
if (!parse_comments(matcher, line))
continue;
switch (_state) {
case COMMENTS:
if (line.find(CONFIG_KW_CHIPSETS))
throw ParsingError("Section chipsets not found");
_state = CHIPSETS;
break;
case CHIPSETS:
if (!line.find(CONFIG_KW_LINKS))
_state = LINKS;
else if (!parse_chipsets(matcher, line))
throw ParsingError("Syntax error while parsing chipsets");
break;
case LINKS:
if (!parse_links(matcher, line))
throw ParsingError("Syntax error while parsing links");
break;
default:
break;
}
}
if (_state != LINKS)
throw ParsingError(("Section links not found"));
_state = SUCCESS;
}
bool Parser::parse_comments(std::smatch &matcher, std::string &line) const {
if (!std::regex_search(line, matcher, REGEX_COMMENTS))
return false; //empty line
line = matcher[1];
return !std::all_of(line.begin(), line.end(), isspace); //return false if only whitespaces
}
bool Parser::parse_chipsets(std::smatch &matcher, std::string &line) {
if (!std::regex_search(line, matcher, REGEX_CHIPSETS))
return false;
std::string component = matcher[1];
std::string name = matcher[2];
std::string value = matcher[3]; //empty if not specified
if (_chipsets.find(name) != _chipsets.end())
throw ParsingError("Found several chipsets with the same name");
auto chipset = _factory->createComponent(component, name);
_chipsets[name] = std::move(chipset);
return true;
}
bool Parser::parse_links(std::smatch &matcher, std::string &line) const {
if (!std::regex_search(line, matcher, REGEX_LINKS))
return false;
std::string linked_name = matcher[1];
std::size_t linked_pin = parse_uint(matcher[2]);
std::string linker_name = matcher[3];
std::size_t linker_pin = parse_uint(matcher[4]);
auto linked = _chipsets.find(linked_name);
auto linker = _chipsets.find(linker_name);
if (linked == _chipsets.end() || linker == _chipsets.end())
throw ParsingError("Undefined reference name to a chipset");
linker->second->setLink(linker_pin, *(linked->second.get()), linked_pin);
return true;
}
size_t Parser::parse_uint(std::string string) const {
size_t uint;
std::istringstream(string) >> uint;
return uint;
}
std::map<std::string, std::unique_ptr<IComponent>> &Parser::getChipsets() {
if (_state != SUCCESS)
throw ParsingError("Components were not parsed yet");
return _chipsets;
};
}
//
// Created by romain on 01/03/2018.
//
#ifndef CPP_NANOTEKSPICE_HEADER_H
#define CPP_NANOTEKSPICE_HEADER_H
#include "ComponentFactory.hpp"
#include <regex>
namespace nts
{
class Parser
{
public:
Parser(ComponentFactory &factory, std::string const &file)
: _factory(&factory), _file(file), _state(COMMENTS), _chipsets() {};
~Parser() = default;
Parser(Parser const &) = delete;
Parser(Parser &) = delete;
Parser &operator=(Parser const &) = delete;
Parser &operator=(Parser &) = delete;
/**
* Perform the parsing of the file field
*
* @throws ParsingError if the file cant be parsed
*/
void run();
/**
* Get all parsed components indexed by chipset names
*
* @return the map with all parsed components
* @throws ParsingError if the file is not parsed yet
*/
std::map<std::string, std::unique_ptr<IComponent>> &getChipsets();
private:
static char constexpr CONFIG_KW_CHIPSETS[] = ".chipsets:";
static char constexpr CONFIG_KW_LINKS[] = ".links:";
static std::regex const REGEX_COMMENTS;
static std::regex const REGEX_CHIPSETS;
static std::regex const REGEX_LINKS;
bool parse_comments(std::smatch &matcher, std::string &line) const;
bool parse_chipsets(std::smatch &matcher, std::string &line);
bool parse_links(std::smatch &matcher, std::string &line) const;
size_t parse_uint(std::string string) const;
enum ParserFunc {
COMMENTS,
CHIPSETS,
LINKS,
SUCCESS
};
ComponentFactory *_factory;
std::string const _file;
ParserFunc _state;
std::map<std::string, std::unique_ptr<IComponent>> _chipsets;
};
}
#endif //CPP_NANOTEKSPICE_HEADER_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment