|
|
|
@ -22,33 +22,33 @@ namespace Compiler
|
|
|
|
|
switch (op)
|
|
|
|
|
{
|
|
|
|
|
case '(':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'e': // ==
|
|
|
|
|
case 'n': // !=
|
|
|
|
|
case 'l': // <
|
|
|
|
|
case 'L': // <=
|
|
|
|
|
case 'g': // <
|
|
|
|
|
case 'G': // >=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case '+':
|
|
|
|
|
case '-':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
|
case '/':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -59,7 +59,7 @@ namespace Compiler
|
|
|
|
|
assert (Index<static_cast<int> (mOperands.size()));
|
|
|
|
|
return mOperands[mOperands.size()-1-Index];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char ExprParser::getOperator() const
|
|
|
|
|
{
|
|
|
|
|
assert (!mOperators.empty());
|
|
|
|
@ -70,27 +70,27 @@ namespace Compiler
|
|
|
|
|
{
|
|
|
|
|
return std::find (mOperators.begin(), mOperators.end(), '(')!=mOperators.end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExprParser::popOperator()
|
|
|
|
|
{
|
|
|
|
|
assert (!mOperators.empty());
|
|
|
|
|
mOperators.resize (mOperators.size()-1);
|
|
|
|
|
mOperators.resize (mOperators.size()-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExprParser::popOperand()
|
|
|
|
|
{
|
|
|
|
|
assert (!mOperands.empty());
|
|
|
|
|
mOperands.resize (mOperands.size()-1);
|
|
|
|
|
mOperands.resize (mOperands.size()-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ExprParser::replaceBinaryOperands()
|
|
|
|
|
{
|
|
|
|
|
char t1 = getOperandType (1);
|
|
|
|
|
char t2 = getOperandType();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
popOperand();
|
|
|
|
|
popOperand();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (t1==t2)
|
|
|
|
|
mOperands.push_back (t1);
|
|
|
|
|
else if (t1=='f' || t2=='f')
|
|
|
|
@ -102,59 +102,59 @@ namespace Compiler
|
|
|
|
|
void ExprParser::pop()
|
|
|
|
|
{
|
|
|
|
|
char op = getOperator();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (op)
|
|
|
|
|
{
|
|
|
|
|
case 'm':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::negate (mCode, getOperandType());
|
|
|
|
|
popOperator();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '+':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::add (mCode, getOperandType (1), getOperandType());
|
|
|
|
|
popOperator();
|
|
|
|
|
replaceBinaryOperands();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '-':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::sub (mCode, getOperandType (1), getOperandType());
|
|
|
|
|
popOperator();
|
|
|
|
|
replaceBinaryOperands();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::mul (mCode, getOperandType (1), getOperandType());
|
|
|
|
|
popOperator();
|
|
|
|
|
replaceBinaryOperands();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '/':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::div (mCode, getOperandType (1), getOperandType());
|
|
|
|
|
popOperator();
|
|
|
|
|
replaceBinaryOperands();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'e':
|
|
|
|
|
case 'n':
|
|
|
|
|
case 'l':
|
|
|
|
|
case 'L':
|
|
|
|
|
case 'g':
|
|
|
|
|
case 'G':
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::compare (mCode, op, getOperandType (1), getOperandType());
|
|
|
|
|
popOperator();
|
|
|
|
|
popOperand();
|
|
|
|
|
popOperand();
|
|
|
|
|
mOperands.push_back ('l');
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
throw std::logic_error ("unknown operator");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -165,36 +165,36 @@ namespace Compiler
|
|
|
|
|
mOperands.push_back ('l');
|
|
|
|
|
Generator::pushInt (mCode, mLiterals, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExprParser::pushFloatLiteral (float value)
|
|
|
|
|
{
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
mOperands.push_back ('f');
|
|
|
|
|
Generator::pushFloat (mCode, mLiterals, value);
|
|
|
|
|
Generator::pushFloat (mCode, mLiterals, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExprParser::pushBinaryOperator (char c)
|
|
|
|
|
{
|
|
|
|
|
while (!mOperators.empty() && getPriority (getOperator())>=getPriority (c))
|
|
|
|
|
pop();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mOperators.push_back (c);
|
|
|
|
|
mNextOperand = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExprParser::close()
|
|
|
|
|
{
|
|
|
|
|
while (getOperator()!='(')
|
|
|
|
|
pop();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
Literals& literals, bool argument)
|
|
|
|
|
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
|
|
|
|
@ -205,11 +205,13 @@ namespace Compiler
|
|
|
|
|
{
|
|
|
|
|
if (!mExplicit.empty())
|
|
|
|
|
return Parser::parseInt (value, loc, scanner);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mFirst = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mNextOperand)
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
pushIntegerLiteral (value);
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
return true;
|
|
|
|
@ -228,13 +230,15 @@ namespace Compiler
|
|
|
|
|
return Parser::parseFloat (value, loc, scanner);
|
|
|
|
|
|
|
|
|
|
mFirst = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mNextOperand)
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
pushFloatLiteral (value);
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// no comma was used between arguments
|
|
|
|
@ -252,29 +256,31 @@ namespace Compiler
|
|
|
|
|
mFirst = false;
|
|
|
|
|
|
|
|
|
|
if (mNextOperand)
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
std::string name2 = toLower (name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char type = mLocals.getType (name2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (type!=' ')
|
|
|
|
|
{
|
|
|
|
|
Generator::fetchLocal (mCode, type, mLocals.getIndex (name2));
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
mOperands.push_back (type=='f' ? 'f' : 'l');
|
|
|
|
|
return true;
|
|
|
|
|
mOperands.push_back (type=='f' ? 'f' : 'l');
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type = getContext().getGlobalType (name2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (type!=' ')
|
|
|
|
|
{
|
|
|
|
|
Generator::fetchGlobal (mCode, mLiterals, type, name2);
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
mOperands.push_back (type=='f' ? 'f' : 'l');
|
|
|
|
|
return true;
|
|
|
|
|
mOperands.push_back (type=='f' ? 'f' : 'l');
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mExplicit.empty() && getContext().isId (name))
|
|
|
|
|
{
|
|
|
|
|
mExplicit = name;
|
|
|
|
@ -287,161 +293,183 @@ namespace Compiler
|
|
|
|
|
scanner.putbackName (name, loc);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Parser::parseName (name, loc, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
|
|
|
|
{
|
|
|
|
|
mFirst = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!mExplicit.empty())
|
|
|
|
|
{
|
|
|
|
|
if (mRefOp && mNextOperand)
|
|
|
|
|
{
|
|
|
|
|
if (keyword==Scanner::K_getdisabled)
|
|
|
|
|
{
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
|
|
|
|
|
Generator::getDisabled (mCode, mLiterals, mExplicit);
|
|
|
|
|
mOperands.push_back ('l');
|
|
|
|
|
mExplicit.clear();
|
|
|
|
|
mRefOp = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (keyword==Scanner::K_getdistance)
|
|
|
|
|
{
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
parseArguments ("c", scanner);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::getDistance (mCode, mLiterals, mExplicit);
|
|
|
|
|
mOperands.push_back ('f');
|
|
|
|
|
mExplicit.clear();
|
|
|
|
|
mRefOp = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check for custom extensions
|
|
|
|
|
if (const Extensions *extensions = getContext().getExtensions())
|
|
|
|
|
{
|
|
|
|
|
char returnType;
|
|
|
|
|
std::string argumentType;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (extensions->isFunction (keyword, returnType, argumentType, true))
|
|
|
|
|
{
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
parseArguments (argumentType, scanner);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit);
|
|
|
|
|
mOperands.push_back (returnType);
|
|
|
|
|
mExplicit.clear();
|
|
|
|
|
mRefOp = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Parser::parseKeyword (keyword, loc, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mNextOperand)
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
if (keyword==Scanner::K_getsquareroot)
|
|
|
|
|
{
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
parseArguments ("f", scanner);
|
|
|
|
|
|
|
|
|
|
Generator::squareRoot (mCode);
|
|
|
|
|
mOperands.push_back ('f');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (keyword==Scanner::K_menumode)
|
|
|
|
|
{
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::menuMode (mCode);
|
|
|
|
|
mOperands.push_back ('l');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (keyword==Scanner::K_random)
|
|
|
|
|
{
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
parseArguments ("l", scanner);
|
|
|
|
|
|
|
|
|
|
Generator::random (mCode);
|
|
|
|
|
mOperands.push_back ('l');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (keyword==Scanner::K_scriptrunning)
|
|
|
|
|
{
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
parseArguments ("c", scanner);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::scriptRunning (mCode);
|
|
|
|
|
mOperands.push_back ('l');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (keyword==Scanner::K_getdistance)
|
|
|
|
|
{
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
parseArguments ("c", scanner);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator::getDistance (mCode, mLiterals, "");
|
|
|
|
|
mOperands.push_back ('f');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (keyword==Scanner::K_getsecondspassed)
|
|
|
|
|
{
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
|
|
|
|
|
Generator::getSecondsPassed (mCode);
|
|
|
|
|
mOperands.push_back ('f');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (keyword==Scanner::K_getdisabled)
|
|
|
|
|
{
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
|
|
|
|
|
Generator::getDisabled (mCode, mLiterals, "");
|
|
|
|
|
mOperands.push_back ('l');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// check for custom extensions
|
|
|
|
|
if (const Extensions *extensions = getContext().getExtensions())
|
|
|
|
|
{
|
|
|
|
|
start();
|
|
|
|
|
|
|
|
|
|
char returnType;
|
|
|
|
|
std::string argumentType;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (extensions->isFunction (keyword, returnType, argumentType, false))
|
|
|
|
|
{
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
parseArguments (argumentType, scanner);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extensions->generateFunctionCode (keyword, mCode, mLiterals, "");
|
|
|
|
|
mOperands.push_back (returnType);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mNextOperand = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -454,7 +482,7 @@ namespace Compiler
|
|
|
|
|
scanner.putbackKeyword (keyword, loc);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Parser::parseKeyword (keyword, loc, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -467,10 +495,10 @@ namespace Compiler
|
|
|
|
|
mRefOp = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Parser::parseSpecial (code, loc, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (code==Scanner::S_comma)
|
|
|
|
|
{
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
@ -481,14 +509,14 @@ namespace Compiler
|
|
|
|
|
mFirst = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// end marker
|
|
|
|
|
scanner.putbackSpecial (code, loc);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mFirst = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (code==Scanner::S_newline)
|
|
|
|
|
{
|
|
|
|
|
// end marker
|
|
|
|
@ -496,7 +524,7 @@ namespace Compiler
|
|
|
|
|
scanner.putbackSpecial (code, loc);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (code==Scanner::S_minus && mNextOperand)
|
|
|
|
|
{
|
|
|
|
|
// unary
|
|
|
|
@ -504,7 +532,7 @@ namespace Compiler
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (code==Scanner::S_open)
|
|
|
|
|
{
|
|
|
|
|
if (mNextOperand)
|
|
|
|
@ -520,7 +548,7 @@ namespace Compiler
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (code==Scanner::S_close && !mNextOperand)
|
|
|
|
|
{
|
|
|
|
|
if (isOpen())
|
|
|
|
@ -528,17 +556,17 @@ namespace Compiler
|
|
|
|
|
close();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
scanner.putbackSpecial (code, loc);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!mNextOperand)
|
|
|
|
|
{
|
|
|
|
|
mTokenLoc = loc;
|
|
|
|
|
char c = 0; // comparison
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
case Scanner::S_plus: pushBinaryOperator ('+'); return true;
|
|
|
|
@ -552,7 +580,7 @@ namespace Compiler
|
|
|
|
|
case Scanner::S_cmpGT: c = 'g'; break;
|
|
|
|
|
case Scanner::S_cmpGE: c = 'G'; break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (c)
|
|
|
|
|
{
|
|
|
|
|
if (mArgument && !isOpen())
|
|
|
|
@ -562,15 +590,15 @@ namespace Compiler
|
|
|
|
|
scanner.putbackSpecial (code, loc);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pushBinaryOperator (c);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Parser::parseSpecial (code, loc, scanner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExprParser::reset()
|
|
|
|
|
{
|
|
|
|
|
mOperands.clear();
|
|
|
|
@ -580,8 +608,9 @@ namespace Compiler
|
|
|
|
|
mFirst = true;
|
|
|
|
|
mExplicit.clear();
|
|
|
|
|
mRefOp = false;
|
|
|
|
|
Parser::reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char ExprParser::append (std::vector<Interpreter::Type_Code>& code)
|
|
|
|
|
{
|
|
|
|
|
if (mOperands.empty() && mOperators.empty())
|
|
|
|
@ -589,7 +618,7 @@ namespace Compiler
|
|
|
|
|
getErrorHandler().error ("missing expression", mTokenLoc);
|
|
|
|
|
return 'l';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mNextOperand || mOperands.empty())
|
|
|
|
|
{
|
|
|
|
|
getErrorHandler().error ("syntax error in expression", mTokenLoc);
|
|
|
|
@ -603,62 +632,90 @@ namespace Compiler
|
|
|
|
|
|
|
|
|
|
assert (mOperands.size()==1);
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
bool optional = false;
|
|
|
|
|
bool optionalCount = 0;
|
|
|
|
|
|
|
|
|
|
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
|
|
|
|
|
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::stack<std::vector<Interpreter::Type_Code> > stack;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end();
|
|
|
|
|
++iter)
|
|
|
|
|
{
|
|
|
|
|
if (*iter=='S' || *iter=='c')
|
|
|
|
|
if (*iter=='/')
|
|
|
|
|
{
|
|
|
|
|
optional = true;
|
|
|
|
|
}
|
|
|
|
|
else if (*iter=='S' || *iter=='c')
|
|
|
|
|
{
|
|
|
|
|
stringParser.reset();
|
|
|
|
|
|
|
|
|
|
if (optional)
|
|
|
|
|
stringParser.setOptional (true);
|
|
|
|
|
|
|
|
|
|
if (*iter=='c') stringParser.smashCase();
|
|
|
|
|
scanner.scan (stringParser);
|
|
|
|
|
|
|
|
|
|
scanner.scan (stringParser);
|
|
|
|
|
|
|
|
|
|
if (optional && stringParser.isEmpty())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (invert)
|
|
|
|
|
{
|
|
|
|
|
std::vector<Interpreter::Type_Code> tmp;
|
|
|
|
|
stringParser.append (tmp);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stack.push (tmp);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
stringParser.append (code);
|
|
|
|
|
|
|
|
|
|
if (optional)
|
|
|
|
|
++optionalCount;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
parser.reset();
|
|
|
|
|
parser.reset();
|
|
|
|
|
|
|
|
|
|
if (optional)
|
|
|
|
|
parser.setOptional (true);
|
|
|
|
|
|
|
|
|
|
scanner.scan (parser);
|
|
|
|
|
|
|
|
|
|
if (optional && parser.isEmpty())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
std::vector<Interpreter::Type_Code> tmp;
|
|
|
|
|
|
|
|
|
|
char type = parser.append (tmp);
|
|
|
|
|
|
|
|
|
|
if (type!=*iter)
|
|
|
|
|
Generator::convert (tmp, type, *iter);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (invert)
|
|
|
|
|
stack.push (tmp);
|
|
|
|
|
else
|
|
|
|
|
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
|
|
|
|
|
|
|
|
|
|
if (optional)
|
|
|
|
|
++optionalCount;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (!stack.empty())
|
|
|
|
|
{
|
|
|
|
|
std::vector<Interpreter::Type_Code>& tmp = stack.top();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stack.pop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return optionalCount;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|