Commit e09e8b00 authored by aggsol's avatar aggsol

wip parsing

parent 3bc0c78d
cmake_minimum_required(VERSION 3.8) cmake_minimum_required(VERSION 3.8)
project("gamebook-combat" VERSION 0.1.0 LANGUAGES CXX) project("gamebook-tools" VERSION 0.1.0 LANGUAGES CXX)
# Create compile_commands.json for cppcheck # Create compile_commands.json for cppcheck
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
...@@ -28,8 +28,6 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") ...@@ -28,8 +28,6 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
add_subdirectory(src) add_subdirectory(src)
configure_file(data/lw-crt.csv data/lw-crt.csv COPYONLY) configure_file(../data/lw-crt.csv data/lw-crt.csv COPYONLY)
#file(GLOB Data data/*.csv)
#file(COPY ${Data} DESTINATION ${PROJECT_BINARY_DIR}/data )
message(STATUS "Version = ${PROJECT_VERSION}") message(STATUS "Version = ${PROJECT_VERSION}")
\ No newline at end of file
#include "CliArguments.hpp" #include "CliArguments.hpp"
#include <cassert>
#include <istream> #include <istream>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <deque>
#include <map>
namespace {
const std::string SECTION_SUFFIX = "section-";
}
class Section
{
public:
int m_number = -1;
int m_startLine = -1;
std::deque<std::string> m_lines;
std::deque<int> m_parents;
std::deque<int> m_children;
std::string m_style;
};
class Parser class Parser
{ {
public: public:
bool parseLine(const std::string& line); void parseLine(const std::string& line);
const std::map<int, Section>& sections() const { return m_sections; }
private: private:
enum class State
int m_currSection = -1;
std::map<int, Section> m_sections;
enum class LineState
{ {
Start, Start = 0,
SectionStart CommentStart = 1,
DataStart = 2,
SectionTitle = 3,
Style = 4,
}; };
State m_state = State::Start;
}; };
bool Parser::parseLine(const std::string& line) void Parser::parseLine(const std::string& line)
{ {
if(line.empty()) if(line.empty())
{ {
return true; return;
} }
if(m_state == State::Start)) LineState state = LineState::Start;
bool done = false;
for(unsigned i=0; i<line.size() && not done; ++i)
{ {
int slashCount = 0; char c = line[i];
int equalCount = 0: switch(state)
for(int i=0; i<line.length; ++i)
{ {
char c = string[i]; case LineState::Start:
switch(first) if(c == '/')
{
state = LineState::CommentStart;
}
else if(c == '[')
{
state = LineState::DataStart;
}
else if(c == '=')
{
state = LineState::SectionTitle;
}
break;
case LineState::Style:
if(c == '\n' || c == ' ' || c == '\t' || c == '\r')
{
throw std::runtime_error("Invalid style/class");
}
else if(c == ']')
{
done = true;
}
else
{
m_sections[m_currSection].m_style += c;
}
break;
case LineState::SectionTitle:
if(c == '=')
{ {
case '/': // comment // NOP
slashCount++; }
if(i == 1 && slashCount == 2) else if(c == ' ')
{
try
{
int section = std::stoi(line.substr(i));
if(section != m_currSection)
{
throw std::runtime_error("Mismatch section title and section anchor");
}
done = true;
}
catch(const std::exception& ex)
{ {
return true; // Section 0 is a special case
if(m_currSection != 0) {
std::ostringstream msg;
msg << "Invalid section title. Expected: " << m_currSection;
throw std::runtime_error(msg.str());
}
} }
case '=': }
break;
case LineState::DataStart:
if(c == '.')
{
state = LineState::Style;
m_sections[m_currSection].m_style += c;
}
else if(c == '[')
{
try
{
int section = std::stoi(line.substr(10));
// std::cout << "line:" << line << "\n"
// << "current section=" << m_currSection << " section=" << section << "\n";
if(section == m_currSection)
{
throw std::runtime_error("Section already defined");
}
auto it = m_sections.find(section);
if(it != m_sections.end())
{
throw std::runtime_error("Duplicate section");
}
m_sections[section].m_number = section;
m_currSection = section;
done = true;
}
catch(const std::exception& ex)
{
default: throw std::runtime_error(std::string("Invalid section anchor: ") + ex.what());
return false; }
}
else
{
throw std::runtime_error("Invalid attribute. Missing '[' or '.'");
}
break;
case LineState::CommentStart:
if(c != '/')
{
throw std::runtime_error("Invalid comment. Missing /");
}
else
{
done = true;
} }
break;
default:
std::ostringstream msg;
msg << "Unhandled character '" << c << "' Parser State:" << static_cast<int>(state);
throw std::runtime_error(msg.str());
break;
} }
} }
return false; m_sections[m_currSection].m_lines.push_back(line);
return;
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[])
...@@ -66,17 +192,25 @@ int main(int argc, char* argv[]) ...@@ -66,17 +192,25 @@ int main(int argc, char* argv[])
} }
Parser parser; Parser parser;
std::string line; std::string line;
int lineCounter = 1;
while(file) while(file)
{ {
std::getline(file, line); std::getline(file, line);
if(!parser.parseLine(line)) try
{ {
std::cout << "Error: " << line << "\n"; parser.parseLine(line);
}
catch(const std::exception& ex)
{
std::cerr << "Error Line:" << lineCounter << "\n" << ex.what() << "\n";
return 101; return 101;
} }
lineCounter++;
} }
std::cout << "Line count: " << lineCounter << "\n"
<< "Number of sections: " << parser.sections().size() << "\n";
return 0; return 0;
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment