From 804aed62985d9eabbd246339b9b7a4ee07cf10cf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 1 Jul 2010 16:40:03 +0200 Subject: [PATCH] added basic message box formatting --- components/compiler/exprparser.cpp | 76 ++++++++++++++++++++------ components/compiler/exprparser.hpp | 13 ++++- components/compiler/generator.cpp | 6 ++ components/compiler/generator.hpp | 2 + components/compiler/lineparser.cpp | 31 +++++++++++ components/compiler/stringparser.cpp | 52 ++++++++++++++++++ components/compiler/stringparser.hpp | 46 ++++++++++++++++ components/interpreter/miscopcodes.hpp | 66 +++++++++++++++++++++- 8 files changed, 271 insertions(+), 21 deletions(-) create mode 100644 components/compiler/stringparser.cpp create mode 100644 components/compiler/stringparser.hpp diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index b1522d99a..658e9334a 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -4,11 +4,13 @@ #include #include #include +#include #include "generator.hpp" #include "scanner.hpp" #include "errorhandler.hpp" #include "locals.hpp" +#include "stringparser.hpp" namespace Compiler { @@ -184,24 +186,10 @@ namespace Compiler popOperator(); } - + void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner) { - ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true); - - for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end(); - ++iter) - { - parser.reset(); - scanner.scan (parser); - - char type = parser.append (mCode); - - if (type!=*iter) - Generator::convert (mCode, type, *iter); - - mOperands.push_back (*iter); - } + parseArguments (arguments, scanner, mCode); } ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, @@ -285,6 +273,7 @@ namespace Compiler parseArguments ("f", scanner); Generator::squareRoot (mCode); + mOperands.push_back ('f'); mNextOperand = false; return true; @@ -433,5 +422,60 @@ namespace Compiler assert (mOperands.size()==1); return mOperands[0]; } + + void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner, + std::vector& code, bool invert) + { + ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true); + StringParser stringParser (getErrorHandler(), getContext(), mLiterals); + + std::stack > stack; + + for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end(); + ++iter) + { + if (*iter=='S') + { + stringParser.reset(); + scanner.scan (stringParser); + + if (invert) + { + std::vector tmp; + stringParser.append (tmp); + + stack.push (tmp); + } + else + stringParser.append (code); + } + else + { + parser.reset(); + scanner.scan (parser); + + std::vector tmp; + + char type = parser.append (tmp); + + if (type!=*iter) + Generator::convert (tmp, type, *iter); + + if (invert) + stack.push (tmp); + else + std::copy (tmp.begin(), tmp.end(), std::back_inserter (code)); + } + } + + while (!stack.empty()) + { + std::vector& tmp = stack.top(); + + std::copy (tmp.begin(), tmp.end(), std::back_inserter (code)); + + stack.pop(); + } + } } diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index db7074056..4ac74075c 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -48,9 +48,9 @@ namespace Compiler void pushBinaryOperator (char c); void close(); - - void parseArguments (const std::string& arguments, Scanner& scanner); - + + void parseArguments (const std::string& arguments, Scanner& scanner); + public: ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, @@ -89,6 +89,13 @@ namespace Compiler char append (std::vector& code); ///< Generate code for parsed expression. /// \return Type ('l': integer, 'f': float) + + void parseArguments (const std::string& arguments, Scanner& scanner, + std::vector& code, bool invert = false); + ///< Parse sequence of arguments specified by \a arguments. + /// \param arguments Each character represents one arguments ('l': integer, + /// 'f': float, 'S': string) + /// \param invert Store arguments in reverted order. }; } diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index e6af41673..0f5a9a478 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -275,6 +275,12 @@ namespace Compiler opFetchFloatLiteral (code); } + void pushString (CodeContainer& code, Literals& literals, const std::string& value) + { + int index = literals.addString (value); + opPushInt (code, index); + } + void assignToLocal (CodeContainer& code, char localType, int localIndex, const CodeContainer& value, char valueType) { diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 8864d51ec..708516cc7 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -17,6 +17,8 @@ namespace Compiler void pushInt (CodeContainer& code, Literals& literals, int value); void pushFloat (CodeContainer& code, Literals& literals, float value); + + void pushString (CodeContainer& code, Literals& literals, const std::string& value); void assignToLocal (CodeContainer& code, char localType, int localIndex, const CodeContainer& value, char valueType); diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 09ecdb82a..50f89ab7f 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -78,6 +78,37 @@ namespace Compiler if (mState==MessageState || mState==MessageCommaState) { + std::string arguments; + + for (std::size_t i=0; i +#include + +#include "scanner.hpp" +#include "generator.hpp" + +namespace Compiler +{ + StringParser::StringParser (ErrorHandler& errorHandler, Context& context, Literals& literals) + : Parser (errorHandler, context), mLiterals (literals), mState (StartState) + { + + } + + bool StringParser::parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner) + { + if (mState==StartState || mState==CommaState) + { + Generator::pushString (mCode, mLiterals, name); + return false; + } + + return Parser::parseName (name, loc, scanner); + } + + bool StringParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) + { + if (code==Scanner::S_comma && mState==StartState) + { + mState = CommaState; + return true; + } + + return Parser::parseSpecial (code, loc, scanner); + } + + void StringParser::append (std::vector& code) + { + std::copy (mCode.begin(), mCode.end(), std::back_inserter (code)); + } + + void StringParser::reset() + { + mState = StartState; + mCode.clear(); + } +} + diff --git a/components/compiler/stringparser.hpp b/components/compiler/stringparser.hpp new file mode 100644 index 000000000..9d128e2d3 --- /dev/null +++ b/components/compiler/stringparser.hpp @@ -0,0 +1,46 @@ +#ifndef COMPILER_STRINGPARSER_H_INCLUDED +#define COMPILER_STRINGPARSER_H_INCLUDED + +#include + +#include + +#include "parser.hpp" + +namespace Compiler +{ + class Literals; + + class StringParser : public Parser + { + enum State + { + StartState, CommaState + }; + + Literals& mLiterals; + State mState; + std::vector mCode; + + public: + + StringParser (ErrorHandler& errorHandler, Context& context, Literals& literals); + + virtual bool parseName (const std::string& name, const TokenLoc& loc, + Scanner& scanner); + ///< Handle a name token. + /// \return fetch another token? + + virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner); + ///< Handle a special character token. + /// \return fetch another token? + + void append (std::vector& code); + ///< Append code for parsed string. + + void reset(); + ///< Reset parser to clean state. + }; +} + +#endif diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index f37620874..89f6116d2 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "opcodes.hpp" #include "runtime.hpp" @@ -18,11 +19,72 @@ namespace Interpreter { if (arg0!=0) throw std::logic_error ("message box buttons not implemented yet"); - + + // message int index = runtime[0]; runtime.pop(); + std::string message = runtime.getStringLiteral (index); + + // additional parameters + std::string formattedMessage; + + for (std::size_t i=0; i (&runtime[0]); + runtime.pop(); + + std::ostringstream out; + out << value; + formattedMessage += out.str(); + } + else if (c=='f' || c=='F' || c=='.') + { + while (c!='f' && i (&runtime[0]); + runtime.pop(); + + std::ostringstream out; + out << value; + formattedMessage += out.str(); + } + else if (c=='%') + formattedMessage += "%"; + else + { + formattedMessage += "%"; + formattedMessage += c; + } + } + } + } + + // buttons (not implemented) std::vector buttons; - runtime.getContext().messageBox (runtime.getStringLiteral (index), buttons); + + runtime.getContext().messageBox (formattedMessage, buttons); } }; }