XPlor/libs/dsl/ast.h
njohnson c45d5cba86 Add XScript language features and DslKeys abstraction
- Add inline, array, const, and match statement syntax
- Add true/false keywords and deflate() decompression function
- Introduce DslKeys enum for internal metadata key management
- Improve parse_here delegation pattern with variable merging
- Remove deprecated bracket attribute syntax (use ui() instead)
- Enhance script type editor with additional functionality
- Remove obsolete install.cmd

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 12:08:26 -05:00

169 lines
4.0 KiB
C++

#ifndef AST_H
#define AST_H
#include <QString>
#include <QVector>
#include <QVariant>
#include <QHash>
#include <QPair>
#include <variant>
enum class ByteOrder { LE, BE };
enum class ScalarType { U8, I8, U16, I16, U32, I32, U64, I64, F32, F64, Bool};
struct Expr;
using ExprPtr = QSharedPointer<Expr>;
struct Stmt;
using StmtPtr = QSharedPointer<Stmt>;
struct UiFlags {
bool ui = false;
bool readOnly = false;
bool hidden = false;
QString display;
QString tableTitle;
QString columnsCsv;
QHash<QString, QString> formats;
bool visible() const { return ui && !hidden; }
bool isTable() const { return !tableTitle.isEmpty(); }
};
struct Expr {
struct Int { qint64 v; };
struct String { QString v; };
struct Var { QString name; };
struct Unary {
QString op;
ExprPtr rhs;
};
struct Binary {
QString op;
ExprPtr lhs;
ExprPtr rhs;
};
// call like read(x), pos(), size()
struct Call {
QString fn;
QVector<ExprPtr> args;
};
// member access: object.field
struct Member {
ExprPtr object;
QString field;
};
// pipeline: base | stage | stage
// stage is represented as Call(fn,args) but comes from "identifier" or "parse TypeName"
struct Pipe {
ExprPtr base;
QVector<Call> stages;
};
using Node = std::variant<Int, String, Var, Unary, Binary, Call, Member, Pipe>;
Node node;
int line = 1;
int col = 1;
};
struct Stmt {
struct ReadScalar { ScalarType type; QString name; UiFlags ui; };
struct Skip { ExprPtr count; };
struct Align { ExprPtr n; };
struct Seek { ExprPtr pos; };
struct Assign { QString name; ExprPtr value; UiFlags ui; };
struct If {
ExprPtr cond;
QVector<StmtPtr> thenBody;
QVector<StmtPtr> elseBody;
};
struct While {
ExprPtr cond;
QVector<StmtPtr> body;
};
struct Repeat {
ExprPtr count;
QVector<StmtPtr> body;
};
// for i in 0..count { ... } (range is [start, end))
struct ForRange {
QString var;
ExprPtr start;
ExprPtr end;
QVector<StmtPtr> body;
};
struct Require { ExprPtr cond; };
struct SetByteOrder { ByteOrder order; };
struct CallStmt { ExprPtr call; }; // Function call as statement (result discarded)
struct Break {}; // break from while loop
// inline cstring name @ name_ptr;
// inline typename name @ ptr_field [ui="Display", set_name];
struct Inline {
QString typeName; // "cstring", "material", etc.
QString varName; // variable to store result
QString ptrField; // pointer field to check (== -1 means inline)
UiFlags ui;
bool setName = false; // call set_name() with result
};
// array[count] items: typename @ ptr;
struct ArrayDecl {
ExprPtr count;
QString varName;
QString elementType;
QString ptrField; // optional - if present, only parse when ptr == -1
UiFlags ui;
};
// const NAME = value;
struct Const {
QString name;
ExprPtr value;
};
// match(expr) { pattern => result, ... }
struct Match {
ExprPtr expr;
QVector<QPair<QVector<ExprPtr>, QVector<StmtPtr>>> arms; // patterns -> body
QVector<StmtPtr> defaultBody;
};
using Node = std::variant<ReadScalar, Skip, Align, Seek, Assign, If, While, Repeat, ForRange, Require, SetByteOrder, CallStmt, Break, Inline, ArrayDecl, Const, Match>;
Node node;
int line = 1;
int col = 1;
};
struct TypeDef {
QString name;
QString display;
ByteOrder order = ByteOrder::LE;
bool hasExplicitByteOrder = false;
bool isRoot = false;
QVector<StmtPtr> criteria;
QVector<StmtPtr> body;
};
struct Module {
QHash<QString, TypeDef> types;
QVariantMap globals; // Global variables shared across all parse contexts
};
#endif // AST_H