2
0
Эх сурвалжийг харах

* partially done support for VERM
* MSVC compilation fix (using boost::ref is an error)

mateuszb 14 жил өмнө
parent
commit
ccecc6637f
3 өөрчлөгдсөн 133 нэмэгдсэн , 14 устгасан
  1. 3 1
      client/CPreGame.cpp
  2. 128 12
      lib/ERMParser.cpp
  3. 2 1
      lib/VCMI_Lib.cpp

+ 3 - 1
client/CPreGame.cpp

@@ -25,6 +25,8 @@
 #include "Graphics.h"
 //#include <boost/thread.hpp>
 #include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/ref.hpp>
 #include <cstdlib>
 #include "../lib/Connection.h"
 #include "../lib/VCMIDirs.h"
@@ -220,7 +222,7 @@ CMenuScreen::CMenuScreen( EState which )
 				bind(&CMenuScreen::moveTo, this, ref(CGP->scrs[loadGame])), 532, 132, "ZMENULG.DEF", SDLK_l);
 			buttons[2] = new AdventureMapButton("", CGI->generaltexth->zelp[5].second, 0, 524, 251, "ZMENUHS.DEF", SDLK_h); // Highscore
 			buttons[3] = new AdventureMapButton("", CGI->generaltexth->zelp[6].second, 0 /*cb*/, 557, 359, "ZMENUCR.DEF", SDLK_c); // Credits
-			boost::function<void()> confWindow = bind(CInfoWindow::showYesNoDialog, boost::ref(CGI->generaltexth->allTexts[69]), (const std::vector<SComponent*>*)0, do_quit, 0, false, 1);
+			boost::function<void()> confWindow = bind(CInfoWindow::showYesNoDialog, ref(CGI->generaltexth->allTexts[69]), (const std::vector<SComponent*>*)0, do_quit, 0, false, 1);
 			buttons[4] = new AdventureMapButton("", CGI->generaltexth->zelp[7].second, confWindow, 586, 468, "ZMENUQT.DEF", SDLK_ESCAPE); // Exit
 		}
 		break;

+ 128 - 12
lib/ERMParser.cpp

@@ -50,7 +50,7 @@ void ERMParser::parseFile()
 	//check header
 	char header[5];
 	file.getline(header, ARRAY_COUNT(header));
-	if(std::string(header) != "ZVSE")
+	if(std::string(header) != "ZVSE" && std::string(header) != "VERM")
 	{
 		tlog1 << "File " << srcFile << " has wrong header\n";
 		return;
@@ -280,9 +280,31 @@ namespace ERM
 		std::string comment;
 	};
 
-	typedef boost::variant<Tcommand, std::string, qi::unused_type> Tline;
+	//vector expression
 
 
+	typedef boost::variant<Tcommand, std::string, qi::unused_type> TERMline;
+
+	struct TSymbol
+	{
+		boost::optional<std::string> symModifier; //'`', ',', ',@', '#''
+		std::string sym;
+	};
+
+	//for #'symbol expression
+
+	struct TVExp;
+	typedef boost::variant<boost::recursive_wrapper<TVExp>, TSymbol, char, double, int, Tcommand, TStringConstant > TVOption; //options in v-expression
+	//v-expression
+	struct TVExp
+	{
+		//char dummy;
+		std::vector<TVOption> children;
+	};
+
+	//script line
+	typedef boost::variant<TVExp, TERMline> TLine;
+
 	//console printer
 
 	struct VarPrinterVisitor : boost::static_visitor<>
@@ -537,12 +559,78 @@ namespace ERM
 		}
 	};
 
-	void printLineAST(const Tline & ast)
+	void printERM(const TERMline & ast)
 	{
 		tlog2 << "";
 		
 		boost::apply_visitor(LinePrinterVisitor(), ast);
 	}
+
+	void printTVExp(const TVExp & exp);
+
+	struct VOptionPrinterVisitor : boost::static_visitor<>
+	{
+		void operator()(TVExp const& cmd) const
+		{
+			printTVExp(cmd);
+		}
+		void operator()(TSymbol const& cmd) const
+		{
+			if(cmd.symModifier.is_initialized())
+			{
+				tlog2 << cmd.symModifier.get();
+			}
+			tlog2 << cmd.sym;
+		}
+		void operator()(char const& cmd) const
+		{
+			tlog2 << "'" << cmd << "'";
+		}
+		void operator()(int const& cmd) const
+		{
+			tlog2 << cmd;
+		}
+		void operator()(double const& cmd) const
+		{
+			tlog2 << cmd;
+		}
+		void operator()(TERMline const& cmd) const
+		{
+			printERM(cmd);
+		}
+		void operator()(TStringConstant const& cmd) const
+		{
+			tlog2 << "^" << cmd.str << "^";
+		}
+	};
+
+	void printTVExp(const TVExp & exp)
+	{
+		tlog2 << "[ ";
+		BOOST_FOREACH(TVOption opt, exp.children)
+		{
+			boost::apply_visitor(VOptionPrinterVisitor(), opt);
+			tlog2 << " ";
+		}
+		tlog2 << "]";
+	}
+
+	struct TLPrinterVisitor : boost::static_visitor<>
+	{
+		void operator()(TVExp const& cmd) const
+		{
+			printTVExp(cmd);
+		}
+		void operator()(TERMline const& cmd) const
+		{
+			printERM(cmd);
+		}
+	};
+
+	void printAST(const TLine & ast)
+	{
+		boost::apply_visitor(TLPrinterVisitor(), ast);
+	}
 }
 
 BOOST_FUSION_ADAPT_STRUCT(
@@ -670,12 +758,24 @@ BOOST_FUSION_ADAPT_STRUCT(
 	(std::string, comment)
 	)
 
+BOOST_FUSION_ADAPT_STRUCT(
+	ERM::TVExp,
+	//(char, dummy)
+	(std::vector<ERM::TVOption>, children)
+	)
+
+BOOST_FUSION_ADAPT_STRUCT(
+	ERM::TSymbol,
+	(boost::optional<std::string>, symModifier)
+	(std::string, sym)
+	)
+
 namespace ERM
 {
 	template<typename Iterator>
-	struct ERM_grammar : qi::grammar<Iterator, Tline(), ascii::space_type>
+	struct ERM_grammar : qi::grammar<Iterator, TLine(), ascii::space_type>
 	{
-		ERM_grammar() : ERM_grammar::base_type(rline, "ERM script line")
+		ERM_grammar() : ERM_grammar::base_type(vline, "VERM script line")
 		{
 			//do not build too complicated expressions, e.g. (a >> b) | c, qi has problems with them
 			macroUsage %= qi::lexeme[qi::lit('$') >> *(qi::char_ - '$') >> qi::lit('$')];
@@ -686,7 +786,7 @@ namespace ERM
 			iexp %= varExp | qi::int_;
 			varp %=/* qi::lit("?") >> */(varExpNotMacro | qMacroUsage);
  			comment %= *qi::char_;
-			commentLine %= (~qi::char_('!') >> comment | (qi::char_('!') >> (~qi::char_("?!$#")) >> comment ));
+			commentLine %= (~qi::char_("![") >> comment | (qi::char_('!') >> (~qi::char_("?!$#")) >> comment ));
  			cmdName %= qi::lexeme[qi::repeat(2)[qi::char_]];
 			arithmeticOp %= iexp >> qi::char_ >> iexp;
 			//identifier is usually a vector of i-expressions but VR receiver performs arithmetic operations on it
@@ -724,7 +824,15 @@ namespace ERM
 			rline %=
 				(
 					command | commentLine | spirit::eps
-				) > spirit::eoi;
+				);
+
+			vsym %= -(qi::string("`") | qi::string(",") | qi::string("#,") | qi::string(",@") | qi::string("#'")) >> +qi::char_("+*/$%&_=<>~a-zA-Z0-9-");
+
+			
+			vopt %= vsym | (qi::lit("!") >> qi::char_ >> qi::lit("!")) | qi::double_ | qi::int_ | command /*| vexp*/ | string;
+			vexp %= qi::lit("[") >> *(vopt) >> qi::lit("]");
+
+			vline %= (vexp | rline ) > spirit::eoi;
 
 			//error handling
 
@@ -741,11 +849,15 @@ namespace ERM
 			receiver.name("receiver");
 			postTrigger.name("post trigger");
 			command.name("command");
-			rline.name("script line");
+			rline.name("ERM script line");
+			vsym.name("V symbol");
+			vopt.name("V option");
+			vexp.name("V expression");
+			vline.name("VERM line");
 
 			qi::on_error<qi::fail>
 				(
-				rline
+				vline
 				, std::cout //or phoenix::ref(std::count), is there any difference?
 				<< phoenix::val("Error! Expecting ")
 				<< qi::_4                               // what failed?
@@ -788,7 +900,11 @@ namespace ERM
 		qi::rule<Iterator, Treceiver(), ascii::space_type> receiver;
 		qi::rule<Iterator, TPostTrigger(), ascii::space_type> postTrigger;
 		qi::rule<Iterator, Tcommand(), ascii::space_type> command;
-		qi::rule<Iterator, Tline(), ascii::space_type> rline;
+		qi::rule<Iterator, TERMline(), ascii::space_type> rline;
+		qi::rule<Iterator, TSymbol(), ascii::space_type> vsym;
+		qi::rule<Iterator, TVOption(), ascii::space_type> vopt;
+		qi::rule<Iterator, TVExp(), ascii::space_type> vexp;
+		qi::rule<Iterator, TLine(), ascii::space_type> vline;
 	};
 };
 
@@ -798,7 +914,7 @@ void ERMParser::parseLine( const std::string & line )
 		end = line.end();
 
 	ERM::ERM_grammar<std::string::const_iterator> ERMgrammar;
-	ERM::Tline AST;
+	ERM::TLine AST;
 
 // 	bool r = qi::phrase_parse(beg, end, ERMgrammar, ascii::space, AST);
 // 	if(!r || beg != end)
@@ -810,7 +926,7 @@ void ERMParser::parseLine( const std::string & line )
 // 	{
 // 		//parsing succeeded
 // 		tlog2 << line << std::endl;
-// 		ERM::printLineAST(AST);
+// 		ERM::printAST(AST);
 // 	}
 }
 

+ 2 - 1
lib/VCMI_Lib.cpp

@@ -68,7 +68,8 @@ DLL_EXPORT void initDLL(CConsoleHandler *Console, std::ostream *Logfile)
 		if(is_regular(dir->status()))
 		{
 			std::string name = dir->path().leaf();
-			if( boost::algorithm::ends_with(name, ".erm"))
+			if( boost::algorithm::ends_with(name, ".erm") ||
+				boost::algorithm::ends_with(name, ".verm") )
 			{
 
 				ERMParser ep(dir->path().string());