From ccecc6637fd9aa520f76bf270c23afd5f5990909 Mon Sep 17 00:00:00 2001 From: mateuszb Date: Fri, 1 Apr 2011 19:09:05 +0000 Subject: [PATCH] * partially done support for VERM * MSVC compilation fix (using boost::ref is an error) --- client/CPreGame.cpp | 4 +- lib/ERMParser.cpp | 140 ++++++++++++++++++++++++++++++++++++++++---- lib/VCMI_Lib.cpp | 3 +- 3 files changed, 133 insertions(+), 14 deletions(-) diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 535d94c7e..b057683cc 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -25,6 +25,8 @@ #include "Graphics.h" //#include #include +#include +#include #include #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 confWindow = bind(CInfoWindow::showYesNoDialog, boost::ref(CGI->generaltexth->allTexts[69]), (const std::vector*)0, do_quit, 0, false, 1); + boost::function confWindow = bind(CInfoWindow::showYesNoDialog, ref(CGI->generaltexth->allTexts[69]), (const std::vector*)0, do_quit, 0, false, 1); buttons[4] = new AdventureMapButton("", CGI->generaltexth->zelp[7].second, confWindow, 586, 468, "ZMENUQT.DEF", SDLK_ESCAPE); // Exit } break; diff --git a/lib/ERMParser.cpp b/lib/ERMParser.cpp index 0a195da29..698958132 100644 --- a/lib/ERMParser.cpp +++ b/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 Tline; + //vector expression + typedef boost::variant TERMline; + + struct TSymbol + { + boost::optional symModifier; //'`', ',', ',@', '#'' + std::string sym; + }; + + //for #'symbol expression + + struct TVExp; + typedef boost::variant, TSymbol, char, double, int, Tcommand, TStringConstant > TVOption; //options in v-expression + //v-expression + struct TVExp + { + //char dummy; + std::vector children; + }; + + //script line + typedef boost::variant 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, children) + ) + +BOOST_FUSION_ADAPT_STRUCT( + ERM::TSymbol, + (boost::optional, symModifier) + (std::string, sym) + ) + namespace ERM { template - struct ERM_grammar : qi::grammar + struct ERM_grammar : qi::grammar { - 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 ( - 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 receiver; qi::rule postTrigger; qi::rule command; - qi::rule rline; + qi::rule rline; + qi::rule vsym; + qi::rule vopt; + qi::rule vexp; + qi::rule vline; }; }; @@ -798,7 +914,7 @@ void ERMParser::parseLine( const std::string & line ) end = line.end(); ERM::ERM_grammar 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); // } } diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index 39cfd8446..60795de79 100644 --- a/lib/VCMI_Lib.cpp +++ b/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());