BasesParserSLan/Src/Query/Parser.mqh

585 lines
17 KiB
MQL5
Raw Permalink Normal View History

2026-07-23 22:03:03 -05:00
//+------------------------------------------------------------------+
2026-07-20 22:44:15 -05:00
//| Parser.mqh |
2026-07-22 16:22:12 -05:00
//| Copyright 2026, Niquel Mendoza. |
2026-07-20 22:44:15 -05:00
//| https://www.mql5.com |
//+------------------------------------------------------------------+
2026-07-22 16:22:12 -05:00
#property copyright "Copyright 2026, Niquel Mendoza."
2026-07-20 22:44:15 -05:00
#property link "https://www.mql5.com"
#property strict
2026-07-23 08:39:26 -05:00
#ifndef BASESPARSERSLAN_SRC_QUERY_PARSER_MQH
#define BASESPARSERSLAN_SRC_QUERY_PARSER_MQH
2026-07-20 22:44:15 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-07-23 08:39:26 -05:00
#include "AsmDef.mqh"
2026-07-20 22:44:15 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-07-21 08:53:15 -05:00
namespace TSN
{
2026-07-22 15:26:43 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CSLDomQueryCompiler;
2026-07-23 22:12:19 -05:00
class CSLDomQueryVm;
2026-07-24 14:20:05 -05:00
2026-07-22 15:26:43 -05:00
//---
2026-07-24 14:20:05 -05:00
typedef void(*CSLQueryFunc)(CSLDomQueryVm*);
2026-07-22 15:26:43 -05:00
2026-07-20 22:44:15 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CSLDomQueryCompiler
{
public:
2026-07-23 08:39:26 -05:00
//--- Raw
2026-07-20 22:44:15 -05:00
uchar m_raw[];
int m_pos;
int m_len;
2026-07-23 08:39:26 -05:00
int m_offset;
2026-07-20 22:44:15 -05:00
2026-07-22 15:26:43 -05:00
//--- Registros (mitad mitad)
2026-07-23 22:03:03 -05:00
string m_sreg[TSN_DOMPATH_MAX_SIZE_STR];
2026-07-22 15:26:43 -05:00
int m_sreg_s;
2026-07-23 22:03:03 -05:00
DomPathV m_reg[TSN_DOMPATH_MAX_SIZE_REG];
2026-07-22 15:26:43 -05:00
int m_reg_s;
2026-07-22 20:08:38 -05:00
2026-07-22 15:26:43 -05:00
protected:
2026-07-23 08:39:26 -05:00
//--- Bytecode
long m_bytecode[];
int m_bytecode_s;
int m_bytecode_r;
2026-07-23 22:12:19 -05:00
//---
int m_locked_sreg;
2026-07-23 08:39:26 -05:00
//--- Funciones
CSLQueryFunc m_funcs[128];
int m_funcs_size;
2026-07-23 22:03:03 -05:00
//--- Crea un string
int MakeString(int i, const int l);
2026-07-23 08:39:26 -05:00
2026-07-22 15:26:43 -05:00
//--- Hashmap intermdio para
// que el usuiario guardde sus funciones con un keyu.. y luego se consutla con ese key..
// (bueno con hash)
2026-07-23 22:03:03 -05:00
CHashMapFast(string, int) m_hash_func;
2026-07-20 22:44:15 -05:00
2026-07-22 15:26:43 -05:00
//--- Del parseo en si
2026-07-23 22:03:03 -05:00
// HashMap para mapear los jump
2026-07-23 08:39:26 -05:00
CHashMapFast(ulong, int) m_hash_jumps;
struct pack(8) PendintHashJump
{
ulong hash; // hash
int bytecode_pos; // Indice del bytecode
long mask; // mascara a aplicar al valor
2026-07-23 15:58:21 -05:00
int bit_start_mask;
};
PendintHashJump m_pendings_hashes[];
int m_pendings_hashes_s;
int m_pendings_hashes_r;
2026-07-23 08:39:26 -05:00
2026-07-24 14:20:05 -05:00
// Pila de valores tokenizacoin
2026-07-23 08:39:26 -05:00
long m_pila_v[ASMPARSER_MAX_VAL_OPS];
uchar m_pila_v_t[ASMPARSER_MAX_VAL_OPS];
int m_pila_v_s; // tamaño actual usado de pila
2026-07-24 14:20:05 -05:00
// Siguiente token tokenizacion
2026-07-23 08:39:26 -05:00
uint m_pila_ins[ASMPARSER_MAX_VAL_OPS];
int m_pila_ins_t;
int m_pila_curr; // curr instruction pila
2026-07-22 20:08:38 -05:00
2026-07-23 08:39:26 -05:00
//
2026-07-24 14:20:05 -05:00
uchar m_next; // sigueinte token
uint m_p_f; // flags del token
2026-07-20 22:44:15 -05:00
2026-07-23 08:39:26 -05:00
//---
ENUM_ASM_DOMPATH_PARSER_ERR m_last_err_parse;
2026-07-22 20:08:38 -05:00
2026-07-20 22:44:15 -05:00
public:
2026-07-23 22:03:03 -05:00
CSLDomQueryCompiler(void);
2026-07-20 22:44:15 -05:00
~CSLDomQueryCompiler(void) {}
2026-07-23 22:03:03 -05:00
//--- Correct padding
void CorrectPadding();
//--- Load
__forceinline void CalcLen() { m_len = ArraySize(m_raw); }
inline void Assing(const string& raw);
int AssingFile(const string& file_name, const bool comon_flag);
bool AutoParseFileByExt(const int reg_type);
2026-07-24 14:20:05 -05:00
//--- Lockear vlaores previo a los Run
2026-07-23 22:12:19 -05:00
void LockValues();
2026-07-23 22:03:03 -05:00
//--- Save
bool SaveCompiled(const string & file_name_out, const bool out_common_flag) const;
//--- Normalize
void NormalizeUft();
//--- Errores
void GetLastErrorLocation(int &col, int &line) const;
__forceinline ENUM_ASM_DOMPATH_PARSER_ERR LastErr() const { return m_last_err_parse; }
//--- Funciones
void SetFunction(const string &func_name, CSLQueryFunc func);
//--- Compiladores finales
2026-07-22 15:26:43 -05:00
bool CompileAsm();
2026-07-23 22:03:03 -05:00
bool CompileQuery() { return true; } // place holder
2026-07-24 14:20:05 -05:00
//---
void Summary();
__forceinline int GetStepIns(const ENUM_DOMPATH_QUERY_INS_TYPE t) const;
//---
void ParseErrorInfo(bool w_avanze = false) const;
2026-07-20 22:44:15 -05:00
};
2026-07-23 22:03:03 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CSLDomQueryCompiler::CSLDomQueryCompiler()
: m_bytecode_r(256), m_bytecode_s(0), m_pendings_hashes_s(0), m_pendings_hashes_r(16)
, m_funcs_size(0), m_sreg_s(0), m_reg_s(0), m_hash_func(64), m_hash_jumps(64)
{
ArrayResize(m_bytecode, m_bytecode_r, m_bytecode_r);
ArrayResize(m_pendings_hashes, m_pendings_hashes_r, m_pendings_hashes_r);
}
2026-07-24 14:20:05 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CSLDomQueryCompiler::Summary(void)
{
Print("---- CSLDomQueryCompiler ----");
Print("-- Bytecode --");
int cur = 0;
while(cur < m_bytecode_s)
{
const ENUM_DOMPATH_QUERY_INS_TYPE t = ENUM_DOMPATH_QUERY_INS_TYPE(m_bytecode[cur] & TSN_DOMPATH_MASK_INS_TYPE);
PrintFormat("[%d] %s", cur, EnumToString(t));
cur += GetStepIns(t);
}
Print("-- Registers --");
Print("Registers str size: ", m_sreg_s);
Print("Functions size: ", m_funcs_size);
2026-07-24 21:56:07 -05:00
Print("---- end ----");
2026-07-24 14:20:05 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
__forceinline int CSLDomQueryCompiler::GetStepIns(const ENUM_DOMPATH_QUERY_INS_TYPE t) const
{
switch(t)
{
//---
case DOMPATH_QUERY_INS_TYPE_ACCESO_KEY:
case DOMPATH_QUERY_INS_TYPE_ACCESO_KEY_F:
return 2;
//---
case DOMPATH_QUERY_INS_TYPE_ACCESO_IDX:
case DOMPATH_QUERY_INS_TYPE_ACCESO_IDX_F:
case DOMPATH_QUERY_INS_TYPE_INICIAR_ITERACION:
case DOMPATH_QUERY_INS_TYPE_ITER_ASSING:
return 1;
//---
case DOMPATH_QUERY_INS_TYPE_EXIST:
return 2;
//---
case DOMPATH_QUERY_INS_TYPE_SAVE:
case DOMPATH_QUERY_INS_TYPE_SAVE_NO_RESET:
return 1;
//---
case DOMPATH_QUERY_INS_TYPE_M_MUL:
case DOMPATH_QUERY_INS_TYPE_M_RES:
case DOMPATH_QUERY_INS_TYPE_M_DIV:
case DOMPATH_QUERY_INS_TYPE_M_SUM:
case DOMPATH_QUERY_INS_TYPE_M_MOD:
case DOMPATH_QUERY_INS_TYPE_M_BIT_OR:
case DOMPATH_QUERY_INS_TYPE_M_BIT_AND:
case DOMPATH_QUERY_INS_TYPE_M_BIT_XOR:
case DOMPATH_QUERY_INS_TYPE_M_BIT_DEZ_IZQ:
case DOMPATH_QUERY_INS_TYPE_M_BIT_DEZ_DRC:
case DOMPATH_QUERY_INS_TYPE_M_BIT_NOT:
case DOMPATH_QUERY_INS_TYPE_M_UNARY_NOT:
case DOMPATH_QUERY_INS_TYPE_COMPARE_EQ:
case DOMPATH_QUERY_INS_TYPE_COMPARE_MENOR:
case DOMPATH_QUERY_INS_TYPE_COMPARE_MENOR_EQ:
case DOMPATH_QUERY_INS_TYPE_COMPARE_IS:
case DOMPATH_QUERY_INS_TYPE_CALL:
return 2;
case DOMPATH_QUERY_INS_TYPE_RESERVE:
return 1;
case DOMPATH_QUERY_INS_TYPE_SLICING:
return 2;
case DOMPATH_QUERY_INS_TYPE_JUMP:
case DOMPATH_QUERY_INS_TYPE_COPY_ALL:
case DOMPATH_QUERY_INS_TYPE_APPEND:
case DOMPATH_QUERY_INS_TYPE_SALIDA:
return 1;
default:
return 1;
}
}
2026-07-23 22:03:03 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-07-23 22:12:19 -05:00
void CSLDomQueryCompiler::LockValues()
{
2026-07-24 14:20:05 -05:00
// Luego de compilar llamar a esta funcion
2026-07-23 22:12:19 -05:00
m_locked_sreg = m_sreg_s;
}
2026-07-24 22:33:42 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CSLDomQueryCompiler::AutoParseFileByExt(const int reg_type)
{
switch(reg_type)
{
case TSN_DOMPATH_REGTYPE_JSONPB:
{
return m_bytecode_s > 0; // solo chekeamos si el bytecode cargado es mayor a 0
}
case TSN_DOMPATH_REGTYPE_JSONPASM:
{
CorrectPadding();
return CompileAsm();
}
default:
{
m_last_err_parse = ASM_DOMPATH_PARSER_ERR_INVALID_FILE_EXTENSION;
m_pos = 0;
return false;;
}
}
}
2026-07-23 22:12:19 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-07-23 22:03:03 -05:00
int CSLDomQueryCompiler::AssingFile(const string &file_name, const bool comon_flag)
{
2026-07-24 22:33:42 -05:00
const int reg_type = (int)DomPathExtBSPLF_File(file_name);
if(reg_type == TSN_DOMPATH_REGTYPE_JSONPB)
{
// cache
::ResetLastError();
const int fh = FileOpen(file_name, FILE_BIN | FILE_ANSI | (comon_flag ? FILE_COMMON : 0) | FILE_READ);
if(fh == INVALID_HANDLE)
{
return -1;
}
m_bytecode_s = FileReadInteger(fh);
m_bytecode_r = m_bytecode_s;
FileReadArray(fh, m_bytecode, 0, m_bytecode_s);
m_sreg_s = FileReadInteger(fh);
for(int i = 0; i < m_sreg_s; i++)
{
const int l = FileReadInteger(fh);
m_sreg[i] = FileReadString(fh, l);
}
const int t = FileReadInteger(fh);
FileReadArray(fh, m_reg, 0, t);
//---
FileClose(fh);
//---
return TSN_DOMPATH_REGTYPE_JSONPB;
}
else
{
// asm o normal
const int l = (int)FileLoad(file_name, m_raw, (comon_flag ? FILE_COMMON : 0));
if(l == -1)
return -1;
//---
m_len = l;
//---
NormalizeUft();
//---
return reg_type;
}
2026-07-23 22:03:03 -05:00
return 0; // place holder
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CSLDomQueryCompiler::SaveCompiled(const string &file_name_out, const bool out_common_flag) const
{
2026-07-24 14:20:05 -05:00
//---
const int fh = FileOpen(file_name_out, FILE_WRITE | FILE_BIN | FILE_ANSI | (out_common_flag ? FILE_COMMON : 0));
if(fh == INVALID_HANDLE)
{
return false;
}
2026-07-23 22:03:03 -05:00
2026-07-24 14:20:05 -05:00
//---
FileWriteInteger(fh, m_bytecode_s);
FileWriteArray(fh, m_bytecode, 0, m_bytecode_s);
//---
FileWriteInteger(fh, m_sreg_s);
for(int i = 0; i < m_sreg_s; i++)
{
const int l = StringLen(m_sreg[i]);
FileWriteInteger(fh, l);
FileWriteString(fh, m_sreg[i], l);
}
//---
static const int t = TSN_DOMPATH_MAX_SIZE_REG >> 1;
FileWriteInteger(fh, t);
FileWriteArray(fh, m_reg, 0, t);
2026-07-24 22:33:42 -05:00
//---
FileClose(fh);
2026-07-24 14:20:05 -05:00
//---
return true;
2026-07-23 22:03:03 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CSLDomQueryCompiler::SetFunction(const string &func_name, CSLQueryFunc func)
{
const int idx = m_hash_func.Find(func_name);
if(idx == -1)
{
m_funcs[m_funcs_size] = func;
m_hash_func.Add(func_name, m_funcs_size);
m_funcs_size++;
}
else
{
m_funcs[idx] = func;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
inline void CSLDomQueryCompiler::Assing(const string& raw)
{
m_len = StringToCharArray(raw, m_raw);
m_offset = 0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CSLDomQueryCompiler::CorrectPadding()
{
//---
const int prev = m_len;
ArrayResize(m_raw, (m_len += 8));
//--- Rellenamos
for(int i = prev; i < m_len; i++)
{
m_raw[i] = '\n';
}
//--- Chekeamos
if(m_len > m_bytecode_r)
{
m_bytecode_r = m_len;
ArrayResize(m_bytecode, m_len, m_len);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CSLDomQueryCompiler::NormalizeUft()
{
m_offset = 0;
//---
if(m_len >= 2)
{
// UTF16 BE
if(m_raw[0] == 0xFF && m_raw[1] == 0xFE)
{
const int n = (m_len - 2) >> 1;
for(int i = 0; i < n; i++)
m_raw[i] = m_raw[2 + (i * 2)]; // byte bajo (el char real)
m_len = ArrayResize(m_raw, n);
}
// UTF16 LE
else
if(m_raw[0] == 0xFE && m_raw[1] == 0xFF)
{
const int n = (m_len - 2) >> 1;
for(int i = 0; i < n; i++)
m_raw[i] = m_raw[3 + (i * 2)]; // byte alto (invertido)
m_len = ArrayResize(m_raw, n);
}
}
else
if(m_len >= 3 && m_raw[0] == 0xEF && m_raw[1] == 0xBB && m_raw[2] == 0xBF)
{
// UTF-8 BOM
m_offset = 3; // simplemente saltear
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CSLDomQueryCompiler::MakeString(int i, const int l)
{
//---
m_sreg[m_sreg_s].Truncate(l);
int k = 0;
const int e = i + l;
//---
for(; i < e; i++)
m_sreg[m_sreg_s].SetChar(k++, m_raw[i]);
//---
m_sreg_s++;
return m_sreg_s - 1;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CSLDomQueryCompiler::GetLastErrorLocation(int &col, int &line) const
{
col = 1;
line = 1;
//Print("err:");
//PrintFormat("Val = '%s'", CharArrayToString(m_raw, 0, m_pos));
for(int i = 0; i <= m_pos && i < m_len; i++)
{
if(m_raw[i] == '\n')
{
line++;
col = 1;
}
else
col++;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CSLDomQueryCompiler::ParseErrorInfo(bool w_avanze) const
{
if(m_last_err_parse == ASM_DOMPATH_PARSER_ERR_NOT)
return;
//---
int col, line;
GetLastErrorLocation(col, line);
string err = "";
//---
switch(m_last_err_parse)
{
case ASM_DOMPATH_PARSER_ERR_MALFORMERD_ASM:
err = "ASM mal formado: se encontro un token que no era valido en este punto";
break;
case ASM_DOMPATH_PARSER_ERR_INVALID_INSTRUCTION:
err = "Instruccion invalida: el nombre de instruccion (INS_*) no existe";
break;
case ASM_DOMPATH_PARSER_ERR_INVALID_TOKEN:
err = "Token invalido: caracter inesperado, no coincide con ningun token conocido";
break;
case ASM_DOMPATH_PARSER_ERR_JUMP_NOT_CLOSED:
err = "Etiqueta de salto (@Alias:) sin cerrar antes del final del archivo";
break;
case ASM_DOMPATH_PARSER_ERR_INVALID_CASE_INS:
err = "Instruccion reconocida pero sin manejo implementado en el compilador (case invalido)";
break;
case ASM_DOMPATH_PARSER_ERR_STRING_NOT_CLOSED:
err = "Cadena (string) sin comilla de cierre antes del final del archivo";
break;
case ASM_DOMPATH_PARSER_ERR_INVALID_JUMP_KEY:
err = "Salto a una etiqueta que nunca fue declarada (@Alias: inexistente)";
break;
case ASM_DOMPATH_PARSER_ERR_STR_HASH_NOT_CLOSED:
err = "Hash de salto (' o *) sin caracter de cierre antes del final del archivo";
break;
case ASM_DOMPATH_PARSER_ERR_MALFORMERD_ASM_CTX_GEN:
err = "ASM mal formado dentro del contexto de generacion (secuencia de tokens invalida para esta instruccion)";
break;
case ASM_DOMPATH_PARSER_ERR_FUNCTION_NOT_EXIST:
err = "La funcion invocada (CALL) no fue registrada previamente con SetFunction";
break;
case ASM_DOMPATH_PARSER_ERR_COMENTARIO_NO_CERRO_Y_AUN_QUEDA_ALGO:
err = "El comentario no cerro correctamente y aun quedaba contenido pendiente de parsear";
break;
2026-07-24 22:33:42 -05:00
case ASM_DOMPATH_PARSER_ERR_INVALID_FILE_EXTENSION:
err = "Tipo de extension de archivo invalida";
break;
default:
err = "Error desconocido";
break;
}
//---
PrintFormat("[DomPath ASM] Error (linea %d, columna %d):\n'%s'", line, col, err);
//---
if(w_avanze)
{
Print("Avanze: ");
Print("--------");
Print(CharArrayToString(m_raw, 0, m_pos));
Print("--------");
}
}
2026-07-20 22:44:15 -05:00
}
//+------------------------------------------------------------------+
2026-07-23 08:39:26 -05:00
#endif // BASESPARSERSLAN_SRC_QUERY_PARSER_MQH
//+------------------------------------------------------------------+