You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/components/compiler/scriptparser.cpp

98 lines
2.6 KiB
C++

#include "scriptparser.hpp"
#include "errorhandler.hpp"
#include "scanner.hpp"
#include "skipparser.hpp"
namespace Compiler
{
ScriptParser::ScriptParser(ErrorHandler& errorHandler, const Context& context, Locals& locals, bool end)
: Parser(errorHandler, context)
, mOutput(locals)
, mLineParser(errorHandler, context, locals, mOutput.getLiterals(), mOutput.getCode())
, mControlParser(errorHandler, context, locals, mOutput.getLiterals())
, mEnd(end)
{
}
Interpreter::Program ScriptParser::getProgram() const
{
return mOutput.getProgram();
}
bool ScriptParser::parseName(const std::string& name, const TokenLoc& loc, Scanner& scanner)
{
mLineParser.reset();
if (mLineParser.parseName(name, loc, scanner))
scanner.scan(mLineParser);
return true;
}
bool ScriptParser::parseKeyword(int keyword, const TokenLoc& loc, Scanner& scanner)
{
if (keyword == Scanner::K_while || keyword == Scanner::K_if || keyword == Scanner::K_elseif)
{
mControlParser.reset();
if (mControlParser.parseKeyword(keyword, loc, scanner))
scanner.scan(mControlParser);
mControlParser.appendCode(mOutput.getCode());
return true;
}
/// \todo add an option to disable this nonsense
if (keyword == Scanner::K_endif)
{
// surplus endif
getErrorHandler().warning("endif without matching if/elseif", loc);
SkipParser skip(getErrorHandler(), getContext());
scanner.scan(skip);
return true;
}
if (keyword == Scanner::K_end && mEnd)
{
return false;
}
mLineParser.reset();
if (mLineParser.parseKeyword(keyword, loc, scanner))
scanner.scan(mLineParser);
return true;
}
bool ScriptParser::parseSpecial(int code, const TokenLoc& loc, Scanner& scanner)
{
if (code == Scanner::S_newline) // empty line
return true;
if (code == Scanner::S_open) /// \todo Option to switch this off
{
scanner.putbackSpecial(code, loc);
return parseKeyword(Scanner::K_if, loc, scanner);
}
mLineParser.reset();
if (mLineParser.parseSpecial(code, loc, scanner))
scanner.scan(mLineParser);
return true;
}
void ScriptParser::parseEOF(Scanner& scanner)
{
if (mEnd)
Parser::parseEOF(scanner);
}
void ScriptParser::reset()
{
mLineParser.reset();
mOutput.clear();
}
}