Skip to content

Instantly share code, notes, and snippets.

@Romain-P
Created March 3, 2018 02:33
Show Gist options
  • Select an option

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

Select an option

Save Romain-P/a798ec42b6733ed04fbf775175b54663 to your computer and use it in GitHub Desktop.
//
// EPITECH PROJECT, 2018
//
// File description:
//
//
#include <Exceptions.hpp>
#include <iostream>
#include "ConsoleAnalyser.hpp"
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
namespace nts {
//reference
char constexpr ConsoleAnalyser::STATEMENT_DELIMITER;
char constexpr ConsoleAnalyser::COMMAND_EXIT[];
char constexpr ConsoleAnalyser::COMMAND_DISPLAY[];
char constexpr ConsoleAnalyser::COMMAND_SIMULATE[];
char constexpr ConsoleAnalyser::COMMAND_LOOP[];
char constexpr ConsoleAnalyser::COMMAND_DUMP[];
bool ConsoleAnalyser::loop_mode = false;
bool ConsoleAnalyser::parse_options() {
if (_parsed)
return false;
for (size_t i=2; i < _argc; ++i) {
std::string opt(_args[i]);
if (!parse_statement(opt))
throw ParsingError("Invalid option");
}
return (_parsed = true);
}
bool ConsoleAnalyser::init_analyser() {
if (_init)
return false;
_init = true;
handle_sigint();
std::cout << "> ";
for(std::string line; std::getline(std::cin, line);) {
if (line == COMMAND_EXIT)
break;
else if (line == COMMAND_DISPLAY)
_manager->Display();
else if (line == COMMAND_SIMULATE)
_manager->Simulate();
else if (line == COMMAND_LOOP)
start_loop();
else if (line == COMMAND_DUMP)
_manager->Dump();
else if (!parse_statement(line))
throw ParsingError("Unknown command");
std::cout << "> ";
}
return true;
}
bool ConsoleAnalyser::parse_statement(std::string &line) const {
size_t delimiter_pos = line.find(STATEMENT_DELIMITER);
if (delimiter_pos == std::string::npos)
return false;
std::string component = line.substr(0, delimiter_pos);
line.erase(0, delimiter_pos + 1);
char state = (char) std::stoi(line);
Tristate parsed;
switch(state) {
case true:
parsed = TRUE;
break;
case false:
parsed = FALSE;
break;
case -true:
parsed = UNDEFINED;
break;
default:
throw ParsingError("Invalid command statement found");
}
_manager->ChangePinValue(component, parsed);
return true;
}
void ConsoleAnalyser::handle_sigint() {
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = [](int) -> void {
std::cout<<std::endl;
loop_mode = false;
};
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, nullptr);
}
void ConsoleAnalyser::start_loop() {
loop_mode = true;
while (loop_mode)
_manager->Simulate();
}
}
//
// EPITECH PROJECT, 2018
//
// File description:
//
//
#ifndef UNTITLED3_CONSOLEANALYSER_H
#define UNTITLED3_CONSOLEANALYSER_H
#include <cstddef>
#include "Parser.hpp"
#include "NtsManager.hpp"
namespace nts {
class ConsoleAnalyser {
public:
ConsoleAnalyser(NtsManager &manager, std::size_t argc, char *args[])
: _init(false), _parsed(false), _manager(&manager), _argc(argc), _args(args) {};
~ConsoleAnalyser() = default;
ConsoleAnalyser(ConsoleAnalyser const &) = delete;
ConsoleAnalyser(ConsoleAnalyser &) = delete;
ConsoleAnalyser &operator=(ConsoleAnalyser const &) = delete;
ConsoleAnalyser &operator=(ConsoleAnalyser &) = delete;
bool parse_options();
bool init_analyser();
private:
static char constexpr STATEMENT_DELIMITER = '=';
static char constexpr COMMAND_EXIT[] = "exit";
static char constexpr COMMAND_DISPLAY[] = "display";
static char constexpr COMMAND_SIMULATE[] = "simulate";
static char constexpr COMMAND_LOOP[] = "loop";
static char constexpr COMMAND_DUMP[] = "dump";
static bool loop_mode;
bool parse_statement(std::string &line) const;
void start_loop();
void handle_sigint();
bool _init;
bool _parsed;
NtsManager * const _manager;
size_t const _argc;
char ** _args;
};
}
#endif //UNTITLED3_CONSOLEANALYSER_H
//
// 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;
}
bool Parser::successed() const {
return _state == SUCCESS;
}
}
//
// Created by romain on 01/03/2018.
//
#ifndef CPP_NANOTEKSPICE_HEADER_H
#define CPP_NANOTEKSPICE_HEADER_H
#include "ComponentFactory.hpp"
#include "NtsManager.hpp"
#include <regex>
namespace nts
{
class Parser
{
public:
Parser(ComponentFactory &factory, NtsManager &manager, std::string const &file)
: _factory(&factory), _chipsets(manager.getComponents()), _file(file), _state(COMMENTS) {};
~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();
bool successed() const;
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::map<std::string, std::unique_ptr<IComponent>> &_chipsets;
std::string const _file;
ParserFunc _state;
};
}
#endif //CPP_NANOTEKSPICE_HEADER_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment