#include "controlparser.hpp" #include #include #include "scanner.hpp" #include "generator.hpp" namespace Compiler { ControlParser::ControlParser (ErrorHandler& errorHandler, Context& context, Locals& locals, Literals& literals) : Parser (errorHandler, context), mLocals (locals), mLiterals (literals), mLineParser (errorHandler, context, locals, literals, mCodeBlock), mExprParser (errorHandler, context, locals, literals), mState (StartState) { } void ControlParser::appendCode (std::vector& code) const { std::copy (mCode.begin(), mCode.end(), std::back_inserter (code)); } bool ControlParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner) { if (mState==StartState) { if (keyword==Scanner::K_if) { mExprParser.reset(); scanner.scan (mExprParser); mState = IfEndState; return true; } } else if (mState==IfBodyState || mState==IfElseifBodyState || mState==IfElseBodyState) { if (keyword==Scanner::K_endif || keyword==Scanner::K_elseif || keyword==Scanner::K_else) { std::pair entry; if (mState!=IfElseBodyState) mExprParser.append (entry.first); std::copy (mCodeBlock.begin(), mCodeBlock.end(), std::back_inserter (entry.second)); mIfCode.push_back (entry); mCodeBlock.clear(); if (keyword==Scanner::K_endif) { // store code for if-cascade Codes codes; for (IfCodes::reverse_iterator iter (mIfCode.rbegin()); iter!=mIfCode.rend(); ++iter) { Codes block; if (iter!=mIfCode.rbegin()) Generator::jump (iter->second, codes.size()+1); if (!iter->first.empty()) { // if or elseif std::copy (iter->first.begin(), iter->first.end(), std::back_inserter (block)); Generator::jumpOnZero (block, iter->second.size()+1); } std::copy (iter->second.begin(), iter->second.end(), std::back_inserter (block)); std::swap (codes, block); std::copy (block.begin(), block.end(), std::back_inserter (codes)); } std::copy (codes.begin(), codes.end(), std::back_inserter (mCode)); mIfCode.clear(); mState = IfEndifState; } else if (keyword==Scanner::K_elseif) { mExprParser.reset(); scanner.scan (mExprParser); mState = IfElseifEndState; } else if (keyword==Scanner::K_else) { mState = IfElseEndState; } return true; } else if (keyword==Scanner::K_if || keyword==Scanner::K_while) { // nested ControlParser parser (getErrorHandler(), getContext(), mLocals, mLiterals); if (parser.parseKeyword (keyword, loc, scanner)) scanner.scan (parser); parser.appendCode (mCodeBlock); return true; } else { mLineParser.reset(); if (mLineParser.parseKeyword (keyword, loc, scanner)) scanner.scan (mLineParser); return true; } } return Parser::parseKeyword (keyword, loc, scanner); } bool ControlParser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner) { if (code==Scanner::S_newline) { switch (mState) { case IfEndState: mState = IfBodyState; return true; case IfElseifEndState: mState = IfElseifBodyState; return true; case IfElseEndState: mState = IfElseBodyState; return true; case IfBodyState: case IfElseifBodyState: case IfElseBodyState: return true; // empty line case IfEndifState: return false; default: ; } } return Parser::parseSpecial (code, loc, scanner); } void ControlParser::reset() { mCode.clear(); mCodeBlock.clear(); mIfCode.clear(); mState = StartState; } }