Discard additional tokens in non-expression contexts

macos_ci_fix
Evil Eye 1 year ago
parent c9d4ca5320
commit 02775c490b

@ -19,7 +19,16 @@ namespace
mErrorHandler.reset(); mErrorHandler.reset();
std::istringstream input(scriptBody); std::istringstream input(scriptBody);
Compiler::Scanner scanner(mErrorHandler, input, mCompilerContext.getExtensions()); Compiler::Scanner scanner(mErrorHandler, input, mCompilerContext.getExtensions());
try
{
scanner.scan(mParser); scanner.scan(mParser);
}
catch (...)
{
if (!shouldFail)
logErrors();
throw;
}
if (mErrorHandler.isGood()) if (mErrorHandler.isGood())
return CompiledScript(mParser.getProgram(), mParser.getLocals()); return CompiledScript(mParser.getProgram(), mParser.getLocals());
else if (!shouldFail) else if (!shouldFail)
@ -385,6 +394,12 @@ if (player->GameHour == 10)
set player->GameHour to 20 set player->GameHour to 20
endif endif
End)mwscript";
const std::string sIssue4996 = R"mwscript(---Begin issue4996
player-> SetPos, Z, myZ + 50
End)mwscript"; End)mwscript";
const std::string sIssue5087 = R"mwscript(Begin Begin const std::string sIssue5087 = R"mwscript(Begin Begin
@ -457,6 +472,9 @@ set a to 1
-+'\/.,><$@---!=\/?--------(){}------ show a -+'\/.,><$@---!=\/?--------(){}------ show a
( GetDisabled == 1 )
GetDisabled == 1
End)mwscript"; End)mwscript";
TEST_F(MWScriptTest, mwscript_test_invalid) TEST_F(MWScriptTest, mwscript_test_invalid)
@ -810,6 +828,12 @@ End)mwscript";
EXPECT_FALSE(!compile(sIssue4888)); EXPECT_FALSE(!compile(sIssue4888));
} }
TEST_F(MWScriptTest, mwscript_test_4996)
{
registerExtensions();
EXPECT_FALSE(!compile(sIssue4996));
}
TEST_F(MWScriptTest, mwscript_test_5087) TEST_F(MWScriptTest, mwscript_test_5087)
{ {
registerExtensions(); registerExtensions();

@ -271,18 +271,14 @@ namespace Compiler
mCode.insert(mCode.end(), code.begin(), code.end()); mCode.insert(mCode.end(), code.begin(), code.end());
extensions->generateInstructionCode(keyword, mCode, mLiterals, mExplicit, optionals); extensions->generateInstructionCode(keyword, mCode, mLiterals, mExplicit, optionals);
SkipParser skip(getErrorHandler(), getContext(), true);
scanner.scan(skip);
mState = EndState; mState = EndState;
return true; return true;
} }
}
if (const Extensions* extensions = getContext().getExtensions())
{
char returnType; char returnType;
std::string argumentType;
bool hasExplicit = mState == ExplicitState;
if (extensions->isFunction(keyword, returnType, argumentType, hasExplicit)) if (extensions->isFunction(keyword, returnType, argumentType, hasExplicit))
{ {
if (!hasExplicit && mState == ExplicitState) if (!hasExplicit && mState == ExplicitState)
@ -302,6 +298,9 @@ namespace Compiler
int optionals = mExprParser.parseArguments(argumentType, scanner, code, keyword); int optionals = mExprParser.parseArguments(argumentType, scanner, code, keyword);
mCode.insert(mCode.end(), code.begin(), code.end()); mCode.insert(mCode.end(), code.begin(), code.end());
extensions->generateFunctionCode(keyword, mCode, mLiterals, mExplicit, optionals); extensions->generateFunctionCode(keyword, mCode, mLiterals, mExplicit, optionals);
SkipParser skip(getErrorHandler(), getContext(), true);
scanner.scan(skip);
} }
mState = EndState; mState = EndState;
return true; return true;

@ -1,39 +1,55 @@
#include "skipparser.hpp" #include "skipparser.hpp"
#include "errorhandler.hpp"
#include "scanner.hpp" #include "scanner.hpp"
namespace Compiler namespace Compiler
{ {
SkipParser::SkipParser(ErrorHandler& errorHandler, const Context& context) SkipParser::SkipParser(ErrorHandler& errorHandler, const Context& context, bool reportStrayArguments)
: Parser(errorHandler, context) : Parser(errorHandler, context)
, mReportStrayArguments(reportStrayArguments)
{ {
} }
void SkipParser::reportStrayArgument(const TokenLoc& loc)
{
if (mReportStrayArguments)
getErrorHandler().warning("Extra argument", loc);
}
bool SkipParser::parseInt(int value, const TokenLoc& loc, Scanner& scanner) bool SkipParser::parseInt(int value, const TokenLoc& loc, Scanner& scanner)
{ {
reportStrayArgument(loc);
return true; return true;
} }
bool SkipParser::parseFloat(float value, const TokenLoc& loc, Scanner& scanner) bool SkipParser::parseFloat(float value, const TokenLoc& loc, Scanner& scanner)
{ {
reportStrayArgument(loc);
return true; return true;
} }
bool SkipParser::parseName(const std::string& name, const TokenLoc& loc, Scanner& scanner) bool SkipParser::parseName(const std::string& name, const TokenLoc& loc, Scanner& scanner)
{ {
reportStrayArgument(loc);
return true; return true;
} }
bool SkipParser::parseKeyword(int keyword, const TokenLoc& loc, Scanner& scanner) bool SkipParser::parseKeyword(int keyword, const TokenLoc& loc, Scanner& scanner)
{ {
reportStrayArgument(loc);
return true; return true;
} }
bool SkipParser::parseSpecial(int code, const TokenLoc& loc, Scanner& scanner) bool SkipParser::parseSpecial(int code, const TokenLoc& loc, Scanner& scanner)
{ {
if (code == Scanner::S_newline) if (code == Scanner::S_newline)
{
if (mReportStrayArguments)
scanner.putbackSpecial(code, loc);
return false; return false;
}
reportStrayArgument(loc);
return true; return true;
} }
} }

@ -11,8 +11,12 @@ namespace Compiler
class SkipParser : public Parser class SkipParser : public Parser
{ {
bool mReportStrayArguments;
void reportStrayArgument(const TokenLoc& loc);
public: public:
SkipParser(ErrorHandler& errorHandler, const Context& context); SkipParser(ErrorHandler& errorHandler, const Context& context, bool reportStrayArguments = false);
bool parseInt(int value, const TokenLoc& loc, Scanner& scanner) override; bool parseInt(int value, const TokenLoc& loc, Scanner& scanner) override;
///< Handle an int token. ///< Handle an int token.

Loading…
Cancel
Save