2026-05-13 16:28:02 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| StaticAst.mqh |
|
|
|
|
|
//| Copyright 2026, Niquel Mendoza. |
|
|
|
|
|
//| https://www.mql5.com/es/users/nique_372/news |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#property copyright "Copyright 2026, Niquel Mendoza."
|
|
|
|
|
#property link "https://www.mql5.com/es/users/nique_372/news"
|
|
|
|
|
#property strict
|
|
|
|
|
|
|
|
|
|
#ifndef EXPRESSEVALBYLEO_SRC_MATHEVAL_STATIC_AST_MQH
|
|
|
|
|
#define EXPRESSEVALBYLEO_SRC_MATHEVAL_STATIC_AST_MQH
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#include "Defines.mqh"
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Este AST solo procesa operaciones estaticas (Sin valores dinamicos) @smop(10 * 29 * (10 + 20) % 30)
|
|
|
|
|
// Esta super optimizado para ello en cambio
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
struct pack(sizeof(int)) CMathExpresionEvalStatic
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
int m_pos;
|
|
|
|
|
int m_size;
|
|
|
|
|
ENUM_MATH_EVAL_EXP_ERR_PARSE m_last_err;
|
|
|
|
|
int m_err_pos;
|
|
|
|
|
int m_para_stack;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
bool ParseInternalRaw(const TokenMathExp& tokens[], const int math_op, BitInterpreter &val, int& type);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
bool RawOp(const TokenMathExp &tokens[], const int type_op, int pos1, int pos2, BitInterpreter &bit, int &type);
|
|
|
|
|
bool RawOpAply(const TokenMathExp &tokens[], const int type_op, int pos2, BitInterpreter &bit, int &type);
|
|
|
|
|
bool RawOpSobreBits(const TokenMathExp &tokens[], const int type_op, BitInterpreter& bit, int& type, const BitInterpreter &bit2, const int type_2);
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
CMathExpresionEvalStatic(void) {}
|
|
|
|
|
//~CMathExpresionEvalStatic(void) {}
|
|
|
|
|
|
|
|
|
|
//---
|
2026-05-14 14:13:20 -05:00
|
|
|
void CleanCache(const TokenMathExp& tokens[]);
|
|
|
|
|
bool ParsNoRes(const TokenMathExp &tokens[], BitInterpreter& it, int& type);
|
2026-05-13 16:28:02 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
__forceinline ENUM_MATH_EVAL_EXP_ERR_PARSE LastErr() const { return m_last_err; }
|
|
|
|
|
__forceinline int LastErrPos() const { return m_err_pos; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-05-14 14:13:20 -05:00
|
|
|
void CMathExpresionEvalStatic::CleanCache(const TokenMathExp& tokens[])
|
2026-05-13 16:28:02 -05:00
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
m_size = ArraySize(tokens);
|
|
|
|
|
m_pos = 0;
|
|
|
|
|
m_para_stack = 0;
|
2026-05-14 14:13:20 -05:00
|
|
|
m_err_pos = 0;
|
2026-05-13 16:28:02 -05:00
|
|
|
m_last_err = WRONG_VALUE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// ParseNoRes // 10 * 20 -
|
|
|
|
|
// ParseInternalRaw // 200 - 10 + 2
|
|
|
|
|
// ParseInternalRaw // 190 + 2 *
|
|
|
|
|
// ParsNoRes // 2 * 2
|
|
|
|
|
// ParseInternalRaw // 190 + 4
|
|
|
|
|
// .
|
|
|
|
|
// .
|
|
|
|
|
// 10 * 20 - 10 + 2 * 2
|
|
|
|
|
// 200 - 10 + 2 * 2
|
|
|
|
|
// 190 + 2 * 2
|
|
|
|
|
// 200 -
|
|
|
|
|
//
|
|
|
|
|
//---
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CMathExpresionEvalStatic::RawOp(const TokenMathExp &tokens[], const int type_op, int pos1, int pos2, BitInterpreter &bit, int &type)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// Se asume que pos1, pos2 son numeros
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const int type_number_1 = tokens[pos1].type >> AST_LOGIC_EXTRA_TYPE_START_BIT; // Tipo de numero 1
|
|
|
|
|
const int type_number_2 = tokens[pos2].type >> AST_LOGIC_EXTRA_TYPE_START_BIT; // Tipo de numero 2
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if((type_number_1 & type_number_2) == 1)
|
|
|
|
|
{
|
|
|
|
|
type = AST_LOGIC_NUMBER_INTEGER;
|
|
|
|
|
switch(type_op)
|
|
|
|
|
{
|
|
|
|
|
case BINARY_NODE_OP_BIT_OR:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value | tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_XOR:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value ^ tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_AND:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value & tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_DEZPLAZAMIENTO_DRC:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value >> tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_DEZPLAZAMIENTO_IZQ:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value << tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_RESTA:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value - tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_SUMA:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value + tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_MODULO:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value % tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_DIVICION:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value / tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_MUL:
|
|
|
|
|
bit.long_value = tokens[pos1].v.long_value * tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
default:
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_TIPO_DE_OPERACION_MATH_DESCONOCIDA;
|
|
|
|
|
m_err_pos = pos2 - 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
const double left = (type_number_1 == AST_LOGIC_NUMBER_DOUBLE) ? tokens[pos1].v.double_value : (double)tokens[pos1].v.long_value;
|
|
|
|
|
const double right = (type_number_2 == AST_LOGIC_NUMBER_DOUBLE) ? tokens[pos2].v.double_value : (double)tokens[pos2].v.long_value;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
type = AST_LOGIC_NUMBER_DOUBLE;
|
|
|
|
|
switch(type_op)
|
|
|
|
|
{
|
|
|
|
|
case BINARY_NODE_OP_RESTA:
|
|
|
|
|
bit.double_value = left - right;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_SUMA:
|
|
|
|
|
bit.double_value = left + right;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_DIVICION:
|
|
|
|
|
bit.double_value = left / right;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_MUL:
|
|
|
|
|
bit.double_value = left * right;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
default:
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_TIPO_DE_OPERACION_INVALIDA_PARA_DBL;
|
|
|
|
|
m_err_pos = pos2 - 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CMathExpresionEvalStatic::RawOpAply(const TokenMathExp &tokens[], const int type_op, int pos2, BitInterpreter &bit, int &type)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// Se asume que pos1, pos2 son numeros
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const int type_number_1 = type; // Tipo de numero 1
|
|
|
|
|
const int type_number_2 = tokens[pos2].type >> AST_LOGIC_EXTRA_TYPE_START_BIT; // Tipo de numero 2
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if((type_number_1 & type_number_2) == 1)
|
|
|
|
|
{
|
|
|
|
|
type = AST_LOGIC_NUMBER_INTEGER;
|
|
|
|
|
switch(type_op)
|
|
|
|
|
{
|
|
|
|
|
case BINARY_NODE_OP_BIT_OR:
|
|
|
|
|
bit.long_value |= tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_XOR:
|
|
|
|
|
bit.long_value ^= tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_AND:
|
|
|
|
|
bit.long_value &= tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_DEZPLAZAMIENTO_DRC:
|
|
|
|
|
bit.long_value >>= tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_DEZPLAZAMIENTO_IZQ:
|
|
|
|
|
bit.long_value <<= tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_RESTA:
|
|
|
|
|
bit.long_value -= tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_SUMA:
|
|
|
|
|
bit.long_value += tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_MODULO:
|
|
|
|
|
bit.long_value %= tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_DIVICION:
|
|
|
|
|
bit.long_value /= tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_MUL:
|
|
|
|
|
bit.long_value *= tokens[pos2].v.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
default:
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_TIPO_DE_OPERACION_MATH_DESCONOCIDA;
|
|
|
|
|
m_err_pos = pos2 - 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
const double right = (type_number_2 == AST_LOGIC_NUMBER_DOUBLE) ? tokens[pos2].v.double_value : (double)tokens[pos2].v.long_value;
|
|
|
|
|
if(type == AST_LOGIC_NUMBER_INTEGER)
|
|
|
|
|
bit.double_value = (double)bit.long_value;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
type = AST_LOGIC_NUMBER_DOUBLE;
|
2026-05-14 13:03:00 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-05-13 16:28:02 -05:00
|
|
|
switch(type_op)
|
|
|
|
|
{
|
|
|
|
|
case BINARY_NODE_OP_RESTA:
|
|
|
|
|
bit.double_value -= right;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_SUMA:
|
|
|
|
|
bit.double_value += right;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_DIVICION:
|
|
|
|
|
bit.double_value /= right;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_MUL:
|
|
|
|
|
bit.double_value *= right;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
default:
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_TIPO_DE_OPERACION_INVALIDA_PARA_DBL;
|
|
|
|
|
m_err_pos = pos2 - 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
2026-05-14 13:03:00 -05:00
|
|
|
return false;
|
2026-05-13 16:28:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CMathExpresionEvalStatic::RawOpSobreBits(const TokenMathExp &tokens[], const int type_op, BitInterpreter& bit, int& type, const BitInterpreter &bit2, const int type_2)
|
|
|
|
|
{
|
|
|
|
|
//--- Ambos son enteros
|
|
|
|
|
if((type & type_2) == 1)
|
|
|
|
|
{
|
|
|
|
|
type = AST_LOGIC_NUMBER_INTEGER;
|
|
|
|
|
|
|
|
|
|
switch(type_op)
|
|
|
|
|
{
|
|
|
|
|
case BINARY_NODE_OP_BIT_OR:
|
|
|
|
|
bit.long_value = bit.long_value | bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_XOR:
|
|
|
|
|
bit.long_value = bit.long_value ^ bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_AND:
|
|
|
|
|
bit.long_value = bit.long_value & bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_DEZPLAZAMIENTO_DRC:
|
|
|
|
|
bit.long_value = bit.long_value >> bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_BIT_DEZPLAZAMIENTO_IZQ:
|
|
|
|
|
bit.long_value = bit.long_value << bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_RESTA:
|
|
|
|
|
bit.long_value = bit.long_value - bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_SUMA:
|
|
|
|
|
bit.long_value = bit.long_value + bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_MODULO:
|
|
|
|
|
bit.long_value = bit.long_value % bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_DIVICION:
|
|
|
|
|
bit.long_value = bit.long_value / bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_MUL:
|
|
|
|
|
bit.long_value = bit.long_value * bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
default:
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_TIPO_DE_OPERACION_MATH_DESCONOCIDA;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const double right = (type_2 == AST_LOGIC_NUMBER_DOUBLE) ? bit2.double_value : (double)bit2.long_value;
|
2026-05-14 13:03:00 -05:00
|
|
|
if(type == AST_LOGIC_NUMBER_INTEGER)
|
|
|
|
|
bit.double_value = (double)bit.long_value;
|
|
|
|
|
|
2026-05-14 11:13:22 -05:00
|
|
|
//---
|
|
|
|
|
type = AST_LOGIC_NUMBER_DOUBLE;
|
2026-05-13 16:28:02 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
switch(type_op)
|
|
|
|
|
{
|
|
|
|
|
case BINARY_NODE_OP_RESTA:
|
2026-05-14 13:03:00 -05:00
|
|
|
bit.double_value -= right;
|
|
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_SUMA:
|
2026-05-14 13:03:00 -05:00
|
|
|
bit.double_value += right;
|
|
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_DIVICION:
|
2026-05-14 13:03:00 -05:00
|
|
|
bit.double_value /= right;
|
|
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
case BINARY_NODE_OP_MUL:
|
2026-05-14 13:03:00 -05:00
|
|
|
bit.double_value *= right;
|
|
|
|
|
return true;
|
2026-05-13 16:28:02 -05:00
|
|
|
default:
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_TIPO_DE_OPERACION_INVALIDA_PARA_DBL;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CMathExpresionEvalStatic::ParsNoRes(const TokenMathExp &tokens[], BitInterpreter& it, int& type)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// La idea con esta funcion es pase normal tal cual
|
|
|
|
|
|
|
|
|
|
//--- Extraccion
|
|
|
|
|
// Tipo de numero 1
|
|
|
|
|
int tkn_type = tokens[m_pos].type & 0xFFFF;
|
|
|
|
|
if(tkn_type == AST_TOKEN_MATH_T_VALUE_OPERDOR_PARA_INI)
|
|
|
|
|
{
|
|
|
|
|
m_para_stack++;
|
|
|
|
|
m_pos++; // Le sigue un numero
|
|
|
|
|
|
|
|
|
|
//---
|
2026-05-14 16:54:23 -05:00
|
|
|
if((tokens[m_pos].type & 0xFFFF) != AST_TOKEN_MATH_T_VALUE_NUMBER)
|
2026-05-13 16:28:02 -05:00
|
|
|
{
|
2026-05-14 12:56:06 -05:00
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_VALOR;
|
2026-05-13 16:28:02 -05:00
|
|
|
m_err_pos = m_pos - 1; // previa a para
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2026-05-14 16:54:23 -05:00
|
|
|
if(tkn_type != AST_TOKEN_MATH_T_VALUE_NUMBER)
|
2026-05-13 16:28:02 -05:00
|
|
|
{
|
2026-05-14 16:54:23 -05:00
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_VALOR;
|
|
|
|
|
m_err_pos = m_pos; // previa a para
|
2026-05-13 16:28:02 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const int pos_val_1 = m_pos++;
|
|
|
|
|
// NOTA: Ahora mismo solo extraemos el tipo
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Check de len
|
|
|
|
|
// neceistmos 2 tokens mas
|
|
|
|
|
// [m_pos]: tipo op
|
|
|
|
|
// [m_pos + 1]: valor | o para ini
|
|
|
|
|
if(m_pos + 1 >= m_size)
|
|
|
|
|
{
|
|
|
|
|
// En este caso solo hay un valor asi que lo damos
|
|
|
|
|
type = tokens[pos_val_1].type >> AST_LOGIC_EXTRA_TYPE_START_BIT;
|
|
|
|
|
if(type == AST_LOGIC_NUMBER_INTEGER)
|
|
|
|
|
{
|
|
|
|
|
it.long_value = tokens[pos_val_1].v.long_value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
it.double_value = tokens[pos_val_1].v.double_value;
|
|
|
|
|
}
|
|
|
|
|
// Listo retornamos
|
|
|
|
|
return true;
|
|
|
|
|
} // Contianuamos
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Tipó de op
|
|
|
|
|
// Aqui esta el tipo de operacion matematica
|
|
|
|
|
tkn_type = tokens[m_pos].type & 0xFFFF;
|
|
|
|
|
if(tkn_type != AST_TOKEN_MATH_T_VALUE_OPERDOR_MATEMATICO)
|
|
|
|
|
{
|
|
|
|
|
if(m_para_stack == 0)
|
|
|
|
|
{
|
|
|
|
|
// Luego de un valor siempre debe de haber un operador matematico
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_OPERADOR_MATEMATICO;
|
|
|
|
|
m_err_pos = m_pos;
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(tkn_type == AST_TOKEN_MATH_T_VALUE_OPERDOR_PARA_END) // Para end o operador
|
|
|
|
|
{
|
|
|
|
|
m_para_stack--;
|
|
|
|
|
if((tkn_type = (tokens[++m_pos].type & 0xFFFF)) != AST_TOKEN_MATH_T_VALUE_OPERDOR_MATEMATICO)
|
|
|
|
|
{
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_OPERADOR_LUEGO_DE_PARA;
|
|
|
|
|
m_err_pos = m_pos - 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Ahora mismo estamos en el operador
|
|
|
|
|
}
|
|
|
|
|
// No hay parantesis nodo abierto....
|
|
|
|
|
}
|
|
|
|
|
const int type_op_1 = tokens[m_pos++].type >> AST_LOGIC_EXTRA_TYPE_START_BIT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Tipo de valor 2
|
|
|
|
|
tkn_type = tokens[m_pos].type & 0xFFFF;
|
|
|
|
|
if(tkn_type == AST_TOKEN_MATH_T_VALUE_OPERDOR_PARA_INI)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// En este caso lo que haremo sera parar lo que estuvimos haciendo...
|
|
|
|
|
type = tokens[pos_val_1].type >> AST_LOGIC_EXTRA_TYPE_START_BIT;
|
|
|
|
|
if(type == AST_LOGIC_NUMBER_INTEGER)
|
|
|
|
|
{
|
|
|
|
|
it.long_value = tokens[pos_val_1].v.long_value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
it.double_value = tokens[pos_val_1].v.double_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
//const int locked = m_para_stack;
|
|
|
|
|
BitInterpreter bit;
|
|
|
|
|
int bit_type;
|
|
|
|
|
//
|
|
|
|
|
if(!ParsNoRes(tokens, bit, bit_type))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(!RawOpSobreBits(tokens, type_op_1, it, type, bit, bit_type))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//Print("VALUE 1: ", (type == AST_LOGIC_NUMBER_DOUBLE ? it.double_value : it.long_value), " TYPE: ", type);
|
|
|
|
|
//Print("VALUE 2: ", (bit_type == AST_LOGIC_NUMBER_DOUBLE ? bit.double_value : bit.long_value), " TYPE: ", bit_type);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_para_stack--; // Restamos la idea es acabar en )
|
|
|
|
|
// Asi quye ahora mismo pos apunta a ello m_pos=)
|
|
|
|
|
|
|
|
|
|
if(m_pos + 2 < m_size)
|
|
|
|
|
{
|
|
|
|
|
// Necesitaremos dos espacios mas..
|
|
|
|
|
// Ahora misto esmtaos en = [)][Opeador][( Or Valor]
|
|
|
|
|
|
|
|
|
|
const int t = (tokens[++m_pos].type & 0xFFFF);
|
|
|
|
|
if(t == AST_TOKEN_MATH_T_VALUE_OPERDOR_PARA_END)
|
|
|
|
|
{
|
|
|
|
|
// Para end no hay nada mas que hacer
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(t != AST_TOKEN_MATH_T_VALUE_OPERDOR_MATEMATICO)
|
|
|
|
|
{
|
|
|
|
|
// Error luego de un ) tiene que haber un operador matematico (no un numoero valor)
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_OPERADOR_LUEGO_DE_PARA;
|
|
|
|
|
m_err_pos = m_pos - 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Continuamos el parseo agregando al valor actual
|
|
|
|
|
// pos++ para el siguiente valor seira [( or valor]
|
|
|
|
|
return ParseInternalRaw(tokens, (tokens[m_pos++].type >> AST_LOGIC_EXTRA_TYPE_START_BIT), it, type);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
}
|
|
|
|
|
else
|
2026-05-14 16:54:23 -05:00
|
|
|
if(tkn_type != AST_TOKEN_MATH_T_VALUE_NUMBER)
|
2026-05-13 16:28:02 -05:00
|
|
|
{
|
2026-05-14 16:54:23 -05:00
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_VALOR;
|
|
|
|
|
m_err_pos = m_pos; // previa a para
|
2026-05-13 16:28:02 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const int pos_val_2 = m_pos++; // Valores [Raw | Variable | Funcion Build-in | Funcion Custom]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Operador 2... este es opcional en caso exista haremos recursion
|
|
|
|
|
// 1. Ero comprobaremos si hay espacio para el token actual
|
|
|
|
|
// neceistamos dos tokens
|
|
|
|
|
// [op][val] (Dado que si hay un op si o si tinee uqe haber un val o parentesis)
|
|
|
|
|
bool is_closed = false;
|
|
|
|
|
if(m_pos + 1 >= m_size || (is_closed = ((tokens[m_pos].type & 0xFFFF) == AST_TOKEN_MATH_T_VALUE_OPERDOR_PARA_END)))
|
|
|
|
|
{
|
|
|
|
|
//if(is_closed)
|
|
|
|
|
// m_para_stack--;
|
|
|
|
|
|
|
|
|
|
// No hay espacio, solo tenemos V X V
|
|
|
|
|
// Ahora la idea aqui seria calcular el resultado
|
|
|
|
|
return RawOp(tokens, type_op_1, pos_val_1, pos_val_2, it, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Extraemos op2
|
|
|
|
|
tkn_type = tokens[m_pos].type & 0xFFFF;
|
|
|
|
|
if(tkn_type != AST_TOKEN_MATH_T_VALUE_OPERDOR_MATEMATICO)
|
|
|
|
|
{
|
|
|
|
|
// Luego de un valor siempre debe de haber un operador matematico
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_OPERADOR_MATEMATICO;
|
|
|
|
|
m_err_pos = m_pos;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const int type_op_2 = tokens[m_pos++].type >> AST_LOGIC_EXTRA_TYPE_START_BIT;
|
|
|
|
|
// m_pos = apunta ahora mismo al siguiente valor o () o ~
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- En caso haya otro operador +\* etc..
|
|
|
|
|
// La idea sera ver cual es mas improtante el op1 uno actual?¿ o el otro
|
|
|
|
|
if(type_op_2 > type_op_1)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// El operador siguiente 2 es mas impornate que el actual... enotnces lo que haremos
|
|
|
|
|
// Sera reducir primermente nuestor puntero de lectura para que apunte al valor 2
|
|
|
|
|
// [Valor][Op1][Valor2][Op2]
|
|
|
|
|
|
|
|
|
|
//--- Asignamos un valor
|
|
|
|
|
type = tokens[pos_val_1].type >> AST_LOGIC_EXTRA_TYPE_START_BIT;
|
|
|
|
|
if(type == AST_LOGIC_NUMBER_INTEGER)
|
|
|
|
|
{
|
|
|
|
|
it.long_value = tokens[pos_val_1].v.long_value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
it.double_value = tokens[pos_val_1].v.double_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
//Print("VALUE 1: ", (type == AST_LOGIC_NUMBER_DOUBLE ? it.double_value : it.long_value), " TYPE: ", type);
|
|
|
|
|
|
|
|
|
|
//--- Continuamos con op2
|
|
|
|
|
BitInterpreter bit;
|
|
|
|
|
int bit_type = tokens[pos_val_2].type >> AST_LOGIC_EXTRA_TYPE_START_BIT;
|
|
|
|
|
if(bit_type == AST_LOGIC_NUMBER_INTEGER)
|
|
|
|
|
{
|
|
|
|
|
bit.long_value = tokens[pos_val_2].v.long_value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bit.double_value = tokens[pos_val_2].v.double_value;
|
|
|
|
|
}
|
|
|
|
|
if(!ParseInternalRaw(tokens, type_op_2, bit, bit_type))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//Print("VALUE 2: ", (bit_type == AST_LOGIC_NUMBER_DOUBLE ? bit.double_value : bit.long_value), " TYPE: ", bit_type);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Print("OP2: " , type_op_1);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Junsta ambos bits y reotrn true
|
|
|
|
|
return RawOpSobreBits(tokens, type_op_1, it, type, bit, bit_type);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// En este caso No lo es asi que aprovecharemos en dar valor a nuesto it actual
|
|
|
|
|
if(!RawOp(tokens, type_op_1, pos_val_1, pos_val_2, it, type))
|
|
|
|
|
return false;
|
|
|
|
|
// Luego continuareoms
|
|
|
|
|
|
|
|
|
|
return ParseInternalRaw(tokens, type_op_2, it, type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
// 200 - 10 + 2 * 2
|
|
|
|
|
// 190 + 2 * 2.0
|
|
|
|
|
bool CMathExpresionEvalStatic::ParseInternalRaw(const TokenMathExp& tokens[], const int math_op, BitInterpreter &val, int& type)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// Ahora mismo nos ubicamos en la posicion de valor (Valor | () | ~)
|
|
|
|
|
|
|
|
|
|
//--- Valor
|
|
|
|
|
int tkn_type = tokens[m_pos].type & 0xFFFF;
|
|
|
|
|
if(tkn_type == AST_TOKEN_MATH_T_VALUE_OPERDOR_PARA_INI)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
//const int locked = m_para_stack;
|
|
|
|
|
BitInterpreter bit;
|
|
|
|
|
int bit_type;
|
|
|
|
|
// aumenta stak
|
|
|
|
|
if(!ParsNoRes(tokens, bit, bit_type))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(!RawOpSobreBits(tokens, math_op, val, type, bit, bit_type))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_para_stack--; // Restamos la idea es acabar en )
|
|
|
|
|
// Asi quye ahora mismo pos apunta a ello m_pos=)
|
|
|
|
|
|
|
|
|
|
if(m_pos + 2 < m_size)
|
|
|
|
|
{
|
|
|
|
|
// Necesitaremos dos espacios mas..
|
|
|
|
|
// Ahora misto esmtaos en = [)][Opeador][( Or Valor]
|
|
|
|
|
|
|
|
|
|
const int t = (tokens[++m_pos].type & 0xFFFF);
|
|
|
|
|
if(t == AST_TOKEN_MATH_T_VALUE_OPERDOR_PARA_END)
|
|
|
|
|
{
|
|
|
|
|
// Para end no hay nada mas que hacer
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if(t != AST_TOKEN_MATH_T_VALUE_OPERDOR_MATEMATICO)
|
|
|
|
|
{
|
|
|
|
|
// Error luego de un ) tiene que haber un operador matematico (no un numoero valor)
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_OPERADOR_LUEGO_DE_PARA;
|
|
|
|
|
m_err_pos = m_pos - 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Continuamos el parseo agregando al valor actual
|
|
|
|
|
// pos++ para el siguiente valor seira [( or valor]
|
|
|
|
|
return ParseInternalRaw(tokens, (tokens[m_pos++].type >> AST_LOGIC_EXTRA_TYPE_START_BIT), val, type);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2026-05-14 16:54:23 -05:00
|
|
|
if(tkn_type != AST_TOKEN_MATH_T_VALUE_NUMBER)
|
2026-05-13 16:28:02 -05:00
|
|
|
{
|
2026-05-14 16:54:23 -05:00
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_VALOR;
|
|
|
|
|
m_err_pos = m_pos; // previa a para
|
2026-05-13 16:28:02 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const int pos_val_2 = m_pos++; // Valores [Raw | Variable | Funcion Build-in | Funcion Custom]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Operador 2... este es opcional en caso exista haremos recursion
|
|
|
|
|
// 1. Ero comprobaremos si hay espacio para el token actual
|
|
|
|
|
// neceistamos dos tokens
|
|
|
|
|
// [op][val] (Dado que si hay un op si o si tinee uqe haber un val o parentesis)
|
|
|
|
|
bool is_closed = false;
|
|
|
|
|
if(m_pos + 1 >= m_size || (is_closed = ((tokens[m_pos].type & 0xFFFF) == AST_TOKEN_MATH_T_VALUE_OPERDOR_PARA_END)))
|
|
|
|
|
{
|
|
|
|
|
// if(is_closed)
|
|
|
|
|
// m_para_stack--;
|
|
|
|
|
// No hay espacio, solo tenemos V X V
|
|
|
|
|
// Ahora la idea aqui seria calcular el resultado
|
|
|
|
|
return RawOpAply(tokens, math_op, pos_val_2, val, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Extraemos op2
|
|
|
|
|
tkn_type = tokens[m_pos].type & 0xFFFF;
|
|
|
|
|
if(tkn_type != AST_TOKEN_MATH_T_VALUE_OPERDOR_MATEMATICO)
|
|
|
|
|
{
|
|
|
|
|
// Luego de un valor siempre debe de haber un operador matematico
|
|
|
|
|
m_last_err = MATH_EVAL_EXP_ERR_PARSE_SE_ESPERABA_UN_OPERADOR_MATEMATICO;
|
|
|
|
|
m_err_pos = m_pos;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const int type_op_2 = tokens[m_pos++].type >> AST_LOGIC_EXTRA_TYPE_START_BIT;
|
|
|
|
|
// m_pos = apunta ahora mismo al siguiente valor o () o ~
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- En caso haya otro operador +\* etc..
|
|
|
|
|
// La idea sera ver cual es mas improtante el op1 uno actual?¿ o el otro
|
|
|
|
|
if(type_op_2 > math_op)
|
|
|
|
|
{
|
|
|
|
|
// El operador siguiente 2 es mas impornate que el actual... enotnces lo que haremos
|
|
|
|
|
// Sera reducir primermente nuestor puntero de lectura para que apunte al valor 2
|
|
|
|
|
// m_pos -= 2; // 2 espacios [Valor2][Op2][AHORA MISMO APUNTAMOS AQUI]
|
|
|
|
|
// Luego
|
|
|
|
|
BitInterpreter bit;
|
|
|
|
|
int bit_type = tokens[pos_val_2].type >> AST_LOGIC_EXTRA_TYPE_START_BIT;
|
|
|
|
|
if(bit_type == AST_LOGIC_NUMBER_INTEGER)
|
|
|
|
|
{
|
|
|
|
|
bit.long_value = tokens[pos_val_2].v.long_value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bit.double_value = tokens[pos_val_2].v.double_value;
|
|
|
|
|
}
|
|
|
|
|
if(!ParseInternalRaw(tokens, type_op_2, bit, bit_type))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Junsta ambos bits y reotrn true
|
|
|
|
|
return RawOpSobreBits(tokens, math_op, val, type, bit, bit_type);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//--- Revisamos si aun hay tokens
|
|
|
|
|
if(!RawOpAply(tokens, math_op, pos_val_2, val, type))
|
|
|
|
|
{
|
|
|
|
|
// No hay espacio, solo tenemos V X V
|
|
|
|
|
// Ahora la idea aqui seria calcular el resultado
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return ParseInternalRaw(tokens, type_op_2, val, type); // Continuamos
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#endif // EXPRESSEVALBYLEO_SRC_MATHEVAL_STATIC_AST_MQH
|