xdl_parser/
ast.rs

1//! XDL Abstract Syntax Tree definitions
2
3use xdl_core::XdlValue;
4/// Source location information
5#[derive(Debug, Clone, PartialEq)]
6pub struct Location {
7    pub line: usize,
8    pub column: usize,
9    pub filename: Option<String>,
10}
11
12/// XDL Program (top-level AST node)
13#[derive(Debug, Clone, PartialEq)]
14pub struct Program {
15    pub statements: Vec<Statement>,
16    pub location: Location,
17}
18
19/// XDL Statements
20#[derive(Debug, Clone, PartialEq)]
21pub enum Statement {
22    Assignment {
23        target: Expression,
24        value: Expression,
25        location: Location,
26    },
27    Expression {
28        expr: Expression,
29        location: Location,
30    },
31    If {
32        condition: Expression,
33        then_block: Vec<Statement>,
34        else_block: Option<Vec<Statement>>,
35        location: Location,
36    },
37    For {
38        variable: String,
39        start: Expression,
40        end: Expression,
41        step: Option<Expression>,
42        body: Vec<Statement>,
43        location: Location,
44    },
45    Foreach {
46        variable: String,
47        iterable: Expression,
48        index_var: Option<String>,
49        body: Vec<Statement>,
50        location: Location,
51    },
52    While {
53        condition: Expression,
54        body: Vec<Statement>,
55        location: Location,
56    },
57    Repeat {
58        body: Vec<Statement>,
59        condition: Expression,
60        location: Location,
61    },
62    Break {
63        location: Location,
64    },
65    Continue {
66        location: Location,
67    },
68    Return {
69        value: Option<Expression>,
70        location: Location,
71    },
72    ProcedureCall {
73        name: String,
74        args: Vec<Expression>,
75        keywords: Vec<Keyword>,
76        location: Location,
77    },
78    Common {
79        name: String,
80        variables: Vec<String>,
81        location: Location,
82    },
83    CompileOpt {
84        options: Vec<String>,
85        location: Location,
86    },
87    FunctionDef {
88        name: String,
89        params: Vec<Parameter>,
90        keywords: Vec<KeywordDecl>,
91        body: Vec<Statement>,
92        location: Location,
93    },
94    ProcedureDef {
95        name: String,
96        params: Vec<Parameter>,
97        keywords: Vec<KeywordDecl>,
98        body: Vec<Statement>,
99        location: Location,
100    },
101    Label {
102        name: String,
103        location: Location,
104    },
105    Goto {
106        label: String,
107        location: Location,
108    },
109    Case {
110        expr: Expression,
111        branches: Vec<CaseBranch>,
112        else_block: Option<Vec<Statement>>,
113        location: Location,
114    },
115    Switch {
116        expr: Expression,
117        branches: Vec<CaseBranch>,
118        else_block: Option<Vec<Statement>>,
119        location: Location,
120    },
121    // Object-oriented programming
122    ClassDefinition {
123        name: String,
124        body: Vec<Statement>,
125        location: Location,
126    },
127    MethodDefinition {
128        class_name: String,
129        method_name: String,
130        is_function: bool, // true for FUNCTION, false for PRO
131        params: Vec<Parameter>,
132        keywords: Vec<KeywordDecl>,
133        body: Vec<Statement>,
134        location: Location,
135    },
136    ObjectDestroy {
137        objects: Vec<Expression>,
138        location: Location,
139    },
140}
141
142/// XDL Expressions
143#[derive(Debug, Clone, PartialEq)]
144pub enum Expression {
145    Literal {
146        value: XdlValue,
147        location: Location,
148    },
149    Variable {
150        name: String,
151        location: Location,
152    },
153    SystemVariable {
154        name: String,
155        location: Location,
156    },
157    ArrayRef {
158        array: Box<Expression>,
159        indices: Vec<ArrayIndex>,
160        location: Location,
161    },
162    StructRef {
163        object: Box<Expression>,
164        field: String,
165        location: Location,
166    },
167    MethodCall {
168        object: Box<Expression>,
169        method: String,
170        args: Vec<Expression>,
171        keywords: Vec<Keyword>,
172        location: Location,
173    },
174    FunctionCall {
175        name: String,
176        args: Vec<Expression>,
177        keywords: Vec<Keyword>,
178        location: Location,
179    },
180    Binary {
181        op: BinaryOp,
182        left: Box<Expression>,
183        right: Box<Expression>,
184        location: Location,
185    },
186    Unary {
187        op: UnaryOp,
188        expr: Box<Expression>,
189        location: Location,
190    },
191    Ternary {
192        condition: Box<Expression>,
193        if_true: Box<Expression>,
194        if_false: Box<Expression>,
195        location: Location,
196    },
197    ArrayDef {
198        elements: Vec<Expression>,
199        location: Location,
200    },
201    StructDef {
202        name: Option<String>,
203        fields: Vec<StructField>,
204        location: Location,
205    },
206    Pointer {
207        expr: Box<Expression>,
208        location: Location,
209    },
210    Deref {
211        expr: Box<Expression>,
212        location: Location,
213    },
214    PostIncrement {
215        expr: Box<Expression>,
216        location: Location,
217    },
218    PostDecrement {
219        expr: Box<Expression>,
220        location: Location,
221    },
222    PreIncrement {
223        expr: Box<Expression>,
224        location: Location,
225    },
226    PreDecrement {
227        expr: Box<Expression>,
228        location: Location,
229    },
230    // Object-oriented programming
231    ObjectNew {
232        class_name: String,
233        args: Vec<Expression>,
234        keywords: Vec<Keyword>,
235        location: Location,
236    },
237}
238
239/// Array indexing expressions
240#[derive(Debug, Clone, PartialEq)]
241pub enum ArrayIndex {
242    Single(Box<Expression>),
243    Range {
244        start: Option<Box<Expression>>,
245        end: Option<Box<Expression>>,
246        step: Option<Box<Expression>>,
247    },
248    All, // *
249}
250
251/// Binary operators
252#[derive(Debug, Clone, Copy, PartialEq, Eq)]
253pub enum BinaryOp {
254    // Arithmetic
255    Add,
256    Subtract,
257    Multiply,
258    Divide,
259    Modulo,
260    Power,
261    MatrixMultiply,
262
263    // Logical
264    And,
265    Or,
266    Xor,
267
268    // Bitwise
269    BitwiseAnd,
270    BitwiseOr,
271    BitwiseXor,
272    LeftShift,
273    RightShift,
274
275    // Comparison
276    Equal,
277    NotEqual,
278    Less,
279    LessEqual,
280    Greater,
281    GreaterEqual,
282
283    // String
284    Concatenate,
285
286    // Assignment
287    Assign,
288    PlusAssign,
289    MinusAssign,
290    MultiplyAssign,
291    DivideAssign,
292    ModuloAssign,
293    PowerAssign,
294    AndAssign,
295    OrAssign,
296    XorAssign,
297}
298
299/// Unary operators
300#[derive(Debug, Clone, Copy, PartialEq, Eq)]
301pub enum UnaryOp {
302    Plus,
303    Minus,
304    Not,
305    BitwiseNot,
306}
307
308/// Function/procedure parameters
309#[derive(Debug, Clone, PartialEq)]
310pub struct Parameter {
311    pub name: String,
312    pub by_reference: bool,
313    pub optional: bool,
314    pub location: Location,
315}
316
317/// Keyword declarations in function/procedure definitions
318#[derive(Debug, Clone, PartialEq)]
319pub struct KeywordDecl {
320    pub name: String,
321    pub by_reference: bool,
322    pub location: Location,
323}
324
325/// Keyword arguments in function/procedure calls
326#[derive(Debug, Clone, PartialEq)]
327pub struct Keyword {
328    pub name: String,
329    pub value: Option<Expression>,
330    pub location: Location,
331}
332
333/// CASE/SWITCH branch
334#[derive(Debug, Clone, PartialEq)]
335pub struct CaseBranch {
336    pub values: Vec<Expression>, // List of values to match (can be ranges or single values)
337    pub body: Vec<Statement>,
338    pub location: Location,
339}
340
341/// Structure field definition
342#[derive(Debug, Clone, PartialEq)]
343pub struct StructField {
344    pub name: String,
345    pub value: Expression,
346    pub location: Location,
347}
348
349impl Location {
350    pub fn new(line: usize, column: usize) -> Self {
351        Self {
352            line,
353            column,
354            filename: None,
355        }
356    }
357
358    pub fn with_file(line: usize, column: usize, filename: String) -> Self {
359        Self {
360            line,
361            column,
362            filename: Some(filename),
363        }
364    }
365
366    pub fn unknown() -> Self {
367        Self {
368            line: 0,
369            column: 0,
370            filename: None,
371        }
372    }
373}
374
375impl Statement {
376    /// Get the location of this statement
377    pub fn location(&self) -> &Location {
378        match self {
379            Statement::Assignment { location, .. } => location,
380            Statement::Expression { location, .. } => location,
381            Statement::If { location, .. } => location,
382            Statement::For { location, .. } => location,
383            Statement::Foreach { location, .. } => location,
384            Statement::While { location, .. } => location,
385            Statement::Repeat { location, .. } => location,
386            Statement::Break { location } => location,
387            Statement::Continue { location } => location,
388            Statement::Return { location, .. } => location,
389            Statement::ProcedureCall { location, .. } => location,
390            Statement::Common { location, .. } => location,
391            Statement::CompileOpt { location, .. } => location,
392            Statement::FunctionDef { location, .. } => location,
393            Statement::ProcedureDef { location, .. } => location,
394            Statement::Label { location, .. } => location,
395            Statement::Goto { location, .. } => location,
396            Statement::Case { location, .. } => location,
397            Statement::Switch { location, .. } => location,
398            Statement::ClassDefinition { location, .. } => location,
399            Statement::MethodDefinition { location, .. } => location,
400            Statement::ObjectDestroy { location, .. } => location,
401        }
402    }
403}
404
405impl Expression {
406    /// Get the location of this expression
407    pub fn location(&self) -> &Location {
408        match self {
409            Expression::Literal { location, .. } => location,
410            Expression::Variable { location, .. } => location,
411            Expression::SystemVariable { location, .. } => location,
412            Expression::ArrayRef { location, .. } => location,
413            Expression::StructRef { location, .. } => location,
414            Expression::MethodCall { location, .. } => location,
415            Expression::FunctionCall { location, .. } => location,
416            Expression::Binary { location, .. } => location,
417            Expression::Unary { location, .. } => location,
418            Expression::Ternary { location, .. } => location,
419            Expression::ArrayDef { location, .. } => location,
420            Expression::StructDef { location, .. } => location,
421            Expression::Pointer { location, .. } => location,
422            Expression::Deref { location, .. } => location,
423            Expression::PostIncrement { location, .. } => location,
424            Expression::PostDecrement { location, .. } => location,
425            Expression::PreIncrement { location, .. } => location,
426            Expression::PreDecrement { location, .. } => location,
427            Expression::ObjectNew { location, .. } => location,
428        }
429    }
430
431    /// Check if this expression is a constant literal
432    pub fn is_constant(&self) -> bool {
433        matches!(self, Expression::Literal { .. })
434    }
435
436    /// Check if this expression is a simple variable reference
437    pub fn is_variable(&self) -> bool {
438        matches!(self, Expression::Variable { .. })
439    }
440}