mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-19 07:39:46 +00:00
implemented optional arguments
This commit is contained in:
parent
17135a6403
commit
f4e79a48f0
7 changed files with 344 additions and 239 deletions
|
@ -17,21 +17,21 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
std::pair<Codes, Codes> entry;
|
std::pair<Codes, Codes> entry;
|
||||||
|
|
||||||
if (mState!=IfElseBodyState)
|
if (mState!=IfElseBodyState)
|
||||||
mExprParser.append (entry.first);
|
mExprParser.append (entry.first);
|
||||||
|
|
||||||
std::copy (mCodeBlock.begin(), mCodeBlock.end(),
|
std::copy (mCodeBlock.begin(), mCodeBlock.end(),
|
||||||
std::back_inserter (entry.second));
|
std::back_inserter (entry.second));
|
||||||
|
|
||||||
mIfCode.push_back (entry);
|
mIfCode.push_back (entry);
|
||||||
|
|
||||||
mCodeBlock.clear();
|
mCodeBlock.clear();
|
||||||
|
|
||||||
if (keyword==Scanner::K_endif)
|
if (keyword==Scanner::K_endif)
|
||||||
{
|
{
|
||||||
// store code for if-cascade
|
// store code for if-cascade
|
||||||
Codes codes;
|
Codes codes;
|
||||||
|
|
||||||
for (IfCodes::reverse_iterator iter (mIfCode.rbegin());
|
for (IfCodes::reverse_iterator iter (mIfCode.rbegin());
|
||||||
iter!=mIfCode.rend(); ++iter)
|
iter!=mIfCode.rend(); ++iter)
|
||||||
{
|
{
|
||||||
|
@ -47,17 +47,17 @@ namespace Compiler
|
||||||
std::back_inserter (block));
|
std::back_inserter (block));
|
||||||
Generator::jumpOnZero (block, iter->second.size()+1);
|
Generator::jumpOnZero (block, iter->second.size()+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::copy (iter->second.begin(), iter->second.end(),
|
std::copy (iter->second.begin(), iter->second.end(),
|
||||||
std::back_inserter (block));
|
std::back_inserter (block));
|
||||||
|
|
||||||
std::swap (codes, block);
|
std::swap (codes, block);
|
||||||
|
|
||||||
std::copy (block.begin(), block.end(), std::back_inserter (codes));
|
std::copy (block.begin(), block.end(), std::back_inserter (codes));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::copy (codes.begin(), codes.end(), std::back_inserter (mCode));
|
std::copy (codes.begin(), codes.end(), std::back_inserter (mCode));
|
||||||
|
|
||||||
mIfCode.clear();
|
mIfCode.clear();
|
||||||
mState = IfEndifState;
|
mState = IfEndifState;
|
||||||
}
|
}
|
||||||
|
@ -66,36 +66,36 @@ namespace Compiler
|
||||||
mExprParser.reset();
|
mExprParser.reset();
|
||||||
scanner.scan (mExprParser);
|
scanner.scan (mExprParser);
|
||||||
|
|
||||||
mState = IfElseifEndState;
|
mState = IfElseifEndState;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_else)
|
else if (keyword==Scanner::K_else)
|
||||||
{
|
{
|
||||||
mState = IfElseEndState;
|
mState = IfElseEndState;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_if || keyword==Scanner::K_while)
|
else if (keyword==Scanner::K_if || keyword==Scanner::K_while)
|
||||||
{
|
{
|
||||||
// nested
|
// nested
|
||||||
ControlParser parser (getErrorHandler(), getContext(), mLocals, mLiterals);
|
ControlParser parser (getErrorHandler(), getContext(), mLocals, mLiterals);
|
||||||
|
|
||||||
if (parser.parseKeyword (keyword, loc, scanner))
|
if (parser.parseKeyword (keyword, loc, scanner))
|
||||||
scanner.scan (parser);
|
scanner.scan (parser);
|
||||||
|
|
||||||
parser.appendCode (mCodeBlock);
|
parser.appendCode (mCodeBlock);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mLineParser.reset();
|
mLineParser.reset();
|
||||||
if (mLineParser.parseKeyword (keyword, loc, scanner))
|
if (mLineParser.parseKeyword (keyword, loc, scanner))
|
||||||
scanner.scan (mLineParser);
|
scanner.scan (mLineParser);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,24 +104,24 @@ namespace Compiler
|
||||||
if (keyword==Scanner::K_endwhile)
|
if (keyword==Scanner::K_endwhile)
|
||||||
{
|
{
|
||||||
Codes loop;
|
Codes loop;
|
||||||
|
|
||||||
Codes expr;
|
Codes expr;
|
||||||
mExprParser.append (expr);
|
mExprParser.append (expr);
|
||||||
|
|
||||||
Generator::jump (loop, -mCodeBlock.size()-expr.size());
|
Generator::jump (loop, -mCodeBlock.size()-expr.size());
|
||||||
|
|
||||||
std::copy (expr.begin(), expr.end(), std::back_inserter (mCode));
|
std::copy (expr.begin(), expr.end(), std::back_inserter (mCode));
|
||||||
|
|
||||||
Codes skip;
|
Codes skip;
|
||||||
|
|
||||||
Generator::jumpOnZero (skip, mCodeBlock.size()+loop.size()+1);
|
Generator::jumpOnZero (skip, mCodeBlock.size()+loop.size()+1);
|
||||||
|
|
||||||
std::copy (skip.begin(), skip.end(), std::back_inserter (mCode));
|
std::copy (skip.begin(), skip.end(), std::back_inserter (mCode));
|
||||||
|
|
||||||
std::copy (mCodeBlock.begin(), mCodeBlock.end(), std::back_inserter (mCode));
|
std::copy (mCodeBlock.begin(), mCodeBlock.end(), std::back_inserter (mCode));
|
||||||
|
|
||||||
Codes loop2;
|
Codes loop2;
|
||||||
|
|
||||||
Generator::jump (loop2, -mCodeBlock.size()-expr.size()-skip.size());
|
Generator::jump (loop2, -mCodeBlock.size()-expr.size()-skip.size());
|
||||||
|
|
||||||
if (loop.size()!=loop2.size())
|
if (loop.size()!=loop2.size())
|
||||||
|
@ -129,31 +129,31 @@ namespace Compiler
|
||||||
"internal compiler error: failed to generate a while loop");
|
"internal compiler error: failed to generate a while loop");
|
||||||
|
|
||||||
std::copy (loop2.begin(), loop2.end(), std::back_inserter (mCode));
|
std::copy (loop2.begin(), loop2.end(), std::back_inserter (mCode));
|
||||||
|
|
||||||
mState = WhileEndwhileState;
|
mState = WhileEndwhileState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_if || keyword==Scanner::K_while)
|
else if (keyword==Scanner::K_if || keyword==Scanner::K_while)
|
||||||
{
|
{
|
||||||
// nested
|
// nested
|
||||||
ControlParser parser (getErrorHandler(), getContext(), mLocals, mLiterals);
|
ControlParser parser (getErrorHandler(), getContext(), mLocals, mLiterals);
|
||||||
|
|
||||||
if (parser.parseKeyword (keyword, loc, scanner))
|
if (parser.parseKeyword (keyword, loc, scanner))
|
||||||
scanner.scan (parser);
|
scanner.scan (parser);
|
||||||
|
|
||||||
parser.appendCode (mCodeBlock);
|
parser.appendCode (mCodeBlock);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mLineParser.reset();
|
mLineParser.reset();
|
||||||
if (mLineParser.parseKeyword (keyword, loc, scanner))
|
if (mLineParser.parseKeyword (keyword, loc, scanner))
|
||||||
scanner.scan (mLineParser);
|
scanner.scan (mLineParser);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,14 +164,14 @@ namespace Compiler
|
||||||
mExprParser (errorHandler, context, locals, literals),
|
mExprParser (errorHandler, context, locals, literals),
|
||||||
mState (StartState)
|
mState (StartState)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlParser::appendCode (std::vector<Interpreter::Type_Code>& code) const
|
void ControlParser::appendCode (std::vector<Interpreter::Type_Code>& code) const
|
||||||
{
|
{
|
||||||
std::copy (mCode.begin(), mCode.end(), std::back_inserter (code));
|
std::copy (mCode.begin(), mCode.end(), std::back_inserter (code));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ControlParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
bool ControlParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
if (mState==StartState)
|
if (mState==StartState)
|
||||||
|
@ -190,20 +190,20 @@ namespace Compiler
|
||||||
scanner.scan (mExprParser);
|
scanner.scan (mExprParser);
|
||||||
|
|
||||||
mState = WhileEndState;
|
mState = WhileEndState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mState==IfBodyState || mState==IfElseifBodyState || mState==IfElseBodyState)
|
else if (mState==IfBodyState || mState==IfElseifBodyState || mState==IfElseBodyState)
|
||||||
{
|
{
|
||||||
if (parseIfBody (keyword, loc, scanner))
|
if (parseIfBody (keyword, loc, scanner))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (mState==WhileBodyState)
|
else if (mState==WhileBodyState)
|
||||||
{
|
{
|
||||||
if ( parseWhileBody (keyword, loc, scanner))
|
if ( parseWhileBody (keyword, loc, scanner))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseKeyword (keyword, loc, scanner);
|
return Parser::parseKeyword (keyword, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,24 +218,24 @@ namespace Compiler
|
||||||
case IfElseEndState: mState = IfElseBodyState; return true;
|
case IfElseEndState: mState = IfElseBodyState; return true;
|
||||||
|
|
||||||
case WhileEndState: mState = WhileBodyState; return true;
|
case WhileEndState: mState = WhileBodyState; return true;
|
||||||
|
|
||||||
case IfBodyState:
|
case IfBodyState:
|
||||||
case IfElseifBodyState:
|
case IfElseifBodyState:
|
||||||
case IfElseBodyState:
|
case IfElseBodyState:
|
||||||
case WhileBodyState:
|
case WhileBodyState:
|
||||||
|
|
||||||
return true; // empty line
|
return true; // empty line
|
||||||
|
|
||||||
case IfEndifState:
|
case IfEndifState:
|
||||||
case WhileEndwhileState:
|
case WhileEndwhileState:
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseSpecial (code, loc, scanner);
|
return Parser::parseSpecial (code, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +245,6 @@ namespace Compiler
|
||||||
mCodeBlock.clear();
|
mCodeBlock.clear();
|
||||||
mIfCode.clear();
|
mIfCode.clear();
|
||||||
mState = StartState;
|
mState = StartState;
|
||||||
|
Parser::reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,33 +22,33 @@ namespace Compiler
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case '(':
|
case '(':
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 'e': // ==
|
case 'e': // ==
|
||||||
case 'n': // !=
|
case 'n': // !=
|
||||||
case 'l': // <
|
case 'l': // <
|
||||||
case 'L': // <=
|
case 'L': // <=
|
||||||
case 'g': // <
|
case 'g': // <
|
||||||
case 'G': // >=
|
case 'G': // >=
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
case '-':
|
case '-':
|
||||||
|
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
case '*':
|
case '*':
|
||||||
case '/':
|
case '/':
|
||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
|
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ namespace Compiler
|
||||||
assert (Index<static_cast<int> (mOperands.size()));
|
assert (Index<static_cast<int> (mOperands.size()));
|
||||||
return mOperands[mOperands.size()-1-Index];
|
return mOperands[mOperands.size()-1-Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
char ExprParser::getOperator() const
|
char ExprParser::getOperator() const
|
||||||
{
|
{
|
||||||
assert (!mOperators.empty());
|
assert (!mOperators.empty());
|
||||||
|
@ -70,27 +70,27 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
return std::find (mOperators.begin(), mOperators.end(), '(')!=mOperators.end();
|
return std::find (mOperators.begin(), mOperators.end(), '(')!=mOperators.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::popOperator()
|
void ExprParser::popOperator()
|
||||||
{
|
{
|
||||||
assert (!mOperators.empty());
|
assert (!mOperators.empty());
|
||||||
mOperators.resize (mOperators.size()-1);
|
mOperators.resize (mOperators.size()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::popOperand()
|
void ExprParser::popOperand()
|
||||||
{
|
{
|
||||||
assert (!mOperands.empty());
|
assert (!mOperands.empty());
|
||||||
mOperands.resize (mOperands.size()-1);
|
mOperands.resize (mOperands.size()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::replaceBinaryOperands()
|
void ExprParser::replaceBinaryOperands()
|
||||||
{
|
{
|
||||||
char t1 = getOperandType (1);
|
char t1 = getOperandType (1);
|
||||||
char t2 = getOperandType();
|
char t2 = getOperandType();
|
||||||
|
|
||||||
popOperand();
|
popOperand();
|
||||||
popOperand();
|
popOperand();
|
||||||
|
|
||||||
if (t1==t2)
|
if (t1==t2)
|
||||||
mOperands.push_back (t1);
|
mOperands.push_back (t1);
|
||||||
else if (t1=='f' || t2=='f')
|
else if (t1=='f' || t2=='f')
|
||||||
|
@ -102,59 +102,59 @@ namespace Compiler
|
||||||
void ExprParser::pop()
|
void ExprParser::pop()
|
||||||
{
|
{
|
||||||
char op = getOperator();
|
char op = getOperator();
|
||||||
|
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case 'm':
|
case 'm':
|
||||||
|
|
||||||
Generator::negate (mCode, getOperandType());
|
Generator::negate (mCode, getOperandType());
|
||||||
popOperator();
|
popOperator();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
|
|
||||||
Generator::add (mCode, getOperandType (1), getOperandType());
|
Generator::add (mCode, getOperandType (1), getOperandType());
|
||||||
popOperator();
|
popOperator();
|
||||||
replaceBinaryOperands();
|
replaceBinaryOperands();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '-':
|
case '-':
|
||||||
|
|
||||||
Generator::sub (mCode, getOperandType (1), getOperandType());
|
Generator::sub (mCode, getOperandType (1), getOperandType());
|
||||||
popOperator();
|
popOperator();
|
||||||
replaceBinaryOperands();
|
replaceBinaryOperands();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '*':
|
case '*':
|
||||||
|
|
||||||
Generator::mul (mCode, getOperandType (1), getOperandType());
|
Generator::mul (mCode, getOperandType (1), getOperandType());
|
||||||
popOperator();
|
popOperator();
|
||||||
replaceBinaryOperands();
|
replaceBinaryOperands();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '/':
|
case '/':
|
||||||
|
|
||||||
Generator::div (mCode, getOperandType (1), getOperandType());
|
Generator::div (mCode, getOperandType (1), getOperandType());
|
||||||
popOperator();
|
popOperator();
|
||||||
replaceBinaryOperands();
|
replaceBinaryOperands();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'n':
|
case 'n':
|
||||||
case 'l':
|
case 'l':
|
||||||
case 'L':
|
case 'L':
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
|
|
||||||
Generator::compare (mCode, op, getOperandType (1), getOperandType());
|
Generator::compare (mCode, op, getOperandType (1), getOperandType());
|
||||||
popOperator();
|
popOperator();
|
||||||
popOperand();
|
popOperand();
|
||||||
popOperand();
|
popOperand();
|
||||||
mOperands.push_back ('l');
|
mOperands.push_back ('l');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
throw std::logic_error ("unknown operator");
|
throw std::logic_error ("unknown operator");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,36 +165,36 @@ namespace Compiler
|
||||||
mOperands.push_back ('l');
|
mOperands.push_back ('l');
|
||||||
Generator::pushInt (mCode, mLiterals, value);
|
Generator::pushInt (mCode, mLiterals, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::pushFloatLiteral (float value)
|
void ExprParser::pushFloatLiteral (float value)
|
||||||
{
|
{
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
mOperands.push_back ('f');
|
mOperands.push_back ('f');
|
||||||
Generator::pushFloat (mCode, mLiterals, value);
|
Generator::pushFloat (mCode, mLiterals, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::pushBinaryOperator (char c)
|
void ExprParser::pushBinaryOperator (char c)
|
||||||
{
|
{
|
||||||
while (!mOperators.empty() && getPriority (getOperator())>=getPriority (c))
|
while (!mOperators.empty() && getPriority (getOperator())>=getPriority (c))
|
||||||
pop();
|
pop();
|
||||||
|
|
||||||
mOperators.push_back (c);
|
mOperators.push_back (c);
|
||||||
mNextOperand = true;
|
mNextOperand = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::close()
|
void ExprParser::close()
|
||||||
{
|
{
|
||||||
while (getOperator()!='(')
|
while (getOperator()!='(')
|
||||||
pop();
|
pop();
|
||||||
|
|
||||||
popOperator();
|
popOperator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner)
|
int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner)
|
||||||
{
|
{
|
||||||
parseArguments (arguments, scanner, mCode);
|
return parseArguments (arguments, scanner, mCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||||
Literals& literals, bool argument)
|
Literals& literals, bool argument)
|
||||||
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
|
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
|
||||||
|
@ -205,11 +205,13 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
if (!mExplicit.empty())
|
if (!mExplicit.empty())
|
||||||
return Parser::parseInt (value, loc, scanner);
|
return Parser::parseInt (value, loc, scanner);
|
||||||
|
|
||||||
mFirst = false;
|
mFirst = false;
|
||||||
|
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
pushIntegerLiteral (value);
|
pushIntegerLiteral (value);
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
return true;
|
return true;
|
||||||
|
@ -228,13 +230,15 @@ namespace Compiler
|
||||||
return Parser::parseFloat (value, loc, scanner);
|
return Parser::parseFloat (value, loc, scanner);
|
||||||
|
|
||||||
mFirst = false;
|
mFirst = false;
|
||||||
|
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
pushFloatLiteral (value);
|
pushFloatLiteral (value);
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// no comma was used between arguments
|
// no comma was used between arguments
|
||||||
|
@ -252,29 +256,31 @@ namespace Compiler
|
||||||
mFirst = false;
|
mFirst = false;
|
||||||
|
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
std::string name2 = toLower (name);
|
std::string name2 = toLower (name);
|
||||||
|
|
||||||
char type = mLocals.getType (name2);
|
char type = mLocals.getType (name2);
|
||||||
|
|
||||||
if (type!=' ')
|
if (type!=' ')
|
||||||
{
|
{
|
||||||
Generator::fetchLocal (mCode, type, mLocals.getIndex (name2));
|
Generator::fetchLocal (mCode, type, mLocals.getIndex (name2));
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
mOperands.push_back (type=='f' ? 'f' : 'l');
|
mOperands.push_back (type=='f' ? 'f' : 'l');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = getContext().getGlobalType (name2);
|
type = getContext().getGlobalType (name2);
|
||||||
|
|
||||||
if (type!=' ')
|
if (type!=' ')
|
||||||
{
|
{
|
||||||
Generator::fetchGlobal (mCode, mLiterals, type, name2);
|
Generator::fetchGlobal (mCode, mLiterals, type, name2);
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
mOperands.push_back (type=='f' ? 'f' : 'l');
|
mOperands.push_back (type=='f' ? 'f' : 'l');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExplicit.empty() && getContext().isId (name))
|
if (mExplicit.empty() && getContext().isId (name))
|
||||||
{
|
{
|
||||||
mExplicit = name;
|
mExplicit = name;
|
||||||
|
@ -287,161 +293,183 @@ namespace Compiler
|
||||||
scanner.putbackName (name, loc);
|
scanner.putbackName (name, loc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseName (name, loc, scanner);
|
return Parser::parseName (name, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
mFirst = false;
|
mFirst = false;
|
||||||
|
|
||||||
if (!mExplicit.empty())
|
if (!mExplicit.empty())
|
||||||
{
|
{
|
||||||
if (mRefOp && mNextOperand)
|
if (mRefOp && mNextOperand)
|
||||||
{
|
{
|
||||||
if (keyword==Scanner::K_getdisabled)
|
if (keyword==Scanner::K_getdisabled)
|
||||||
{
|
{
|
||||||
mTokenLoc = loc;
|
start();
|
||||||
|
|
||||||
|
mTokenLoc = loc;
|
||||||
|
|
||||||
Generator::getDisabled (mCode, mLiterals, mExplicit);
|
Generator::getDisabled (mCode, mLiterals, mExplicit);
|
||||||
mOperands.push_back ('l');
|
mOperands.push_back ('l');
|
||||||
mExplicit.clear();
|
mExplicit.clear();
|
||||||
mRefOp = false;
|
mRefOp = false;
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_getdistance)
|
else if (keyword==Scanner::K_getdistance)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments ("c", scanner);
|
parseArguments ("c", scanner);
|
||||||
|
|
||||||
Generator::getDistance (mCode, mLiterals, mExplicit);
|
Generator::getDistance (mCode, mLiterals, mExplicit);
|
||||||
mOperands.push_back ('f');
|
mOperands.push_back ('f');
|
||||||
mExplicit.clear();
|
mExplicit.clear();
|
||||||
mRefOp = false;
|
mRefOp = false;
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for custom extensions
|
// check for custom extensions
|
||||||
if (const Extensions *extensions = getContext().getExtensions())
|
if (const Extensions *extensions = getContext().getExtensions())
|
||||||
{
|
{
|
||||||
char returnType;
|
char returnType;
|
||||||
std::string argumentType;
|
std::string argumentType;
|
||||||
|
|
||||||
if (extensions->isFunction (keyword, returnType, argumentType, true))
|
if (extensions->isFunction (keyword, returnType, argumentType, true))
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments (argumentType, scanner);
|
parseArguments (argumentType, scanner);
|
||||||
|
|
||||||
extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit);
|
extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit);
|
||||||
mOperands.push_back (returnType);
|
mOperands.push_back (returnType);
|
||||||
mExplicit.clear();
|
mExplicit.clear();
|
||||||
mRefOp = false;
|
mRefOp = false;
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseKeyword (keyword, loc, scanner);
|
return Parser::parseKeyword (keyword, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
{
|
{
|
||||||
if (keyword==Scanner::K_getsquareroot)
|
if (keyword==Scanner::K_getsquareroot)
|
||||||
{
|
{
|
||||||
mTokenLoc = loc;
|
start();
|
||||||
|
|
||||||
|
mTokenLoc = loc;
|
||||||
parseArguments ("f", scanner);
|
parseArguments ("f", scanner);
|
||||||
|
|
||||||
Generator::squareRoot (mCode);
|
Generator::squareRoot (mCode);
|
||||||
mOperands.push_back ('f');
|
mOperands.push_back ('f');
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_menumode)
|
else if (keyword==Scanner::K_menumode)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
|
|
||||||
Generator::menuMode (mCode);
|
Generator::menuMode (mCode);
|
||||||
mOperands.push_back ('l');
|
mOperands.push_back ('l');
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_random)
|
else if (keyword==Scanner::K_random)
|
||||||
{
|
{
|
||||||
mTokenLoc = loc;
|
start();
|
||||||
|
|
||||||
|
mTokenLoc = loc;
|
||||||
parseArguments ("l", scanner);
|
parseArguments ("l", scanner);
|
||||||
|
|
||||||
Generator::random (mCode);
|
Generator::random (mCode);
|
||||||
mOperands.push_back ('l');
|
mOperands.push_back ('l');
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_scriptrunning)
|
else if (keyword==Scanner::K_scriptrunning)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments ("c", scanner);
|
parseArguments ("c", scanner);
|
||||||
|
|
||||||
Generator::scriptRunning (mCode);
|
Generator::scriptRunning (mCode);
|
||||||
mOperands.push_back ('l');
|
mOperands.push_back ('l');
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_getdistance)
|
else if (keyword==Scanner::K_getdistance)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments ("c", scanner);
|
parseArguments ("c", scanner);
|
||||||
|
|
||||||
Generator::getDistance (mCode, mLiterals, "");
|
Generator::getDistance (mCode, mLiterals, "");
|
||||||
mOperands.push_back ('f');
|
mOperands.push_back ('f');
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_getsecondspassed)
|
else if (keyword==Scanner::K_getsecondspassed)
|
||||||
{
|
{
|
||||||
mTokenLoc = loc;
|
start();
|
||||||
|
|
||||||
|
mTokenLoc = loc;
|
||||||
|
|
||||||
Generator::getSecondsPassed (mCode);
|
Generator::getSecondsPassed (mCode);
|
||||||
mOperands.push_back ('f');
|
mOperands.push_back ('f');
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyword==Scanner::K_getdisabled)
|
else if (keyword==Scanner::K_getdisabled)
|
||||||
{
|
{
|
||||||
mTokenLoc = loc;
|
start();
|
||||||
|
|
||||||
|
mTokenLoc = loc;
|
||||||
|
|
||||||
Generator::getDisabled (mCode, mLiterals, "");
|
Generator::getDisabled (mCode, mLiterals, "");
|
||||||
mOperands.push_back ('l');
|
mOperands.push_back ('l');
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check for custom extensions
|
// check for custom extensions
|
||||||
if (const Extensions *extensions = getContext().getExtensions())
|
if (const Extensions *extensions = getContext().getExtensions())
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
|
|
||||||
char returnType;
|
char returnType;
|
||||||
std::string argumentType;
|
std::string argumentType;
|
||||||
|
|
||||||
if (extensions->isFunction (keyword, returnType, argumentType, false))
|
if (extensions->isFunction (keyword, returnType, argumentType, false))
|
||||||
{
|
{
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments (argumentType, scanner);
|
parseArguments (argumentType, scanner);
|
||||||
|
|
||||||
extensions->generateFunctionCode (keyword, mCode, mLiterals, "");
|
extensions->generateFunctionCode (keyword, mCode, mLiterals, "");
|
||||||
mOperands.push_back (returnType);
|
mOperands.push_back (returnType);
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -454,7 +482,7 @@ namespace Compiler
|
||||||
scanner.putbackKeyword (keyword, loc);
|
scanner.putbackKeyword (keyword, loc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseKeyword (keyword, loc, scanner);
|
return Parser::parseKeyword (keyword, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,10 +495,10 @@ namespace Compiler
|
||||||
mRefOp = true;
|
mRefOp = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseSpecial (code, loc, scanner);
|
return Parser::parseSpecial (code, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code==Scanner::S_comma)
|
if (code==Scanner::S_comma)
|
||||||
{
|
{
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
|
@ -481,14 +509,14 @@ namespace Compiler
|
||||||
mFirst = false;
|
mFirst = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// end marker
|
// end marker
|
||||||
scanner.putbackSpecial (code, loc);
|
scanner.putbackSpecial (code, loc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mFirst = false;
|
mFirst = false;
|
||||||
|
|
||||||
if (code==Scanner::S_newline)
|
if (code==Scanner::S_newline)
|
||||||
{
|
{
|
||||||
// end marker
|
// end marker
|
||||||
|
@ -496,7 +524,7 @@ namespace Compiler
|
||||||
scanner.putbackSpecial (code, loc);
|
scanner.putbackSpecial (code, loc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code==Scanner::S_minus && mNextOperand)
|
if (code==Scanner::S_minus && mNextOperand)
|
||||||
{
|
{
|
||||||
// unary
|
// unary
|
||||||
|
@ -504,7 +532,7 @@ namespace Compiler
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code==Scanner::S_open)
|
if (code==Scanner::S_open)
|
||||||
{
|
{
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
|
@ -520,7 +548,7 @@ namespace Compiler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code==Scanner::S_close && !mNextOperand)
|
if (code==Scanner::S_close && !mNextOperand)
|
||||||
{
|
{
|
||||||
if (isOpen())
|
if (isOpen())
|
||||||
|
@ -528,17 +556,17 @@ namespace Compiler
|
||||||
close();
|
close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
scanner.putbackSpecial (code, loc);
|
scanner.putbackSpecial (code, loc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mNextOperand)
|
if (!mNextOperand)
|
||||||
{
|
{
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
char c = 0; // comparison
|
char c = 0; // comparison
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case Scanner::S_plus: pushBinaryOperator ('+'); return true;
|
case Scanner::S_plus: pushBinaryOperator ('+'); return true;
|
||||||
|
@ -552,7 +580,7 @@ namespace Compiler
|
||||||
case Scanner::S_cmpGT: c = 'g'; break;
|
case Scanner::S_cmpGT: c = 'g'; break;
|
||||||
case Scanner::S_cmpGE: c = 'G'; break;
|
case Scanner::S_cmpGE: c = 'G'; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
if (mArgument && !isOpen())
|
if (mArgument && !isOpen())
|
||||||
|
@ -562,15 +590,15 @@ namespace Compiler
|
||||||
scanner.putbackSpecial (code, loc);
|
scanner.putbackSpecial (code, loc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pushBinaryOperator (c);
|
pushBinaryOperator (c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseSpecial (code, loc, scanner);
|
return Parser::parseSpecial (code, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::reset()
|
void ExprParser::reset()
|
||||||
{
|
{
|
||||||
mOperands.clear();
|
mOperands.clear();
|
||||||
|
@ -580,8 +608,9 @@ namespace Compiler
|
||||||
mFirst = true;
|
mFirst = true;
|
||||||
mExplicit.clear();
|
mExplicit.clear();
|
||||||
mRefOp = false;
|
mRefOp = false;
|
||||||
|
Parser::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
char ExprParser::append (std::vector<Interpreter::Type_Code>& code)
|
char ExprParser::append (std::vector<Interpreter::Type_Code>& code)
|
||||||
{
|
{
|
||||||
if (mOperands.empty() && mOperators.empty())
|
if (mOperands.empty() && mOperators.empty())
|
||||||
|
@ -589,7 +618,7 @@ namespace Compiler
|
||||||
getErrorHandler().error ("missing expression", mTokenLoc);
|
getErrorHandler().error ("missing expression", mTokenLoc);
|
||||||
return 'l';
|
return 'l';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mNextOperand || mOperands.empty())
|
if (mNextOperand || mOperands.empty())
|
||||||
{
|
{
|
||||||
getErrorHandler().error ("syntax error in expression", mTokenLoc);
|
getErrorHandler().error ("syntax error in expression", mTokenLoc);
|
||||||
|
@ -603,62 +632,90 @@ namespace Compiler
|
||||||
|
|
||||||
assert (mOperands.size()==1);
|
assert (mOperands.size()==1);
|
||||||
return mOperands[0];
|
return mOperands[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner,
|
int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner,
|
||||||
std::vector<Interpreter::Type_Code>& code, bool invert)
|
std::vector<Interpreter::Type_Code>& code, bool invert)
|
||||||
{
|
{
|
||||||
|
bool optional = false;
|
||||||
|
bool optionalCount = 0;
|
||||||
|
|
||||||
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
|
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
|
||||||
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
|
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
|
||||||
|
|
||||||
std::stack<std::vector<Interpreter::Type_Code> > stack;
|
std::stack<std::vector<Interpreter::Type_Code> > stack;
|
||||||
|
|
||||||
for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end();
|
for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end();
|
||||||
++iter)
|
++iter)
|
||||||
{
|
{
|
||||||
if (*iter=='S' || *iter=='c')
|
if (*iter=='/')
|
||||||
|
{
|
||||||
|
optional = true;
|
||||||
|
}
|
||||||
|
else if (*iter=='S' || *iter=='c')
|
||||||
{
|
{
|
||||||
stringParser.reset();
|
stringParser.reset();
|
||||||
|
|
||||||
|
if (optional)
|
||||||
|
stringParser.setOptional (true);
|
||||||
|
|
||||||
if (*iter=='c') stringParser.smashCase();
|
if (*iter=='c') stringParser.smashCase();
|
||||||
scanner.scan (stringParser);
|
scanner.scan (stringParser);
|
||||||
|
|
||||||
|
if (optional && stringParser.isEmpty())
|
||||||
|
break;
|
||||||
|
|
||||||
if (invert)
|
if (invert)
|
||||||
{
|
{
|
||||||
std::vector<Interpreter::Type_Code> tmp;
|
std::vector<Interpreter::Type_Code> tmp;
|
||||||
stringParser.append (tmp);
|
stringParser.append (tmp);
|
||||||
|
|
||||||
stack.push (tmp);
|
stack.push (tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
stringParser.append (code);
|
stringParser.append (code);
|
||||||
|
|
||||||
|
if (optional)
|
||||||
|
++optionalCount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
parser.reset();
|
parser.reset();
|
||||||
|
|
||||||
|
if (optional)
|
||||||
|
parser.setOptional (true);
|
||||||
|
|
||||||
scanner.scan (parser);
|
scanner.scan (parser);
|
||||||
|
|
||||||
|
if (optional && parser.isEmpty())
|
||||||
|
break;
|
||||||
|
|
||||||
std::vector<Interpreter::Type_Code> tmp;
|
std::vector<Interpreter::Type_Code> tmp;
|
||||||
|
|
||||||
char type = parser.append (tmp);
|
char type = parser.append (tmp);
|
||||||
|
|
||||||
if (type!=*iter)
|
if (type!=*iter)
|
||||||
Generator::convert (tmp, type, *iter);
|
Generator::convert (tmp, type, *iter);
|
||||||
|
|
||||||
if (invert)
|
if (invert)
|
||||||
stack.push (tmp);
|
stack.push (tmp);
|
||||||
else
|
else
|
||||||
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
|
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
|
||||||
|
|
||||||
|
if (optional)
|
||||||
|
++optionalCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!stack.empty())
|
while (!stack.empty())
|
||||||
{
|
{
|
||||||
std::vector<Interpreter::Type_Code>& tmp = stack.top();
|
std::vector<Interpreter::Type_Code>& tmp = stack.top();
|
||||||
|
|
||||||
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
|
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
|
||||||
|
|
||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return optionalCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Compiler
|
||||||
|
|
||||||
class ExprParser : public Parser
|
class ExprParser : public Parser
|
||||||
{
|
{
|
||||||
Locals& mLocals;
|
Locals& mLocals;
|
||||||
Literals& mLiterals;
|
Literals& mLiterals;
|
||||||
std::vector<char> mOperands;
|
std::vector<char> mOperands;
|
||||||
std::vector<char> mOperators;
|
std::vector<char> mOperators;
|
||||||
|
@ -26,35 +26,35 @@ namespace Compiler
|
||||||
bool mArgument;
|
bool mArgument;
|
||||||
std::string mExplicit;
|
std::string mExplicit;
|
||||||
bool mRefOp;
|
bool mRefOp;
|
||||||
|
|
||||||
int getPriority (char op) const;
|
int getPriority (char op) const;
|
||||||
|
|
||||||
char getOperandType (int Index = 0) const;
|
char getOperandType (int Index = 0) const;
|
||||||
|
|
||||||
char getOperator() const;
|
char getOperator() const;
|
||||||
|
|
||||||
bool isOpen() const;
|
bool isOpen() const;
|
||||||
|
|
||||||
void popOperator();
|
void popOperator();
|
||||||
|
|
||||||
void popOperand();
|
void popOperand();
|
||||||
|
|
||||||
void replaceBinaryOperands();
|
void replaceBinaryOperands();
|
||||||
|
|
||||||
void pop();
|
void pop();
|
||||||
|
|
||||||
void pushIntegerLiteral (int value);
|
void pushIntegerLiteral (int value);
|
||||||
|
|
||||||
void pushFloatLiteral (float value);
|
void pushFloatLiteral (float value);
|
||||||
|
|
||||||
void pushBinaryOperator (char c);
|
void pushBinaryOperator (char c);
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
void parseArguments (const std::string& arguments, Scanner& scanner);
|
int parseArguments (const std::string& arguments, Scanner& scanner);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||||
Literals& literals, bool argument = false);
|
Literals& literals, bool argument = false);
|
||||||
///< constructor
|
///< constructor
|
||||||
|
@ -84,20 +84,22 @@ namespace Compiler
|
||||||
virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
|
virtual bool parseSpecial (int code, const TokenLoc& loc, Scanner& scanner);
|
||||||
///< Handle a special character token.
|
///< Handle a special character token.
|
||||||
/// \return fetch another token?
|
/// \return fetch another token?
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
///< Reset parser to clean state.
|
///< Reset parser to clean state.
|
||||||
|
|
||||||
char append (std::vector<Interpreter::Type_Code>& code);
|
char append (std::vector<Interpreter::Type_Code>& code);
|
||||||
///< Generate code for parsed expression.
|
///< Generate code for parsed expression.
|
||||||
/// \return Type ('l': integer, 'f': float)
|
/// \return Type ('l': integer, 'f': float)
|
||||||
|
|
||||||
void parseArguments (const std::string& arguments, Scanner& scanner,
|
int parseArguments (const std::string& arguments, Scanner& scanner,
|
||||||
std::vector<Interpreter::Type_Code>& code, bool invert = false);
|
std::vector<Interpreter::Type_Code>& code, bool invert = false);
|
||||||
///< Parse sequence of arguments specified by \a arguments.
|
///< Parse sequence of arguments specified by \a arguments.
|
||||||
/// \param arguments Each character represents one arguments ('l': integer,
|
/// \param arguments Each character represents one arguments ('l': integer,
|
||||||
/// 'f': float, 'S': string, 'c': string (case smashed))
|
/// 'f': float, 'S': string, 'c': string (case smashed), '/': following arguments are
|
||||||
|
/// optional)
|
||||||
/// \param invert Store arguments in reverted order.
|
/// \param invert Store arguments in reverted order.
|
||||||
|
/// \return number of optional arguments
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
namespace Compiler
|
namespace Compiler
|
||||||
{
|
{
|
||||||
FileParser::FileParser (ErrorHandler& errorHandler, Context& context)
|
FileParser::FileParser (ErrorHandler& errorHandler, Context& context)
|
||||||
: Parser (errorHandler, context),
|
: Parser (errorHandler, context),
|
||||||
mScriptParser (errorHandler, context, mLocals, true),
|
mScriptParser (errorHandler, context, mLocals, true),
|
||||||
mState (BeginState)
|
mState (BeginState)
|
||||||
{}
|
{}
|
||||||
|
@ -17,12 +17,12 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
return mName;
|
return mName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileParser::getCode (std::vector<Interpreter::Type_Code>& code) const
|
void FileParser::getCode (std::vector<Interpreter::Type_Code>& code) const
|
||||||
{
|
{
|
||||||
mScriptParser.getCode (code);
|
mScriptParser.getCode (code);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Locals& FileParser::getLocals() const
|
const Locals& FileParser::getLocals() const
|
||||||
{
|
{
|
||||||
return mLocals;
|
return mLocals;
|
||||||
|
@ -37,17 +37,17 @@ namespace Compiler
|
||||||
mState = BeginCompleteState;
|
mState = BeginCompleteState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mState==EndNameState)
|
if (mState==EndNameState)
|
||||||
{
|
{
|
||||||
// optional repeated name after end statement
|
// optional repeated name after end statement
|
||||||
if (mName!=name)
|
if (mName!=name)
|
||||||
reportWarning ("Names for script " + mName + " do not match", loc);
|
reportWarning ("Names for script " + mName + " do not match", loc);
|
||||||
|
|
||||||
mState = EndCompleteState;
|
mState = EndCompleteState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseName (name, loc, scanner);
|
return Parser::parseName (name, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ namespace Compiler
|
||||||
mState = NameState;
|
mState = NameState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mState==NameState)
|
if (mState==NameState)
|
||||||
{
|
{
|
||||||
// keywords can be used as script names too. Thank you Morrowind for another
|
// keywords can be used as script names too. Thank you Morrowind for another
|
||||||
|
@ -67,7 +67,7 @@ namespace Compiler
|
||||||
mState = BeginCompleteState;
|
mState = BeginCompleteState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseKeyword (keyword, loc, scanner);
|
return Parser::parseKeyword (keyword, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,25 +80,25 @@ namespace Compiler
|
||||||
// ignore empty lines
|
// ignore empty lines
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mState==BeginCompleteState)
|
if (mState==BeginCompleteState)
|
||||||
{
|
{
|
||||||
// parse the script body
|
// parse the script body
|
||||||
mScriptParser.reset();
|
mScriptParser.reset();
|
||||||
|
|
||||||
scanner.scan (mScriptParser);
|
scanner.scan (mScriptParser);
|
||||||
|
|
||||||
mState = EndNameState;
|
mState = EndNameState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mState==EndCompleteState || mState==EndNameState)
|
if (mState==EndCompleteState || mState==EndNameState)
|
||||||
{
|
{
|
||||||
// we are done here -> ignore the rest of the script
|
// we are done here -> ignore the rest of the script
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseSpecial (code, loc, scanner);
|
return Parser::parseSpecial (code, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,12 +107,12 @@ namespace Compiler
|
||||||
if (mState!=EndNameState && mState!=EndCompleteState)
|
if (mState!=EndNameState && mState!=EndCompleteState)
|
||||||
Parser::parseEOF (scanner);
|
Parser::parseEOF (scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileParser::reset()
|
void FileParser::reset()
|
||||||
{
|
{
|
||||||
mState = BeginState;
|
mState = BeginState;
|
||||||
mName.clear();
|
mName.clear();
|
||||||
mScriptParser.reset();
|
mScriptParser.reset();
|
||||||
|
Parser::reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,15 +57,15 @@ namespace Compiler
|
||||||
std::string Parser::toLower (const std::string& name)
|
std::string Parser::toLower (const std::string& name)
|
||||||
{
|
{
|
||||||
std::string lowerCase;
|
std::string lowerCase;
|
||||||
|
|
||||||
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
|
std::transform (name.begin(), name.end(), std::back_inserter (lowerCase),
|
||||||
(int(*)(int)) std::tolower);
|
(int(*)(int)) std::tolower);
|
||||||
|
|
||||||
return lowerCase;
|
return lowerCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::Parser (ErrorHandler& errorHandler, Context& context)
|
Parser::Parser (ErrorHandler& errorHandler, Context& context)
|
||||||
: mErrorHandler (errorHandler), mContext (context)
|
: mErrorHandler (errorHandler), mContext (context), mOptional (false), mEmpty (true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
|
@ -79,7 +79,9 @@ namespace Compiler
|
||||||
|
|
||||||
bool Parser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
bool Parser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
reportSeriousError ("Unexpected numeric value", loc);
|
if (!(mOptional && mEmpty))
|
||||||
|
reportSeriousError ("Unexpected numeric value", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +92,9 @@ namespace Compiler
|
||||||
|
|
||||||
bool Parser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner)
|
bool Parser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
reportSeriousError ("Unexpected floating point value", loc);
|
if (!(mOptional && mEmpty))
|
||||||
|
reportSeriousError ("Unexpected floating point value", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +106,9 @@ namespace Compiler
|
||||||
bool Parser::parseName (const std::string& name, const TokenLoc& loc,
|
bool Parser::parseName (const std::string& name, const TokenLoc& loc,
|
||||||
Scanner& scanner)
|
Scanner& scanner)
|
||||||
{
|
{
|
||||||
reportSeriousError ("Unexpected name", loc);
|
if (!(mOptional && mEmpty))
|
||||||
|
reportSeriousError ("Unexpected name", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +119,9 @@ namespace Compiler
|
||||||
|
|
||||||
bool Parser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
bool Parser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
reportSeriousError ("Unexpected keyword", loc);
|
if (!(mOptional && mEmpty))
|
||||||
|
reportSeriousError ("Unexpected keyword", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +132,9 @@ namespace Compiler
|
||||||
|
|
||||||
bool Parser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
bool Parser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
reportSeriousError ("Unexpected special token", loc);
|
if (!(mOptional && mEmpty))
|
||||||
|
reportSeriousError ("Unexpected special token", loc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,5 +146,25 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
reportEOF();
|
reportEOF();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
void Parser::reset()
|
||||||
|
{
|
||||||
|
mOptional = false;
|
||||||
|
mEmpty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::setOptional (bool optional)
|
||||||
|
{
|
||||||
|
mOptional = optional;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::start()
|
||||||
|
{
|
||||||
|
mEmpty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parser::isEmpty() const
|
||||||
|
{
|
||||||
|
return mEmpty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
ErrorHandler& mErrorHandler;
|
ErrorHandler& mErrorHandler;
|
||||||
Context& mContext;
|
Context& mContext;
|
||||||
|
bool mOptional;
|
||||||
|
bool mEmpty;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -47,7 +49,7 @@ namespace Compiler
|
||||||
///< constructor
|
///< constructor
|
||||||
|
|
||||||
virtual ~Parser();
|
virtual ~Parser();
|
||||||
///< destructor
|
///< destructor
|
||||||
|
|
||||||
virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner);
|
virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner);
|
||||||
///< Handle an int token.
|
///< Handle an int token.
|
||||||
|
@ -84,6 +86,19 @@ namespace Compiler
|
||||||
///< Handle EOF token.
|
///< Handle EOF token.
|
||||||
///
|
///
|
||||||
/// - Default-implementation: Report an error.
|
/// - Default-implementation: Report an error.
|
||||||
|
|
||||||
|
virtual void reset();
|
||||||
|
///< Reset parser to clean state.
|
||||||
|
|
||||||
|
void setOptional (bool optional);
|
||||||
|
///< Optional mode: If nothign has been parsed yet and an unexpected token is delivered, stop
|
||||||
|
/// parsing without raising an exception (after a reset the parser is in non-optional mode).
|
||||||
|
|
||||||
|
void start();
|
||||||
|
///< Mark parser as non-empty (at least one token has been parser).
|
||||||
|
|
||||||
|
bool isEmpty() const;
|
||||||
|
///< Has anything been parsed?
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Compiler
|
||||||
StringParser::StringParser (ErrorHandler& errorHandler, Context& context, Literals& literals)
|
StringParser::StringParser (ErrorHandler& errorHandler, Context& context, Literals& literals)
|
||||||
: Parser (errorHandler, context), mLiterals (literals), mState (StartState), mSmashCase (false)
|
: Parser (errorHandler, context), mLiterals (literals), mState (StartState), mSmashCase (false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringParser::parseName (const std::string& name, const TokenLoc& loc,
|
bool StringParser::parseName (const std::string& name, const TokenLoc& loc,
|
||||||
|
@ -20,14 +20,15 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
if (mState==StartState || mState==CommaState)
|
if (mState==StartState || mState==CommaState)
|
||||||
{
|
{
|
||||||
|
start();
|
||||||
if (mSmashCase)
|
if (mSmashCase)
|
||||||
Generator::pushString (mCode, mLiterals, toLower (name));
|
Generator::pushString (mCode, mLiterals, toLower (name));
|
||||||
else
|
else
|
||||||
Generator::pushString (mCode, mLiterals, name);
|
Generator::pushString (mCode, mLiterals, name);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseName (name, loc, scanner);
|
return Parser::parseName (name, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +39,10 @@ namespace Compiler
|
||||||
mState = CommaState;
|
mState = CommaState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseSpecial (code, loc, scanner);
|
return Parser::parseSpecial (code, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringParser::append (std::vector<Interpreter::Type_Code>& code)
|
void StringParser::append (std::vector<Interpreter::Type_Code>& code)
|
||||||
{
|
{
|
||||||
std::copy (mCode.begin(), mCode.end(), std::back_inserter (code));
|
std::copy (mCode.begin(), mCode.end(), std::back_inserter (code));
|
||||||
|
@ -52,11 +53,11 @@ namespace Compiler
|
||||||
mState = StartState;
|
mState = StartState;
|
||||||
mCode.clear();
|
mCode.clear();
|
||||||
mSmashCase = false;
|
mSmashCase = false;
|
||||||
|
Parser::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringParser::smashCase()
|
void StringParser::smashCase()
|
||||||
{
|
{
|
||||||
mSmashCase = true;
|
mSmashCase = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue