瀏覽代碼

* first part of ERM parser

mateuszb 14 年之前
父節點
當前提交
b3ed75ab03
共有 4 個文件被更改,包括 147 次插入2 次删除
  1. 109 0
      lib/ERMParser.cpp
  2. 15 0
      lib/ERMParser.h
  3. 23 1
      lib/VCMI_Lib.cpp
  4. 0 1
      server/CVCMIServer.cpp

+ 109 - 0
lib/ERMParser.cpp

@@ -0,0 +1,109 @@
+#include "ERMParser.h"
+#include <boost/spirit/include/qi.hpp>
+#include <boost/bind.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <fstream>
+
+namespace spirit = boost::spirit;
+namespace qi = boost::spirit::qi;
+
+ERMParser::ERMParser(std::string file)
+	:srcFile(file)
+{}
+
+void ERMParser::parseFile()
+{
+	std::ifstream file(srcFile);
+	if(!file.is_open())
+	{
+		tlog1 << "File " << srcFile << " not found or unable to open\n";
+		return;
+	}
+	//check header
+	char header[5];
+	file.getline(header, ARRAY_COUNT(header));
+	if(std::string(header) != "ZVSE")
+	{
+		tlog1 << "File " << srcFile << " has wrong header\n";
+		return;
+	}
+	//parse file
+	char lineBuf[1024];
+	int lineNum = 1;
+	while(file.good())
+	{
+		//reading line
+		file.getline(lineBuf, ARRAY_COUNT(lineBuf));
+		if(file.gcount() == ARRAY_COUNT(lineBuf))
+		{
+			tlog1 << "Encountered a problem during parsing " << srcFile << " too long line " << lineNum << "\n";
+		}
+		//parsing
+		parseLine(lineBuf);
+
+
+		//loop end
+		++lineNum;
+	}
+}
+
+void callme(char const& i)
+{
+	std::cout << "fd";
+}
+
+void ERMParser::parseLine( std::string line )
+{
+	namespace ascii = spirit::ascii;
+	namespace phoenix = boost::phoenix;
+	typedef std::string::iterator sit;
+	qi::rule<sit> comment = *(qi::char_);
+	qi::rule<sit> commentLine = ~qi::char_('!') >> comment;
+	qi::rule<sit> cmdName = qi::repeat(2)[ascii::alpha];
+	qi::rule<sit> identifier = qi::int_ % '/';
+	qi::rule<sit> condition = qi::char_('&') >> +(qi::int_ | qi::char_("a-zA-Z&/|")) >> qi::char_(":;");
+	qi::rule<sit> trigger = cmdName >> -identifier >> -condition;
+	qi::rule<sit> string = qi::char_('^') >> ascii::print >> qi::char_('^');
+	qi::rule<sit> body = *(qi::char_("a-zA-Z0-9/ ") | string);
+	qi::rule<sit> instruction = cmdName >> -identifier >> -condition >> body;
+	qi::rule<sit> receiver = cmdName >> -identifier >> -condition >> body;
+	qi::rule<sit> postOBtrigger = "$OB" >> -identifier >> -condition;
+
+	qi::rule<sit> rline =
+		(
+			(qi::char_('!') >>
+			(
+				(qi::char_('?') >> trigger) |
+				(qi::char_('!') >> instruction) |
+				(qi::char_('#') >> receiver) |
+				postOBtrigger
+			) >> comment
+			)
+			| commentLine | spirit::eoi
+		);
+
+	qi::on_error<qi::fail>
+		(
+		rline
+		, std::cout //or phoenix::ref(std::count), is there any difference?
+		<< phoenix::val("Error! Expecting ")
+		<< qi::_4                               // what failed?
+		<< phoenix::val(" here: \"")
+		<< phoenix::construct<std::string>(qi::_3, qi::_2)   // iterators to error-pos, end
+		<< phoenix::val("\"")
+		<< std::endl
+		);
+
+	sit beg = line.begin(),
+		end = line.end();
+	bool r = qi::parse(beg, end, rline);
+	if(!r || beg != end)
+	{
+		tlog1 << "Parse error for line " << line << std::endl;
+		tlog1 << "\tCannot parse: " << std::string(beg, end) << std::endl;
+	}
+}

+ 15 - 0
lib/ERMParser.h

@@ -0,0 +1,15 @@
+#pragma once
+#include "../global.h"
+
+class ERMParser
+{
+private:
+	std::string srcFile;
+
+
+	void parseLine(std::string line);
+
+public:
+	ERMParser(std::string file);
+	void parseFile();
+};

+ 23 - 1
lib/VCMI_Lib.cpp

@@ -11,6 +11,10 @@
 #include "CBuildingHandler.h"
 #include "CSpellHandler.h"
 #include "CGeneralTextHandler.h"
+#include "ERMParser.h"
+
+#include <boost/filesystem.hpp> //for erm parser testing
+#include <boost/algorithm/string.hpp> //for erm parser testing
 
 /*
  * VCMI_Lib.cpp, part of VCMI engine
@@ -48,7 +52,25 @@ DLL_EXPORT void initDLL(CConsoleHandler *Console, std::ostream *Logfile)
 	try
 	{
 		VLC->init();
-	} HANDLE_EXCEPTION
+	} HANDLE_EXCEPTION;
+
+
+	using namespace boost::filesystem;
+	//parser checking
+	directory_iterator enddir;
+	for (directory_iterator dir("Data/s"); dir!=enddir; dir++)
+	{
+		if(is_regular(dir->status()))
+		{
+			std::string name = dir->path().leaf();
+			if( boost::algorithm::ends_with(name, ".erm"))
+			{
+
+				ERMParser ep(dir->path().string());
+				ep.parseFile();
+			}
+		}
+	}
 }
 
 DLL_EXPORT void loadToIt(std::string &dest, const std::string &src, int &iter, int mode)

+ 0 - 1
server/CVCMIServer.cpp

@@ -18,7 +18,6 @@
 #include "CVCMIServer.h"
 #include "../StartInfo.h"
 #include "../lib/map.h"
-#include "../lib/CLodHandler.h" 
 #include "../lib/Interprocess.h"
 #include "../lib/VCMI_Lib.h"
 #include "../lib/VCMIDirs.h"