Add expression AST and Pratt parser with REPL

- ast.rs: Expr/ExprKind with UnaryOp, BinaryOp, StructField
- parser.rs: Pratt expression parser with allow_struct_literals flag,
  error recovery via dummy tokens, and 19 unit tests
- main.rs: interactive expression REPL (prints parsed AST)
This commit is contained in:
2026-03-10 17:40:52 +01:00
parent 4f80de51b2
commit becc7a2d34
3 changed files with 767 additions and 6 deletions

113
fluxc/src/ast.rs Normal file
View File

@@ -0,0 +1,113 @@
use crate::token::Span;
// ── Operators ──────────────────────────────────────────────────────────────────
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Neg, // `-`
Not, // `!`
BitNot, // `~`
Deref, // `*`
AddrOf, // `&`
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
// Logical
Or, // `or`
And, // `and`
// Bitwise
BitOr, // `|`
BitXor, // `^`
BitAnd, // `&`
// Comparison
Eq, // `==`
Ne, // `!=`
Lt, // `<`
Gt, // `>`
Le, // `<=`
Ge, // `>=`
// Arithmetic
Add, // `+`
Sub, // `-`
Mul, // `*`
Div, // `/`
Rem, // `%`
}
// ── Struct literal field ───────────────────────────────────────────────────────
#[derive(Debug, Clone)]
pub struct StructField {
pub name: String,
pub name_span: Span,
pub value: Expr,
}
// ── Expression ────────────────────────────────────────────────────────────────
#[derive(Debug, Clone)]
pub struct Expr {
pub kind: ExprKind,
pub span: Span,
}
impl Expr {
pub fn new(kind: ExprKind, span: Span) -> Self {
Self { kind, span }
}
}
#[derive(Debug, Clone)]
pub enum ExprKind {
// Literals
IntLit(String),
FloatLit(String),
StringLit(String),
CharLit(String),
Bool(bool),
// Identifier
Ident(String),
// Struct literal: `Foo { x: 1, y: 2 }`
StructLit {
name: String,
name_span: Span,
fields: Vec<StructField>,
},
// Operators
Unary {
op: UnaryOp,
op_span: Span,
expr: Box<Expr>,
},
Binary {
op: BinaryOp,
op_span: Span,
lhs: Box<Expr>,
rhs: Box<Expr>,
},
// Postfix
Field {
expr: Box<Expr>,
field: String,
field_span: Span,
},
Index {
expr: Box<Expr>,
index: Box<Expr>,
},
Call {
callee: Box<Expr>,
args: Vec<Expr>,
},
// Parenthesised expression
Group(Box<Expr>),
// Placeholder for parse errors — allows parsing to continue
Error,
}