// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*-
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
//
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
// ACDK
//
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
//
#include <acdk/io/StreamTokenizer.h>
#include <acdk/io/FileReader.h>
#include <acdk/io/StringReader.h>
#include <acdk/io/ByteToCharReader.h>
#include <acdk/locale/Encoding.h>
#include <acdk/lang/System.h>
#include <acdk/lang/dmi/AcdkStdWeakTypeDmiClient.h>
#include <acdk/lang/sys/core_vector.h>
#include <acdk/lang/dmi/DmiObject.h>
#include <acdk/lang/dmi/DmiDelegate.h>
#include <acdk/lang/dmi/MetaInfoChildsArray.h>
#include <acdk/lang/reflect/Method.h>
#include "ScriptObject.h"
#include "Script.h"
#include "ScriptException.h"
#include "ScriptEval.h"
#include "ScriptExpr.h"
#include "ScriptGlobals.h"
namespace acdk {
namespace cfgscript {
using acdk::io::StreamTokenizer;
PEVal::PEVal(Token t, IN(PEVal) left, IN(PEVal) right)
: tk(t)
, args(new LeftRightArgs(left, right))
{
}
//static
RString
PEVal::tokenToString(int tk)
{
switch (tk)
{
case TT_VALUE: return "VALUE";
case TT_REFVALUE: return "REFVALUE";
case TT_IDENT: return "IDENT";
case TT_ARGLABEL: return "ARGLABEL";
case TT_OPERATOR: return "OPERATOR";
case TT_METHOD: return "METHOD";
case TT_FIELD: return "FIELD";
case TT_DOTOP: return "DOTOP";
default: return RString("UnknownTk=[") + tk + "]";
}
}
RString
PEVal::toCode()
{
switch (tk)
{
case TT_DOTOP:
if (args != Nil)
return args->left.toCode() + "." + args->right.toCode();
return ".";
case TT_REFVALUE:
case TT_VALUE: return val.toString();
case TT_METHOD:
case TT_UNIT:
case TT_CLASS:
case TT_OPERATOR:
case TT_IDENT: return val.getStringVar();
case TT_ARGLABEL: return val.getStringVar() + ":";
default: return RString("UnknownTk=[") + tk + "]";
}
}
RString
PEVal::toString()
{
if (tk == TT_DOTOP && args != Nil)
return tokenToString(tk) + ": " + args->left.toString() + "." + args->right.toString();
return tokenToString(tk) + ": " + val.getClazzInfo()->name + "=" + val.toCode();
}
/*
OpDescription OpPriorities[] =
{
{ "operator_popc", 1, OpSuffix | OpOutfix }, // ()
{ "operator_co", 1, OpSuffix | OpOutfix }, // {
{ "operator_po", 1, OpSuffix | OpOutfix }, // ()
{ "operator_bobc", 1, OpSuffix | OpOutfix }, // []
{ "operator_bo", 1, OpSuffix | OpOutfix }, // []
{ "operator_dt", 1, OpPrefix | OpInfix }, // .
{ "operator_migt", 1, OpInfix }, // ->
{ "operator_plpl", 2, OpPrefix | OpSuffix | OpRightAssoc }, // ++
{ "operator_mimi", 2, OpPrefix | OpSuffix | OpRightAssoc }, // --
{ "operator_new", 2, OpPrefix }, // new
{ "operator_instanceof", 2, OpInfix }, // *
{ "operator_as", 2, OpInfix }, // *
{ "operator_sl", 2, OpInfix }, // /
{ "operator_pl", 3, OpPrefix | OpInfix }, // +
{ "operator_mi", 3, OpPrefix | OpInfix }, // -
{ "operator_ltlt", 4, OpInfix }, // <<
{ "operator_gtgt", 4, OpInfix }, // >>
{ "operator_gt", 5, OpInfix },
{ "operator_lt", 5, OpInfix },
{ "operator_gteq", 5, OpInfix },
{ "operator_lteq", 5, OpInfix },
{ "operator_eqeq", 6, OpInfix },
{ "operator_nteq", 6, OpInfix },
{ "operator_la", 7, OpInfix }, // &
{ "operator_rf", 8, OpInfix }, // ^
{ "operator_vb", 9, OpInfix }, // |
{ "operator_lala", 10, OpInfix }, // &&
{ "operator_vbvb", 11, OpInfix }, // ||
{ "operator_eq", 12, OpInfix | OpRightAssoc }, // =
{ 0, 0, 0 }
};
*/
OpDescription UnEncodedOpPriorities[] =
{
{ "{", 1, OpOutfix }, // .
{ ".", 1, OpPrefix | OpInfix }, // .
{ "->", 1, OpInfix }, // ->
{ "`", 2, OpSuffix | OpOutfix }, // `<string-literal>`
{ "(", 2, OpSuffix | OpOutfix }, // ()
{ "[", 2, OpSuffix | OpOutfix }, // []
{ "!", 2, OpPrefix },
{ "++", 2, OpPrefix | OpSuffix | OpRightAssoc }, // ++
{ "--", 2, OpPrefix | OpSuffix | OpRightAssoc }, // --
{ "new", 2, OpPrefix }, // *
{ "instanceof", 2, OpInfix }, //
{ "*", 2, OpInfix }, // *
{ "/", 2, OpInfix }, // /
{ "%", 2, OpInfix }, // /
{ "+", 3, OpPrefix | OpInfix }, // +
{ "-", 3, OpPrefix | OpInfix }, // -
{ "<<", 4, OpInfix }, // <<
{ ">>", 4, OpInfix }, // >>
{ ">", 5, OpInfix },
{ "<", 5, OpInfix },
{ ">=", 5, OpInfix },
{ "<=", 5, OpInfix },
{ "==", 6, OpInfix },
{ "!=", 6, OpInfix },
{ "&", 7, OpInfix }, // &
{ "^", 8, OpInfix }, // ^
{ "|", 9, OpInfix }, // |
{ "&&", 10, OpInfix }, // &&
{ "||", 11, OpInfix }, // ||
{ "=", 12, OpInfix | OpRightAssoc }, // =
{ 0, 0, 0 }
};
OpDescription varOpDescription = { "", 1, OpVarOrIdent };
const OpDescription&
getOperatorDesc(INP(RString) op)
{
int i;
for (i = 0; UnEncodedOpPriorities[i].op != 0; ++i)
if (op->equals(UnEncodedOpPriorities[i].op) == true)
return UnEncodedOpPriorities[i];
return UnEncodedOpPriorities[i];
}
int getOperatorPredence(INP(RString) op)
{
for (int i = 0; UnEncodedOpPriorities[i].op != 0; ++i)
if (op->equals(UnEncodedOpPriorities[i].op) == true)
return UnEncodedOpPriorities[i].prio;
return -1;
}
int getOperatorFlags(INP(RString) op)
{
//RString opstr = acdk::lang::reflect::Method::encodeOperatorToFuncName(op);
for (int i = 0; UnEncodedOpPriorities[i].op != 0; ++i)
if (op->equals(UnEncodedOpPriorities[i].op) == true)
return UnEncodedOpPriorities[i].flags;
return 0;
}
int compareOperators(INP(RString) left, INP(RString) right)
{
return getOperatorPredence(left) -
getOperatorPredence(right);
}
bool isOperator(const SourceToken& stk)
{
if (stk.tk == StreamTokenizer::TT_OPERATOR ||
stk.tk == '(' ||
stk.tk == '[' ||
stk.tk == '%' ||
stk.tk == '{' ||
stk.tk == '`' )
return true;
if (stk.tk == StreamTokenizer::TT_WORD)
{
ASCLITERAL(new);
ASCLITERAL(instanceof);
RString sval = stk.value.getStringVar();
if (sval->equals(lit_new) == true ||
sval->equals(lit_instanceof) == true)
return true;
}
return false;
}
bool valOrIdent(const SourceToken& stk)
{
return stk.tk == StreamTokenizer::TT_NUMBER || stk.tk == StreamTokenizer::TT_STRING ||
stk.tk == StreamTokenizer::TT_QCHAR ||
(stk.tk == StreamTokenizer::TT_WORD && isOperator(stk) == false);
}
bool isEndExpr(const SourceToken& stk)
{
return stk.tk != StreamTokenizer::TT_NUMBER &&
stk.tk != StreamTokenizer::TT_STRING &&
stk.tk != StreamTokenizer::TT_WORD &&
stk.tk != StreamTokenizer::TT_QCHAR &&
isOperator(stk) == false
;
}
bool parseExpression(PEStack& stack, OUTP(RScriptExpr) expr);
bool
parseLeftOfNonExpr(PEStack& stack, OUTP(RScriptExpr) expr)
{
int mparsePos = stack.getCurTokenIndex();
int mtk = stack.nextToken();
RString ctstr = stack.curTokenAsCode();
if (isEndExpr(stack.curSourceToken()) == true)
{
expr = new ScriptExpr(varOpDescription, mparsePos);
return true;
}
if (isOperator(stack.curSourceToken()) == true) // x +
{
RString leftstr = stack.curTokenAsString();
const OpDescription& opdesc = getOperatorDesc(leftstr);
if ((opdesc.flags & OpSuffix) == OpSuffix) // x++
{
RScriptExpr leftExpr;
if (parseLeftOfNonExpr(stack, leftExpr) == false)
return false;
expr = new ScriptExpr(opdesc, mparsePos, Nil, leftExpr);
return true;
}
else if ((opdesc.flags & OpOutfix) == OpSuffix) // x(
{
if (parseExpression(stack, expr) == false)
return false;
expr = new ScriptExpr(opdesc, mparsePos, expr);
return true;
}
else if ((opdesc.flags & OpInfix) == OpInfix) // x + ?
{
if (parseExpression(stack, expr) == false)
return false;
if (opdesc.prio <= expr->opDescription.prio)
{
// x * y + 3
RScriptExpr texpr = new ScriptExpr(opdesc, mparsePos);
texpr->rightExpr = expr->leftExpr;
expr->leftExpr = texpr;
}
else
{
// x + y * 3
expr = new ScriptExpr(opdesc, mparsePos, expr);
}
return true;
}
else
{
ELOG("Unknown Token Type: " + leftstr);
}
}
return false;
}
bool
parseExpression(PEStack& stack, OUTP(RScriptExpr) expr)
{
int cparsePos = stack.getCurTokenIndex();
int otk = stack.nextToken();
if (otk == -1)
{
return false;
}
RString leftstr = stack.curTokenAsString();
if (isEndExpr(stack.curSourceToken()) == true)
{
expr = new EmptyExpr();
return true;
}
if (isOperator(stack.curSourceToken()) == true)
{
const OpDescription& opdesc = getOperatorDesc(leftstr);
if ((opdesc.flags & OpPrefix) == OpPrefix)
{
RScriptExpr rightExpr;
if (parseExpression(stack, rightExpr) == false)
return false;
if (opdesc.prio > rightExpr->opDescription.prio)
{
// ++i.left =>
// ++
// Nil i . left
expr = new ScriptExpr(opdesc, cparsePos, Nil, rightExpr);
}
else
{
// ++i * 3 =>
// *
// ++
// i 3
expr = new ScriptExpr(opdesc, cparsePos, Nil, rightExpr->leftExpr);
rightExpr->leftExpr = expr;
expr = rightExpr;
}
return true;
}
else if ((opdesc.flags & OpOutfix) == OpOutfix)
{
RScriptExpr rightExpr;
if (parseExpression(stack, rightExpr) == false)
return false;
expr = new ScriptExpr(opdesc, cparsePos, Nil, rightExpr);
int otk2 = stack.nextToken(); // closing expr
return true;
}
else
{
ELOG("Operator is not prefix or outfix: " + leftstr);
}
}
else // left is no operator
{
// x
RScriptExpr rightExpr;
if (parseLeftOfNonExpr(stack, rightExpr) == false)
return false;
if (rightExpr->opDescription.flags == OpEmpty)
{
expr = new VarOrValExpr(cparsePos);
return true;
}
/*
if (opdesc.prio <= rightExpr->opDescription.prio)
{
expr = new VarOrValExpr(cparsePos);
return true;
}
if (opdesc.prio > rightExpr->opDescription.prio)
{
rightExpr
}
else
{
}*/
return true;
}
return false;
}
//static
acdk::lang::dmi::RDmiObject
ScriptGlobals::castTo(IN(RDmiObject) val, IN(acdk::lang::RClass) cls)
{
if (val->ScriptVar::getClazzInfo() == cls->objectClazzInfo())
return val;
using namespace acdk::lang::dmi;
return new acdk::lang::dmi::DmiObject(val->_castScriptVar(cls->objectClazzInfo(),
SVCastSVCastChar2Int | SVCastInt2Float | SVCastNum2Bool | SVCastBool2Number | SVCastObject2Bool | SVCastAutobox));
}
} // namespace cfgscript
} // namespace acdk
|