Files
dl_old/dl/script/dl_script.h
T
2026-07-02 03:11:28 +08:00

544 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file dl_script.h
* @brief dl脚本语言
*
*
* @version 1.0
* @author lveyou
* @date 24-05-30
*
* @note 尽量不依赖dl的其他文件
*/
#pragma once
#include <vector>
#include <list>
#include <unordered_map>
#include <functional>
#include <string>
#include <cassert>
#include <stack>
#include <variant>
#include <array>
#include <cstdint>
namespace dl
{
using ScriptIndex = uint32_t;
using ScriptInt = int64_t;
using ScriptFloat = double;
using ScriptString = std::string;
using ScriptIndexVS = uint8_t; // 变量空间下标
struct ScriptVar;
class ScriptVM;
using ScriptVector = std::vector<ScriptVar>;
using ScriptTable = std::unordered_map<std::string, ScriptVar>;
using ScriptParam = ScriptVector;
using ScriptFunction = std::function<int(ScriptVM&, const ScriptParam&)>;
constexpr ScriptIndex SCRIPT_INDEX_RETURN = (ScriptIndex)-1; // 返回值
constexpr ScriptIndexVS SCRIPT_INDEX_VS_0 = 0; // 全局空间
constexpr ScriptIndexVS SCRIPT_INDEX_VS_ITERAL = (ScriptIndexVS)-3; // 字面量
constexpr ScriptIndexVS SCRIPT_INDEX_VS_TEMP = (ScriptIndexVS)-2; // 临时变量
constexpr ScriptIndexVS SCRIPT_INDEX_VS_ERROR = (ScriptIndexVS)-1; // 初始变量
//! 变量类型(用户层面)
enum class ScriptVarType : ScriptIndex
{
E_null, // 空
E_int, // 整数
E_float, // 浮点
E_string, // 字符串
E_class, // 类
E_vector, // 数组
E_table, // 表
E_function, // 函数
E_userdata, // 指针
E_operator, // 操作符
E_max
};
//! 是基础类型
inline bool IsBaseType(ScriptVarType type)
{
return type == ScriptVarType::E_null
|| type == ScriptVarType::E_int
|| type == ScriptVarType::E_float
|| type == ScriptVarType::E_userdata
|| type == ScriptVarType::E_operator;
}
//! 操作类型
enum class ScriptOperator : ScriptIndex
{
E_assign, // 赋值
E_add, //
E_sub,
E_mul,
E_div,
E_comma, // 逗号,视为 push_back
E_equal, // ==
E_error
};
std::string_view to_string(ScriptOperator op);
//! 变量(大小严格控制)
struct ScriptVar
{
friend class ScriptVarSpace;
friend bool operator==(const ScriptVar& a, const ScriptVar& b);
public:
ScriptVar()
{
_type = ScriptVarType::E_null;
_indexVarSpace = SCRIPT_INDEX_VS_ERROR;
_value = 0;
}
void FromInt(ScriptInt v)
{
assert(_indexVarSpace != SCRIPT_INDEX_VS_ITERAL);
_type = ScriptVarType::E_int;
*(ScriptInt*)&_value = *(ScriptInt*)&v;
}
void FromFloat(ScriptFloat v)
{
assert(_indexVarSpace != SCRIPT_INDEX_VS_ITERAL);
_type = ScriptVarType::E_float;
*(ScriptFloat*)&_value = *(ScriptFloat*)&v;
}
void FromOperator(ScriptOperator v)
{
assert(_indexVarSpace != SCRIPT_INDEX_VS_ITERAL);
_type = ScriptVarType::E_operator;
*(ScriptOperator*)&_value = *(ScriptOperator*)&v;
}
ScriptInt ToInt() const
{
assert(_type == ScriptVarType::E_int);
return (ScriptInt)_value;
}
ScriptFloat ToFloat() const
{
assert(_type == ScriptVarType::E_float);
return (ScriptFloat)_value;
}
ScriptOperator ToOperator() const
{
assert(_type == ScriptVarType::E_operator);
return (ScriptOperator)_value;
}
ScriptVarType GetType() const { return _type; }
std::string_view GetTypeString() const;
uint64_t GetValue() const
{
assert(IsBaseType(_type));
return _value;
}
uint64_t GetIndex() const
{
assert(!IsBaseType(_type));
return _value;
}
ScriptIndexVS GetSpaceIndex() const
{
return _indexVarSpace;
}
void SetValue(uint64_t v)
{
assert(IsBaseType(_type));
assert(_indexVarSpace != SCRIPT_INDEX_VS_ITERAL);
_value = v;
}
void SetType(ScriptVarType type)
{
assert(_type == ScriptVarType::E_null);
_type = type;
}
void _set_space_index(ScriptIndexVS index)
{
_indexVarSpace = index;
}
private:
ScriptVarType _type;
ScriptIndexVS _indexVarSpace; // 所在变量空间(基础类型需要释放,也需要标记)
uint64_t _value; // 基础类型直接存储(或变量下标)
};
inline bool operator==(const ScriptVar& a, const ScriptVar& b)
{
return a._type == b._type
&& a._indexVarSpace == b._indexVarSpace
&& a._value == b._value;
}
// 初步token(文本解析)
struct ScriptToken
{
enum Type
{
NORMAL,
STRING,
OPERATOR,// 操作符
};
ScriptToken() :
_type{ Type::NORMAL }
{}
ScriptToken(Type type, std::string_view str) :
_type{ type },
_str{ std::string{str} }
{}
Type _type;
std::string _str;
};
std::string_view to_string(ScriptToken::Type type);
//! 表达式token类型
enum class ScriptExprTokenType
{
ESET_variable, // 变量
ESET_literal, // 字面量
ESET_operator, //
};
//! 表达式token(指向真实变量)
struct ScriptExprToken
{
ScriptExprTokenType _type; // 类别
std::string _name; // 字符串内容(变量使用)
ScriptVar _value; // 值(表达式用、字面量)
std::string GetTypeString() const
{
return "expr_token";
}
};
//! 后缀表达式
struct ScriptExpr
{
std::vector<ScriptExprToken> _allToken;
size_t _lineNumber; // 行号(0开始)
std::string _strRaw;// 源代码,调试用
};
inline std::string to_string(const ScriptExpr& expr)
{
if (expr._allToken.empty())
return {};
std::string ret;
for (size_t i = 0; i < expr._allToken.size() - 1; ++i)
{
ret += expr._allToken[i]._name;
ret += ' ';
}
ret += expr._allToken[expr._allToken.size() - 1]._name;
return ret;
}
//! 变量空间
class ScriptVarSpace
{
public:
ScriptVarSpace(ScriptIndexVS index, size_t level) :
_index{ index },
_level{ level }
{}
ScriptIndexVS GetIndex() const { return _index; }
size_t GetLevel() const { return _level; }
ScriptVar AddString(std::string_view v)
{
ScriptVar ret;
ret._type = ScriptVarType::E_string;
ret._indexVarSpace = _index;
ret._value = _vecString.size();
_vecString.push_back(std::string{ v });
return ret;
}
ScriptVar AddFunction(ScriptFunction v)
{
ScriptVar ret;
ret._type = ScriptVarType::E_function;
ret._indexVarSpace = _index;
ret._value = _vecFunction.size();
_vecFunction.push_back(v);
return ret;
}
ScriptVar AddVector()
{
ScriptVar ret;
ret._type = ScriptVarType::E_vector;
ret._indexVarSpace = _index;
ret._value = _vecVector.size();
_vecVector.push_back({});
return ret;
}
void SetString(size_t i, const ScriptString& str)
{
_vecString[i] = str;
}
void SetVector(size_t i, const ScriptVector& vec)
{
_vecVector[i] = vec;
}
const ScriptString& GetString(size_t i) const
{
return _vecString[i];
}
const ScriptFunction& GetFunction(size_t i) const
{
return _vecFunction[i];
}
ScriptVector& GetVetorRef(size_t i)
{
return _vecVector[i];
}
private:
ScriptIndexVS _index; // 自己下标 0全局变量
size_t _level;
std::vector<ScriptString> _vecString;
std::vector<ScriptTable> _vecClass;
std::vector<ScriptVector> _vecVector;
std::vector<ScriptTable> _vecTable;
std::vector<ScriptFunction> _vecFunction;
std::vector<ScriptExpr> _vecExpr;
};
enum class ScriptSegmentType : ScriptIndex
{
E_expr,
E_if,
E_ifelse,
E_else,
E_while,
E_for,
E_vector,
E_table,
};
//! 代码段(包含单独作用域)
struct ScriptSegment
{
ScriptSegmentType _type;
size_t _level; // 层级(作用域)
std::vector<ScriptExpr> _allExpr;
};
//! 代码块
struct ScriptBlock
{
ScriptBlock() :
_varSpaceIteral{ SCRIPT_INDEX_VS_ITERAL, 0 }
{}
std::vector<ScriptSegment> _allSeg;
// 字面量是编译器固定的,不可修改,全局可见,所以单独处理
ScriptVarSpace _varSpaceIteral;
std::vector<std::string> _vecSource;// 不包含换行
std::string GetSource(bool line_number = true, bool header = true, bool footer = true) const;
};
//! 控制语句
struct ScriptControlIf
{
ScriptExpr _cond;
ScriptSegment _seg;
};
struct ScriptControlIfElse
{
ScriptExpr _cond;
ScriptSegment _seg;
};
struct ScriptControlElse
{
ScriptExpr _cond;
ScriptSegment _seg;
};
struct ScriptControlFor
{
std::array<ScriptExpr, 3> _cond;
ScriptSegment _seg;
};
struct ScriptControlWhile
{
ScriptExpr _cond;
ScriptSegment _seg;
};
//! 代码段运行时
struct ScriptSegmentRT
{
//std::
};
//! 虚拟机
class ScriptVM
{
friend class ScriptSystem;
public:
void Execute(const ScriptBlock& block);
// 变量转字符串
std::string Variable2String(const ScriptVar& var);
// 变量转bool
bool Variable2Bool(const ScriptVar& var);
// 中断执行(内部调用)
void Throw() { _bThrow = true; }
ScriptVM();
private:
// 当前执行代码块
const ScriptBlock* _block;
// 名字 -> 变量(变量)
std::unordered_map<std::string, ScriptVar> _allVar;
// 全局变量空间
ScriptVarSpace _varSpaceGlobal;
// 变量空间
std::vector<ScriptVarSpace*> _allVarSpace;
// 函数参数
ScriptParam _param;
//-------------------------------expr------------------------------
// 返回值(可变)
ScriptExprToken _return;
// 操作堆栈
std::vector<ScriptIndex> _stackVar;
// 当前表达式
const ScriptExpr* _expr;
// 临时变量空间
ScriptVarSpace _varSpaceTemp; //todo清理
// 出现异常
bool _bThrow;
void _exec_expr(const ScriptExpr& expr);
void _clear_expr();
// 从 操作堆栈 访问
const ScriptExprToken& _get_stack_expr_token(size_t i);
const ScriptExprToken& _get_stack_expr_token_top(size_t i);
ScriptVar& _get_stack_var(size_t i);
ScriptVar& _get_stack_var_top(size_t i);
void _stack_pop(size_t i);
void _op_arithmetic(ScriptOperator op);
void _op_assign();
void _op_comma();
void _op_equal();
// 获取(新建)变量,新建则在当前变量空间初始化
ScriptVar& _get_variable(const ScriptExprToken& var0);
// 移除变量空间后,从变量表中移除
void _delete_var_space(ScriptVarSpace* vs);
// 返回变量所在空间
ScriptVarSpace* GetVariableSpaceRef(ScriptIndexVS index);
const ScriptVarSpace* GetVariableSpace(ScriptIndexVS index);
ScriptVarSpace* GetVariableSpaceRef(ScriptVar var)
{
return GetVariableSpaceRef(var.GetSpaceIndex());
}
const ScriptVarSpace* GetVariableSpace(ScriptVar var)
{
return GetVariableSpace(var.GetSpaceIndex());
}
//------------------------------------变量创建(默认值)--------------
ScriptVar AddVariable(ScriptIndexVS index, ScriptVarType type);
//------------------------------------变量获取(必须已存在)--------------
ScriptFunction GetVariableFunction(ScriptVar var);
ScriptString GetVariableString(ScriptVar var);
ScriptVector& GetVariableVector(ScriptVar var);
//------------------------------------变量设置(必须已存在)--------------
void SetVariableString(ScriptVar var, ScriptString str);
void SetVariableVector(ScriptVar var, const ScriptVector& vec);
};
//! 管理器
class ScriptSystem
{
public:
ScriptBlock Compile(std::string_view src);
// 中缀 -> 后缀(逆波兰表达式)
std::vector<ScriptExprToken> ConvertMid(const std::vector<ScriptExprToken>& vec);
//! 预处理代码(行号不变)
std::string Preprocess(std::string_view src);
void PreprocessLineNumber(ScriptBlock& block, std::string_view src);
//! 是否操作符
bool IsOperator(std::string_view str);
//! 是否可能为操作符内容(变量名不可能出现)
bool IsMaybeOperator(char ch);
//! 返回操作符优先级,越大越优先
int GetOperatorPriority(std::string_view str);
//! 是否关键字
bool IsKeyword(std::string_view str);
//! 是否变量名
bool IsVariable(std::string_view str);
//! 是否全局变量名
bool IsGlobalVariable(std::string_view str);
//! 返回token类型
ScriptExprTokenType GetTokenType(std::string_view str);
//! 生成表达式token(字面量是编译器信息,需要生成到block)
ScriptExprToken MakeExprToken(ScriptBlock& block, const ScriptToken& token);
//! 生成字面量
ScriptVar MakeLiteral(ScriptBlock& block, const ScriptToken& token);
//! 注册函数
void RegisterFunction(std::string_view name, ScriptFunction func)
{
ScriptVar var = _varSpaceGlobal.AddFunction(func);
_allVar[std::string{ name }] = var;
}
void CopyVariableToVm(ScriptVM& vm)
{
vm._allVar = _allVar;
vm._varSpaceGlobal = _varSpaceGlobal;
}
bool CheckToken(ScriptExprTokenType type);
//! 字符串转操作符变量
ScriptOperator String2Operator(std::string_view str);
//------------------------------------基础运算(不考虑变量)-----------------------
ScriptVar OpArithmetic(ScriptVM& vm, ScriptOperator op, const ScriptVar& v0, const ScriptVar& v1);
void OpAssign(ScriptVM& vm, ScriptVar& v0, const ScriptVar& v1);
ScriptSystem();
private:
// 关键字
std::unordered_map<std::string_view, int> _allKeyword;
// 操作符、优先级(越大越优先)
std::unordered_map<std::string_view, int> _allOperator;
// 变量空间池
std::list<ScriptVarSpace*> _listVarSpaceFree;
// 内置变量(例print)
std::unordered_map<std::string, ScriptVar> _allVar;
// 内置变量空间(全局)
ScriptVarSpace _varSpaceGlobal;
};
extern ScriptSystem* g_script;
}