Skip to content

Commit b7a3524

Browse files
authored
feat: implement mapping language parser with AST and expression support (#44)
- Define AST types: Program, Statement (Rename, Select, Drop, Set, Default, Cast), Expr (Literal, Path, FunctionCall, BinaryOp, UnaryOp), Path with segments (Field, Index, Wildcard), CastType, BinOp, UnaryOp - Implement recursive descent parser with precedence climbing for expressions: or < and < comparison < additive < multiplicative < unary - Parse all 6 statement types with full syntax validation - Support paths with nested fields, array indices, wildcards, and quoted string keys; keyword names allowed as field names - Support expressions: literals (int, float, string, bool, null), path references, function calls (nested, multi-arg, zero-arg), binary ops (+, -, *, /, %, ==, !=, >, >=, <, <=, and, or), unary ops (not, -), and parenthesized grouping - Cast type aliases: integer/int, float/number, string/str, bool/boolean - Error messages with line:column positions and keyword suggestions - Add 60+ tests covering: all statement types, literal types, paths (nested, array index, wildcard, quoted key, keyword field), function calls (single/multi/zero/nested args), all operators, precedence (mul before add, parens override, comparison after arithmetic, and before or), unary not, multi-statement programs, blank lines, comments, empty programs, string concatenation, error cases (missing arrow, missing =, unknown keyword, typo suggestions, missing path, unknown cast type, incomplete statements), and a complex 7-statement program Fixes #16
1 parent fb4fe38 commit b7a3524

File tree

2 files changed

+1729
-2
lines changed

2 files changed

+1729
-2
lines changed

src/mapping/ast.rs

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,103 @@
1-
// TODO: Mapping language AST types
1+
use crate::mapping::lexer::Span;
2+
3+
/// A field path like `.name`, `.users.[0].name`, or `.a.b.c`.
4+
#[derive(Debug, Clone, PartialEq)]
5+
pub struct Path {
6+
pub segments: Vec<PathSegment>,
7+
pub span: Span,
8+
}
9+
10+
/// A single segment in a field path.
11+
#[derive(Debug, Clone, PartialEq)]
12+
pub enum PathSegment {
13+
/// A named field: `.name`
14+
Field(String),
15+
/// An array index: `.[0]`
16+
Index(i64),
17+
/// A wildcard: `.[*]`
18+
Wildcard,
19+
}
20+
21+
/// The target type for cast operations.
22+
#[derive(Debug, Clone, PartialEq, Eq)]
23+
pub enum CastType {
24+
Int,
25+
Float,
26+
String,
27+
Bool,
28+
}
29+
30+
/// A binary operator.
31+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32+
pub enum BinOp {
33+
Add,
34+
Sub,
35+
Mul,
36+
Div,
37+
Mod,
38+
Eq,
39+
NotEq,
40+
Gt,
41+
GtEq,
42+
Lt,
43+
LtEq,
44+
And,
45+
Or,
46+
}
47+
48+
/// A unary operator.
49+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50+
pub enum UnaryOp {
51+
Neg,
52+
Not,
53+
}
54+
55+
/// An expression in the mapping language.
56+
#[derive(Debug, Clone, PartialEq)]
57+
pub enum Expr {
58+
/// A literal value: `42`, `"hello"`, `true`, `null`.
59+
Literal(crate::value::Value),
60+
/// A path reference: `.name`, `.users.[0].age`.
61+
Path(Path),
62+
/// A function call: `lower(.name)`, `replace(.s, "a", "b")`.
63+
FunctionCall {
64+
name: String,
65+
args: Vec<Expr>,
66+
span: Span,
67+
},
68+
/// A binary operation: `.a + .b`, `.x == 42`.
69+
BinaryOp {
70+
left: Box<Expr>,
71+
op: BinOp,
72+
right: Box<Expr>,
73+
},
74+
/// A unary operation: `not .active`, `-.value`.
75+
UnaryOp { op: UnaryOp, expr: Box<Expr> },
76+
}
77+
78+
/// A statement in the mapping language.
79+
#[derive(Debug, Clone, PartialEq)]
80+
pub enum Statement {
81+
/// `rename .old -> .new`
82+
Rename { from: Path, to: Path, span: Span },
83+
/// `select .a, .b, .c`
84+
Select { paths: Vec<Path>, span: Span },
85+
/// `drop .x, .y`
86+
Drop { paths: Vec<Path>, span: Span },
87+
/// `set .x = <expr>`
88+
Set { path: Path, expr: Expr, span: Span },
89+
/// `default .x = <expr>`
90+
Default { path: Path, expr: Expr, span: Span },
91+
/// `cast .x as int`
92+
Cast {
93+
path: Path,
94+
target_type: CastType,
95+
span: Span,
96+
},
97+
}
98+
99+
/// A parsed mapping program: a list of statements.
100+
#[derive(Debug, Clone, PartialEq)]
101+
pub struct Program {
102+
pub statements: Vec<Statement>,
103+
}

0 commit comments

Comments
 (0)