mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 02:39:43 +00:00
implemented optional arguments
This commit is contained in:
parent
17135a6403
commit
f4e79a48f0
7 changed files with 344 additions and 239 deletions
|
@ -245,6 +245,6 @@ namespace Compiler
|
||||||
mCodeBlock.clear();
|
mCodeBlock.clear();
|
||||||
mIfCode.clear();
|
mIfCode.clear();
|
||||||
mState = StartState;
|
mState = StartState;
|
||||||
|
Parser::reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,9 +190,9 @@ namespace Compiler
|
||||||
popOperator();
|
popOperator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner)
|
int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner)
|
||||||
{
|
{
|
||||||
parseArguments (arguments, scanner, mCode);
|
return parseArguments (arguments, scanner, mCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||||
|
@ -210,6 +210,8 @@ namespace Compiler
|
||||||
|
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
pushIntegerLiteral (value);
|
pushIntegerLiteral (value);
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
return true;
|
return true;
|
||||||
|
@ -231,6 +233,8 @@ namespace Compiler
|
||||||
|
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
pushFloatLiteral (value);
|
pushFloatLiteral (value);
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
return true;
|
return true;
|
||||||
|
@ -253,6 +257,8 @@ namespace Compiler
|
||||||
|
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
std::string name2 = toLower (name);
|
std::string name2 = toLower (name);
|
||||||
|
|
||||||
char type = mLocals.getType (name2);
|
char type = mLocals.getType (name2);
|
||||||
|
@ -301,6 +307,8 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
if (keyword==Scanner::K_getdisabled)
|
if (keyword==Scanner::K_getdisabled)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
|
|
||||||
Generator::getDisabled (mCode, mLiterals, mExplicit);
|
Generator::getDisabled (mCode, mLiterals, mExplicit);
|
||||||
|
@ -313,6 +321,8 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_getdistance)
|
else if (keyword==Scanner::K_getdistance)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments ("c", scanner);
|
parseArguments ("c", scanner);
|
||||||
|
|
||||||
|
@ -333,6 +343,8 @@ namespace Compiler
|
||||||
|
|
||||||
if (extensions->isFunction (keyword, returnType, argumentType, true))
|
if (extensions->isFunction (keyword, returnType, argumentType, true))
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments (argumentType, scanner);
|
parseArguments (argumentType, scanner);
|
||||||
|
|
||||||
|
@ -354,6 +366,8 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
if (keyword==Scanner::K_getsquareroot)
|
if (keyword==Scanner::K_getsquareroot)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments ("f", scanner);
|
parseArguments ("f", scanner);
|
||||||
|
|
||||||
|
@ -365,6 +379,8 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_menumode)
|
else if (keyword==Scanner::K_menumode)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
|
|
||||||
Generator::menuMode (mCode);
|
Generator::menuMode (mCode);
|
||||||
|
@ -375,6 +391,8 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_random)
|
else if (keyword==Scanner::K_random)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments ("l", scanner);
|
parseArguments ("l", scanner);
|
||||||
|
|
||||||
|
@ -386,6 +404,8 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_scriptrunning)
|
else if (keyword==Scanner::K_scriptrunning)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments ("c", scanner);
|
parseArguments ("c", scanner);
|
||||||
|
|
||||||
|
@ -397,6 +417,8 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_getdistance)
|
else if (keyword==Scanner::K_getdistance)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments ("c", scanner);
|
parseArguments ("c", scanner);
|
||||||
|
|
||||||
|
@ -408,6 +430,8 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_getsecondspassed)
|
else if (keyword==Scanner::K_getsecondspassed)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
|
|
||||||
Generator::getSecondsPassed (mCode);
|
Generator::getSecondsPassed (mCode);
|
||||||
|
@ -418,6 +442,8 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_getdisabled)
|
else if (keyword==Scanner::K_getdisabled)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
|
|
||||||
Generator::getDisabled (mCode, mLiterals, "");
|
Generator::getDisabled (mCode, mLiterals, "");
|
||||||
|
@ -431,6 +457,8 @@ namespace Compiler
|
||||||
// check for custom extensions
|
// check for custom extensions
|
||||||
if (const Extensions *extensions = getContext().getExtensions())
|
if (const Extensions *extensions = getContext().getExtensions())
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
char returnType;
|
char returnType;
|
||||||
std::string argumentType;
|
std::string argumentType;
|
||||||
|
|
||||||
|
@ -580,6 +608,7 @@ namespace Compiler
|
||||||
mFirst = true;
|
mFirst = true;
|
||||||
mExplicit.clear();
|
mExplicit.clear();
|
||||||
mRefOp = false;
|
mRefOp = false;
|
||||||
|
Parser::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
char ExprParser::append (std::vector<Interpreter::Type_Code>& code)
|
char ExprParser::append (std::vector<Interpreter::Type_Code>& code)
|
||||||
|
@ -605,9 +634,12 @@ namespace Compiler
|
||||||
return mOperands[0];
|
return mOperands[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner,
|
int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner,
|
||||||
std::vector<Interpreter::Type_Code>& code, bool invert)
|
std::vector<Interpreter::Type_Code>& code, bool invert)
|
||||||
{
|
{
|
||||||
|
bool optional = false;
|
||||||
|
bool optionalCount = 0;
|
||||||
|
|
||||||
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
|
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
|
||||||
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
|
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
|
||||||
|
|
||||||
|
@ -616,12 +648,23 @@ namespace Compiler
|
||||||
for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end();
|
for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end();
|
||||||
++iter)
|
++iter)
|
||||||
{
|
{
|
||||||
if (*iter=='S' || *iter=='c')
|
if (*iter=='/')
|
||||||
|
{
|
||||||
|
optional = true;
|
||||||
|
}
|
||||||
|
else if (*iter=='S' || *iter=='c')
|
||||||
{
|
{
|
||||||
stringParser.reset();
|
stringParser.reset();
|
||||||
|
|
||||||
|
if (optional)
|
||||||
|
stringParser.setOptional (true);
|
||||||
|
|
||||||
if (*iter=='c') stringParser.smashCase();
|
if (*iter=='c') stringParser.smashCase();
|
||||||
scanner.scan (stringParser);
|
scanner.scan (stringParser);
|
||||||
|
|
||||||
|
if (optional && stringParser.isEmpty())
|
||||||
|
break;
|
||||||
|
|
||||||
if (invert)
|
if (invert)
|
||||||
{
|
{
|
||||||
std::vector<Interpreter::Type_Code> tmp;
|
std::vector<Interpreter::Type_Code> tmp;
|
||||||
|
@ -631,12 +674,22 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
stringParser.append (code);
|
stringParser.append (code);
|
||||||
|
|
||||||
|
if (optional)
|
||||||
|
++optionalCount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parser.reset();
|
parser.reset();
|
||||||
|
|
||||||
|
if (optional)
|
||||||
|
parser.setOptional (true);
|
||||||
|
|
||||||
scanner.scan (parser);
|
scanner.scan (parser);
|
||||||
|
|
||||||
|
if (optional && parser.isEmpty())
|
||||||
|
break;
|
||||||
|
|
||||||
std::vector<Interpreter::Type_Code> tmp;
|
std::vector<Interpreter::Type_Code> tmp;
|
||||||
|
|
||||||
char type = parser.append (tmp);
|
char type = parser.append (tmp);
|
||||||
|
@ -648,6 +701,9 @@ namespace Compiler
|
||||||
stack.push (tmp);
|
stack.push (tmp);
|
||||||
else
|
else
|
||||||
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
|
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
|
||||||
|
|
||||||
|
if (optional)
|
||||||
|
++optionalCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,6 +715,7 @@ namespace Compiler
|
||||||
|
|
||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return optionalCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace Compiler
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
void parseArguments (const std::string& arguments, Scanner& scanner);
|
int parseArguments (const std::string& arguments, Scanner& scanner);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -92,12 +92,14 @@ namespace Compiler
|
||||||
///< Generate code for parsed expression.
|
///< Generate code for parsed expression.
|
||||||
/// \return Type ('l': integer, 'f': float)
|
/// \return Type ('l': integer, 'f': float)
|
||||||
|
|
||||||
void parseArguments (const std::string& arguments, Scanner& scanner,
|
int parseArguments (const std::string& arguments, Scanner& scanner,
|
||||||
std::vector<Interpreter::Type_Code>& code, bool invert = false);
|
std::vector<Interpreter::Type_Code>& code, bool invert = false);
|
||||||
///< Parse sequence of arguments specified by \a arguments.
|
///< Parse sequence of arguments specified by \a arguments.
|
||||||
/// \param arguments Each character represents one arguments ('l': integer,
|
/// \param arguments Each character represents one arguments ('l': integer,
|
||||||
/// 'f': float, 'S': string, 'c': string (case smashed))
|
/// 'f': float, 'S': string, 'c': string (case smashed), '/': following arguments are
|
||||||
|
/// optional)
|
||||||
/// \param invert Store arguments in reverted order.
|
/// \param invert Store arguments in reverted order.
|
||||||
|
/// \return number of optional arguments
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,6 @@ namespace Compiler
|
||||||
mState = BeginState;
|
mState = BeginState;
|
||||||
mName.clear();
|
mName.clear();
|
||||||
mScriptParser.reset();
|
mScriptParser.reset();
|
||||||
|
Parser::reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::Parser (ErrorHandler& errorHandler, Context& context)
|
Parser::Parser (ErrorHandler& errorHandler, Context& context)
|
||||||
: mErrorHandler (errorHandler), mContext (context)
|
: mErrorHandler (errorHandler), mContext (context), mOptional (false), mEmpty (true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
|
@ -79,7 +79,9 @@ namespace Compiler
|
||||||
|
|
||||||
bool Parser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
bool Parser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
|
if (!(mOptional && mEmpty))
|
||||||
reportSeriousError ("Unexpected numeric value", loc);
|
reportSeriousError ("Unexpected numeric value", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +92,9 @@ namespace Compiler
|
||||||
|
|
||||||
bool Parser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner)
|
bool Parser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
|
if (!(mOptional && mEmpty))
|
||||||
reportSeriousError ("Unexpected floating point value", loc);
|
reportSeriousError ("Unexpected floating point value", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +106,9 @@ namespace Compiler
|
||||||
bool Parser::parseName (const std::string& name, const TokenLoc& loc,
|
bool Parser::parseName (const std::string& name, const TokenLoc& loc,
|
||||||
Scanner& scanner)
|
Scanner& scanner)
|
||||||
{
|
{
|
||||||
|
if (!(mOptional && mEmpty))
|
||||||
reportSeriousError ("Unexpected name", loc);
|
reportSeriousError ("Unexpected name", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +119,9 @@ namespace Compiler
|
||||||
|
|
||||||
bool Parser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
bool Parser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
|
if (!(mOptional && mEmpty))
|
||||||
reportSeriousError ("Unexpected keyword", loc);
|
reportSeriousError ("Unexpected keyword", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +132,9 @@ namespace Compiler
|
||||||
|
|
||||||
bool Parser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
bool Parser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
|
if (!(mOptional && mEmpty))
|
||||||
reportSeriousError ("Unexpected special token", loc);
|
reportSeriousError ("Unexpected special token", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,5 +146,25 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
reportEOF();
|
reportEOF();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
void Parser::reset()
|
||||||
|
{
|
||||||
|
mOptional = false;
|
||||||
|
mEmpty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::setOptional (bool optional)
|
||||||
|
{
|
||||||
|
mOptional = optional;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::start()
|
||||||
|
{
|
||||||
|
mEmpty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parser::isEmpty() const
|
||||||
|
{
|
||||||
|
return mEmpty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
ErrorHandler& mErrorHandler;
|
ErrorHandler& mErrorHandler;
|
||||||
Context& mContext;
|
Context& mContext;
|
||||||
|
bool mOptional;
|
||||||
|
bool mEmpty;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -84,6 +86,19 @@ namespace Compiler
|
||||||
///< Handle EOF token.
|
///< Handle EOF token.
|
||||||
///
|
///
|
||||||
/// - Default-implementation: Report an error.
|
/// - Default-implementation: Report an error.
|
||||||
|
|
||||||
|
virtual void reset();
|
||||||
|
///< Reset parser to clean state.
|
||||||
|
|
||||||
|
void setOptional (bool optional);
|
||||||
|
///< Optional mode: If nothign has been parsed yet and an unexpected token is delivered, stop
|
||||||
|
/// parsing without raising an exception (after a reset the parser is in non-optional mode).
|
||||||
|
|
||||||
|
void start();
|
||||||
|
///< Mark parser as non-empty (at least one token has been parser).
|
||||||
|
|
||||||
|
bool isEmpty() const;
|
||||||
|
///< Has anything been parsed?
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
if (mState==StartState || mState==CommaState)
|
if (mState==StartState || mState==CommaState)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
if (mSmashCase)
|
if (mSmashCase)
|
||||||
Generator::pushString (mCode, mLiterals, toLower (name));
|
Generator::pushString (mCode, mLiterals, toLower (name));
|
||||||
else
|
else
|
||||||
|
@ -52,6 +53,7 @@ namespace Compiler
|
||||||
mState = StartState;
|
mState = StartState;
|
||||||
mCode.clear();
|
mCode.clear();
|
||||||
mSmashCase = false;
|
mSmashCase = false;
|
||||||
|
Parser::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringParser::smashCase()
|
void StringParser::smashCase()
|
||||||
|
@ -59,4 +61,3 @@ namespace Compiler
|
||||||
mSmashCase = true;
|
mSmashCase = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue