Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
3.9 kB · 132 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133#include "fileparser.hpp"
#include <components/misc/strings/algorithm.hpp>
#include "scanner.hpp"#include "tokenloc.hpp"
namespace Compiler{ FileParser::FileParser(ErrorHandler& errorHandler, Context& context) : Parser(errorHandler, context) , mScriptParser(errorHandler, context, mLocals, true) , mState(BeginState) { }
Interpreter::Program FileParser::getProgram() const { return mScriptParser.getProgram(); }
const Locals& FileParser::getLocals() const { return mLocals; }
bool FileParser::parseName(const std::string& name, const TokenLoc& loc, Scanner& scanner) { if (mState == NameState) { mName = name; mState = BeginCompleteState; return true; }
if (mState == EndNameState) { // optional repeated name after end statement if (!Misc::StringUtils::ciEqual(mName, name)) reportWarning("Names for script " + mName + " do not match", loc);
mState = EndCompleteState; return false; // we are stopping here, because there might be more garbage on the end line, // that we must ignore. // /// \todo allow this workaround to be disabled for newer scripts }
if (mState == BeginCompleteState) { reportWarning("Stray string (" + name + ") after begin statement", loc); return true; }
return Parser::parseName(name, loc, scanner); }
bool FileParser::parseKeyword(int keyword, const TokenLoc& loc, Scanner& scanner) { if (mState == BeginState && keyword == Scanner::K_begin) { mState = NameState; scanner.enableTolerantNames(); /// \todo disable return true; }
if (mState == NameState) { // keywords can be used as script names too. Thank you Morrowind for another // syntactic perversity :( mName = loc.mLiteral; mState = BeginCompleteState; return true; }
if (mState == EndNameState) { // optional repeated name after end statement if (!Misc::StringUtils::ciEqual(mName, loc.mLiteral)) reportWarning("Names for script " + mName + " do not match", loc);
mState = EndCompleteState; return false; // we are stopping here, because there might be more garbage on the end line, // that we must ignore. // /// \todo allow this workaround to be disabled for newer scripts }
return Parser::parseKeyword(keyword, loc, scanner); }
bool FileParser::parseSpecial(int code, const TokenLoc& loc, Scanner& scanner) { if (code == Scanner::S_newline) { if (mState == BeginState) return true; if (mState == BeginCompleteState) { // parse the script body mScriptParser.reset();
scanner.scan(mScriptParser);
mState = EndNameState; return true; }
if (mState == EndCompleteState || mState == EndNameState) { // we are done here -> ignore the rest of the script return false; } }
return Parser::parseSpecial(code, loc, scanner); }
void FileParser::parseEOF(Scanner& scanner) { if (mState != EndNameState && mState != EndCompleteState) Parser::parseEOF(scanner); }
void FileParser::reset() { mState = BeginState; mName.clear(); mScriptParser.reset(); Parser::reset(); }}