mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-28 21:07:59 +03:00
added if control structure
This commit is contained in:
parent
73f9436ed9
commit
69342f320d
9 changed files with 366 additions and 3 deletions
165
components/compiler/controlparser.cpp
Normal file
165
components/compiler/controlparser.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
|
||||
#include "controlparser.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#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<Interpreter::Type_Code>& 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<Codes, Codes> 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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue