#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(); } }