Luke Wilson 258b3c8e9b Add comprehensive Zig syntax test coverage
- Add support for error sets and error union types
- Implement for loops with index and payload syntax
- Add defer, break, continue, and switch statements
- Support unary expressions and array indexing
- Add unreachable expression and test declarations
- Extend AST with new type expressions (array, error union)
- Update formatter to handle all new syntax elements
- Fix formatting for switch prongs, payloads, and blocks
2025-06-05 20:44:49 -05:00

545 lines
14 KiB
Go

// Abstract Syntax Tree (AST) definitions for Zig, closely following the grammar in zig-grammar.peg
package zig
// Root is the top-level node of a Zig source file.
type Root struct {
ContainerDocComment DocComment // //! Doc Comment (optional)
ContainerMembers []*ContainerMember
}
type ContainerMember struct {
DocComment DocComment // /// Doc Comment (optional)
Comptime bool // 'comptime' field (optional)
Field *ContainerField
Decl Decl // Can be nil if this is a field
}
// ContainerField represents a field in a struct/enum/union container.
type ContainerField struct {
Name string // May be empty for anonymous fields
Type TypeExpr
ByteAlign *Expr // Optional
Value Expr // Optional initializer
}
// Decl is any top-level declaration (function, variable, usingnamespace, etc).
type Decl interface {
isDecl()
}
// FnFlags is a bitfield for function declaration options.
type FnFlags uint8
const (
FnExport FnFlags = 1 << iota
FnExtern
FnInline
FnNoInline
FnThreadLocal
)
// FnDecl represents a function declaration.
type FnDecl struct {
Flags FnFlags
ExternName string // Optional string for extern
Name string // May be empty (anonymous)
Params []*ParamDecl
ByteAlign *Expr
AddrSpace *Expr
LinkSection *Expr
CallConv *Expr
ReturnType TypeExpr
Body *Block // nil means semicolon
}
func (*FnDecl) isDecl() {}
// GlobalVarFlags is a bitfield for global variable declaration options.
type GlobalVarFlags uint8
const (
GlobalVarConst GlobalVarFlags = 1 << iota
GlobalVarExport
GlobalVarExtern
GlobalVarThreadLocal
)
// GlobalVarDecl represents a top-level (global) variable or constant declaration.
// These are only allowed at the container/module scope and use a restricted syntax:
// no destructuring or multi-var declarations, just a single name and optional type/initializer.
type GlobalVarDecl struct {
Flags GlobalVarFlags
ExternName string // Optional string for extern
Name string
Type TypeExpr // Optional
ByteAlign *Expr
AddrSpace *Expr
LinkSection *Expr
Value Expr // Optional initializer
}
func (*GlobalVarDecl) isDecl() {}
// UsingNamespaceDecl represents a 'usingnamespace' declaration.
type UsingNamespaceDecl struct {
Expr Expr
}
func (*UsingNamespaceDecl) isDecl() {}
// ComptimeDecl represents a 'comptime' block at the container level.
type ComptimeDecl struct {
Block *Block
}
func (*ComptimeDecl) isDecl() {}
// TestDecl represents a 'test' declaration.
type TestDecl struct {
Name string // Optional
Block *Block
}
func (*TestDecl) isDecl() {}
// ParamDecl represents a function parameter.
type ParamDecl struct {
DocComment DocComment // /// Doc Comment (optional)
NoAlias bool
Comptime bool
Name string // May be empty
Type TypeExpr // 'anytype' if empty
}
// ContainerDecl represents a struct, enum, union, or opaque declaration.
type ContainerDecl struct {
Extern bool
Packed bool
Kind string // "struct", "enum", "union", "opaque"
TagType TypeExpr // Optional (for enum/union)
Fields []*ContainerMember
DocComment DocComment
}
func (*ContainerDecl) isDecl() {}
// ErrorSetDecl represents an error set declaration.
type ErrorSetDecl struct {
Names []string
}
func (*ErrorSetDecl) isDecl() {}
// Block represents a block of statements.
type Block struct {
Label string // Optional
Stmts []Stmt
}
// Stmt is any statement.
type Stmt interface {
isStmt()
}
// ExprStmt represents an expression statement (e.g. a function call as a statement).
type ExprStmt struct {
Expr Expr
}
func (*ExprStmt) isStmt() {}
// VarDeclStmt represents a local variable or constant declaration statement inside a function or block.
// These support destructuring and multi-var declarations, and are only valid at statement/block scope.
type VarDeclStmt struct {
Const bool
Pattern VarPattern // Destructuring or multiple variable names
Type TypeExpr // Optional
Value Expr // Optional initializer
ByteAlign Expr // Optional
AddrSpace Expr // Optional
LinkSection Expr // Optional
}
func (*VarDeclStmt) isStmt() {}
// ReturnStmt represents a 'return' statement.
type ReturnStmt struct {
Value Expr // Optional
}
func (*ReturnStmt) isStmt() {}
// IfStmt represents an if statement (with optional else branch and payload).
type IfStmt struct {
Cond Expr // Condition expression
Then Stmt // Then branch
Else Stmt // Optional else branch
Payload *Payload // Optional payload (for |x|, |*x|, |*x, y|, etc.)
}
func (*IfStmt) isStmt() {}
// IfExpr represents an if expression (with optional else branch and payload).
type IfExpr struct {
Cond Expr // Condition expression
Then Expr // Then branch
Else Expr // Optional else branch
Payload *Payload // Optional payload (for |x|, |*x|, |*x, y|, etc.)
}
// DeferStmt represents a 'defer' or 'errdefer' statement.
type DeferStmt struct {
ErrDefer bool // True for 'errdefer', false for 'defer'
Payload *Payload // Optional payload (for |x|, |*x|, etc.)
Stmt Stmt // Statement to defer
}
func (*DeferStmt) isStmt() {}
// SuspendStmt represents a 'suspend' or 'nosuspend' statement.
type SuspendStmt struct {
NoSuspend bool
Stmt Stmt
}
func (*SuspendStmt) isStmt() {}
// BlockStmt allows a block to be used as a statement.
type BlockStmt struct {
Block *Block
}
func (*BlockStmt) isStmt() {}
// BreakStmt represents a 'break' statement.
type BreakStmt struct {
Label string // Optional
Value Expr // Optional
}
func (*BreakStmt) isStmt() {}
// ContinueStmt represents a 'continue' statement.
type ContinueStmt struct {
Label string // Optional
}
func (*ContinueStmt) isStmt() {}
// LoopStmt represents a for/while loop statement.
type LoopStmt struct {
Inline bool // True if 'inline' is present
Kind string // "for" or "while"
Prefix LoopPrefix // ForPrefix or WhilePrefix
Body Stmt // Loop body
Else Stmt // Optional else branch
Payload *Payload // Optional payload (for |x|, |*x|, |*x, y|, etc.)
}
func (*LoopStmt) isStmt() {}
// LoopPrefix is the prefix of a for/while loop.
type LoopPrefix interface{}
// ForPrefix represents the prefix of a for loop.
type ForPrefix struct {
Args []ForArg // For loop arguments
Payload *Payload // Payload (|*x, y|, etc.)
}
// ForArg represents an argument in a for loop.
type ForArg struct {
Expr Expr // Argument expression
From Expr // Optional (for .. or ..<)
}
// WhilePrefix represents the prefix of a while loop.
type WhilePrefix struct {
Cond Expr // Condition expression
Payload *Payload // Optional payload (for |x|, |*x|, etc.)
Continue Expr // Optional (while continue expression)
}
// SwitchStmt represents a switch statement.
type SwitchStmt struct {
Cond Expr
Prongs []*SwitchProng
}
func (*SwitchStmt) isStmt() {}
// SwitchExpr represents a switch expression.
type SwitchExpr struct {
Cond Expr
Prongs []*SwitchProng
}
// SwitchProng represents a prong in a switch.
type SwitchProng struct {
Inline bool // True if 'inline' is present
Cases []*SwitchCase // List of cases for this prong
Payload *Payload // Optional payload (for |*x, y|, etc.)
Expr Expr // Result expression for this prong
}
// SwitchCase represents a case in a switch.
type SwitchCase struct {
Expr Expr
To Expr // Optional (for ..)
IsElse bool
}
// AsmExpr represents an inline assembly expression.
type AsmExpr struct {
Volatile bool
Template Expr
Outputs []*AsmOutputItem
Inputs []*AsmInputItem
Clobbers []string
}
// AsmOutputItem represents an output operand in asm.
type AsmOutputItem struct {
Name string
Constraint string
Type TypeExpr
}
// AsmInputItem represents an input operand in asm.
type AsmInputItem struct {
Name string
Constraint string
Expr Expr
}
// InitListExpr represents an initializer list.
// Exactly one of Fields, Values, or Empty must be set (non-nil/non-empty or true).
type InitListExpr struct {
Fields []*FieldInit // Field initializers (for {.foo = 1, .bar = 2}), mutually exclusive with Values/Empty
Values []Expr // Positional initializers (for {1, 2, 3}), mutually exclusive with Fields/Empty
Empty bool // True if '{}', mutually exclusive with Fields/Values
}
// FieldInit represents a field initializer in an init list.
type FieldInit struct {
Name string
Value Expr
}
// Identifier represents an identifier expression (variable, field, etc).
type Identifier struct {
Name string // The identifier name
}
// Literal represents a literal value (int, float, string, char).
type Literal struct {
Kind string // "int", "float", "string", "char"
Value string // The literal value as a string
}
// BinaryExpr represents a binary operation (e.g. +, -, *, /, etc).
type BinaryExpr struct {
Op string // Operator, e.g. "+", "-", "*", etc.
Left Expr // Left operand
Right Expr // Right operand
}
// UnaryExpr represents a unary operation (e.g. !, -, ~, etc).
type UnaryExpr struct {
Op string // Operator, e.g. "-", "!", "~"
Expr Expr // Operand
}
// GroupedExpr represents a parenthesized expression.
type GroupedExpr struct {
Expr Expr // The grouped expression
}
// CallExpr represents a function call.
type CallExpr struct {
Fun Expr // Function being called
Args []Expr // Arguments to the function
}
// FieldAccessExpr represents a field/member access as a suffix operation (e.g. foo.bar).
//
// Note: in order to call a function on an object, use a CallExpr with a Fun of a FieldAccessExpr.
// See TestHelloWorld for example.
type FieldAccessExpr struct {
Receiver Expr // The object being accessed
Field string // The field name
}
// IndexExpr represents an indexing operation as a suffix (e.g. arr[0]).
type IndexExpr struct {
Receiver Expr // The object being indexed
Index Expr // The index expression
}
// ResumeExpr represents a 'resume' expression.
type ResumeExpr struct {
Expr Expr // The expression to resume
}
// ComptimeExpr represents a 'comptime' expression.
type ComptimeExpr struct {
Expr Expr // The expression to evaluate at comptime
}
// NosuspendExpr represents a 'nosuspend' expression.
type NosuspendExpr struct {
Expr Expr // The expression to evaluate with nosuspend
}
// ContinueExpr represents a 'continue' expression.
type ContinueExpr struct {
Label string // Optional label
}
// Expr is any expression.
type Expr interface{}
// TypeExpr is any type expression.
type TypeExpr interface{}
// PrefixTypeExpr represents a type with a string prefix. Examples include optionals and pointers.
type PrefixTypeExpr struct {
Op string
Base TypeExpr
}
// ArrayTypeExpr represents an array type ([N]T).
type ArrayTypeExpr struct {
Size Expr
Elem TypeExpr
}
// SliceTypeExpr represents a slice type ([]T).
type SliceTypeExpr struct {
Elem TypeExpr
}
// ErrorUnionTypeExpr represents an error union type (E!T).
type ErrorUnionTypeExpr struct {
ErrSet TypeExpr
Type TypeExpr
}
// DocComment represents a doc comment (/// or //! lines).
// Newlines in the string automatically add more comments in the output.
type DocComment string
// Payload represents a control flow payload (|x|, |*x|, |*x, y|, etc).
// Each entry in Names corresponds to a variable name; the same index in Pointers is true if that name is a pointer (|*x|).
type Payload struct {
Names []string // Names in the payload, in order
Pointers []bool // True if the corresponding name is a pointer (|*x|, |*x, y|, |*x, *y|, etc.)
}
// LabeledBlock represents a labeled block or loop (label: {...}).
type LabeledBlock struct {
Label string // The label name
Block *Block // The labeled block
}
// LabeledTypeExpr represents a labeled type block (label: type).
type LabeledTypeExpr struct {
Label string // The label name
Type TypeExpr // The labeled type
}
// IfTypeExpr represents an if expression at the type level.
type IfTypeExpr struct {
Cond Expr
Then TypeExpr
Else TypeExpr // Optional
Payload *Payload // Optional
}
// ForTypeExpr represents a for expression at the type level.
type ForTypeExpr struct {
Prefix *ForPrefix
Body TypeExpr
Else TypeExpr // Optional
Payload *Payload // Optional
}
// WhileTypeExpr represents a while expression at the type level.
type WhileTypeExpr struct {
Prefix *WhilePrefix
Body TypeExpr
Else TypeExpr // Optional
Payload *Payload // Optional
}
// DotAsteriskExpr represents a .*
type DotAsteriskExpr struct {
Receiver Expr // The expression being dereferenced
}
// DotQuestionExpr represents a .?
type DotQuestionExpr struct {
Receiver Expr // The expression being checked for optional
}
// AsyncExpr represents an 'async' expression.
type AsyncExpr struct {
Expr Expr // The expression to be awaited asynchronously
}
// TryExpr represents a 'try' expression.
type TryExpr struct {
Expr Expr // The expression to try
}
// AwaitExpr represents an 'await' expression.
type AwaitExpr struct {
Expr Expr // The expression to await
}
// UnreachableExpr represents the 'unreachable' keyword.
type UnreachableExpr struct{}
// EmptyInitListExpr represents an empty initializer list '{}'.
type EmptyInitListExpr struct{}
// PositionalInitListExpr represents a positional initializer list '{expr, ...}'.
type PositionalInitListExpr struct {
Values []Expr // Expressions in order
}
// FieldInitListExpr represents a field initializer list '{.field = expr, ...}'.
type FieldInitListExpr struct {
Fields []*FieldInit // Field initializers
}
// SwitchProngPayload represents a switch prong payload (|*x, y|).
type SwitchProngPayload struct {
Pointer bool
Names []string
}
// SwitchProngCase represents a single case in a switch prong.
type SwitchProngCase struct {
Expr Expr // The case expression
To Expr // Optional, for ranges
}
// SwitchProngFull represents a full switch prong with cases and payload.
type SwitchProngFull struct {
Inline bool
Cases []*SwitchProngCase // One or more cases
Payload *SwitchProngPayload // Optional
Expr Expr // The result expression
}
// SwitchElseProng represents an 'else' prong in a switch.
type SwitchElseProng struct {
Expr Expr // The result expression
}
// VarPattern represents a variable pattern for destructuring or multiple variable declarations.
type VarPattern struct {
Names []string // Variable names (single or multiple for destructuring)
}