forked from teamnwah/openmw-tes3coop
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
|
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,
|
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||||
Literals& literals)
|
Literals& literals)
|
||||||
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
|
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
|
||||||
|
@ -18,7 +48,7 @@ namespace Compiler
|
||||||
bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
||||||
{
|
{
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
{
|
{
|
||||||
Operand operand;
|
Operand operand;
|
||||||
operand.mType = 'l';
|
operand.mType = 'l';
|
||||||
operand.mInteger = value;
|
operand.mInteger = value;
|
||||||
|
@ -79,6 +109,17 @@ namespace Compiler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (code==Scanner::S_minus)
|
||||||
|
{
|
||||||
|
if (mNextOperand)
|
||||||
|
{
|
||||||
|
// unary
|
||||||
|
mOperators.push_back ('m');
|
||||||
|
mTokenLoc = loc;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Parser::parseSpecial (code, loc, scanner);
|
return Parser::parseSpecial (code, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,17 +138,24 @@ namespace Compiler
|
||||||
if (mNextOperand)
|
if (mNextOperand)
|
||||||
getErrorHandler().error ("syntax error in expression", mTokenLoc);
|
getErrorHandler().error ("syntax error in expression", mTokenLoc);
|
||||||
|
|
||||||
Operand operand = mOperands[mOperands.size()-1];
|
char type = ' ';
|
||||||
mOperands.clear();
|
|
||||||
|
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')
|
return type;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,11 @@ namespace Compiler
|
||||||
bool mNextOperand;
|
bool mNextOperand;
|
||||||
TokenLoc mTokenLoc;
|
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:
|
public:
|
||||||
|
|
||||||
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||||
|
|
|
@ -84,6 +84,16 @@ namespace
|
||||||
{
|
{
|
||||||
code.push_back (segment5 (2));
|
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
|
namespace Compiler
|
||||||
|
@ -145,6 +155,26 @@ namespace Compiler
|
||||||
assert (0);
|
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,
|
void assignToLocal (CodeContainer& code, char localType,
|
||||||
int localIndex, const CodeContainer& value, char valueType);
|
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 4: replace stack[0] with integer literal index stack[0]
|
||||||
op 5: replace stack[0] with float literal index stack[0]
|
op 5: replace stack[0] with float literal index stack[0]
|
||||||
op 6: convert stack[0] from float to integer
|
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
|
opcodes 33554432-67108863 reserved for extensions
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,30 @@ namespace Interpreter
|
||||||
runtime[0] = *reinterpret_cast<Type_Data *> (&integerValue);
|
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
|
#endif
|
||||||
|
|
|
@ -13,7 +13,9 @@ namespace Interpreter
|
||||||
interpreter.installSegment0 (0, new OpPushInt);
|
interpreter.installSegment0 (0, new OpPushInt);
|
||||||
interpreter.installSegment5 (3, new OpIntToFloat);
|
interpreter.installSegment5 (3, new OpIntToFloat);
|
||||||
interpreter.installSegment5 (6, new OpFloatToInt);
|
interpreter.installSegment5 (6, new OpFloatToInt);
|
||||||
|
interpreter.installSegment5 (7, new OpNegateInt);
|
||||||
|
interpreter.installSegment5 (8, new OpNegateFloat);
|
||||||
|
|
||||||
// local variables
|
// local variables
|
||||||
interpreter.installSegment5 (0, new OpStoreLocalShort);
|
interpreter.installSegment5 (0, new OpStoreLocalShort);
|
||||||
interpreter.installSegment5 (1, new OpStoreLocalLong);
|
interpreter.installSegment5 (1, new OpStoreLocalLong);
|
||||||
|
|
Loading…
Reference in a new issue