forked from mirror/openmw-tes3mp
added parsing for signed integers and floats
This commit is contained in:
parent
ab33234027
commit
ca8002e533
7 changed files with 126 additions and 13 deletions
|
@ -9,6 +9,36 @@
|
|||
|
||||
namespace Compiler
|
||||
{
|
||||
char ExprParser::popUnaryOperator()
|
||||
{
|
||||
if (mOperators.empty())
|
||||
return 0;
|
||||
|
||||
char op = mOperators[mOperators.size()-1];
|
||||
|
||||
if (op!='m') // unary -
|
||||
return 0;
|
||||
|
||||
mOperators.resize (mOperators.size()-1);
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
char ExprParser::popOperand (std::vector<Interpreter::Type_Code>& code)
|
||||
{
|
||||
Operand operand = mOperands[mOperands.size()-1];
|
||||
mOperands.resize (mOperands.size()-1);
|
||||
|
||||
if (operand.mType=='l')
|
||||
Generator::pushInt (code, mLiterals, operand.mInteger);
|
||||
else if (operand.mType=='f')
|
||||
Generator::pushFloat (code, mLiterals, operand.mFloat);
|
||||
else
|
||||
throw std::logic_error ("unknown expression type");
|
||||
|
||||
return operand.mType;
|
||||
}
|
||||
|
||||
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
Literals& literals)
|
||||
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
|
||||
|
@ -18,7 +48,7 @@ namespace Compiler
|
|||
bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (mNextOperand)
|
||||
{
|
||||
{
|
||||
Operand operand;
|
||||
operand.mType = 'l';
|
||||
operand.mInteger = value;
|
||||
|
@ -79,6 +109,17 @@ namespace Compiler
|
|||
return false;
|
||||
}
|
||||
|
||||
if (code==Scanner::S_minus)
|
||||
{
|
||||
if (mNextOperand)
|
||||
{
|
||||
// unary
|
||||
mOperators.push_back ('m');
|
||||
mTokenLoc = loc;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Parser::parseSpecial (code, loc, scanner);
|
||||
}
|
||||
|
||||
|
@ -97,17 +138,24 @@ namespace Compiler
|
|||
if (mNextOperand)
|
||||
getErrorHandler().error ("syntax error in expression", mTokenLoc);
|
||||
|
||||
Operand operand = mOperands[mOperands.size()-1];
|
||||
mOperands.clear();
|
||||
char type = ' ';
|
||||
|
||||
while (!mOperands.empty())
|
||||
{
|
||||
type = popOperand (code);
|
||||
|
||||
while (char op = popUnaryOperator())
|
||||
{
|
||||
if (op=='m')
|
||||
{
|
||||
Generator::negate (code, type);
|
||||
}
|
||||
else
|
||||
throw std::logic_error ("unknown unary operator");
|
||||
}
|
||||
}
|
||||
|
||||
if (operand.mType=='l')
|
||||
Generator::pushInt (code, mLiterals, operand.mInteger);
|
||||
else if (operand.mType=='f')
|
||||
Generator::pushFloat (code, mLiterals, operand.mFloat);
|
||||
else
|
||||
throw std::logic_error ("unknown expression type");
|
||||
|
||||
return operand.mType;
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,11 @@ namespace Compiler
|
|||
bool mNextOperand;
|
||||
TokenLoc mTokenLoc;
|
||||
|
||||
char popUnaryOperator();
|
||||
///< returns 0 and not popping, if the next operator isn't unary
|
||||
|
||||
char popOperand (std::vector<Interpreter::Type_Code>& code);
|
||||
|
||||
public:
|
||||
|
||||
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
|
|
|
@ -84,6 +84,16 @@ namespace
|
|||
{
|
||||
code.push_back (segment5 (2));
|
||||
}
|
||||
|
||||
void opNegateInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (7));
|
||||
}
|
||||
|
||||
void opNegateFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (8));
|
||||
}
|
||||
}
|
||||
|
||||
namespace Compiler
|
||||
|
@ -145,6 +155,26 @@ namespace Compiler
|
|||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
void negate (CodeContainer& code, char valueType)
|
||||
{
|
||||
switch (valueType)
|
||||
{
|
||||
case 'l':
|
||||
|
||||
opNegateInt (code);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
|
||||
opNegateFloat (code);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ namespace Compiler
|
|||
|
||||
void assignToLocal (CodeContainer& code, char localType,
|
||||
int localIndex, const CodeContainer& value, char valueType);
|
||||
|
||||
void negate (CodeContainer& code, char valueType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ op 3: convert stack[0] from integer to float
|
|||
op 4: replace stack[0] with integer literal index stack[0]
|
||||
op 5: replace stack[0] with float literal index stack[0]
|
||||
op 6: convert stack[0] from float to integer
|
||||
opcodes 7-33554431 unused
|
||||
op 7: invert sign of int value stack[0]
|
||||
op 8: invert sign of float value stack[0]
|
||||
opcodes 9-33554431 unused
|
||||
opcodes 33554432-67108863 reserved for extensions
|
||||
|
||||
|
|
|
@ -39,6 +39,30 @@ namespace Interpreter
|
|||
runtime[0] = *reinterpret_cast<Type_Data *> (&integerValue);
|
||||
}
|
||||
};
|
||||
|
||||
class OpNegateInt : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Integer data = *reinterpret_cast<Type_Integer *> (&runtime[0]);
|
||||
data = -data;
|
||||
runtime[0] = *reinterpret_cast<Type_Data *> (&data);
|
||||
}
|
||||
};
|
||||
|
||||
class OpNegateFloat : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Float data = *reinterpret_cast<Type_Float *> (&runtime[0]);
|
||||
data = -data;
|
||||
runtime[0] = *reinterpret_cast<Type_Data *> (&data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,9 @@ namespace Interpreter
|
|||
interpreter.installSegment0 (0, new OpPushInt);
|
||||
interpreter.installSegment5 (3, new OpIntToFloat);
|
||||
interpreter.installSegment5 (6, new OpFloatToInt);
|
||||
|
||||
interpreter.installSegment5 (7, new OpNegateInt);
|
||||
interpreter.installSegment5 (8, new OpNegateFloat);
|
||||
|
||||
// local variables
|
||||
interpreter.installSegment5 (0, new OpStoreLocalShort);
|
||||
interpreter.installSegment5 (1, new OpStoreLocalLong);
|
||||
|
|
Loading…
Reference in a new issue