1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-09 17:28:00 +00:00
nescript/src/parser/ast.rs

270 lines
5.2 KiB
Rust
Raw Normal View History

Implement NEScript compiler Milestone 1 ("Hello Sprite") Complete implementation of the NEScript compiler pipeline for M1: - Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators - Parser: recursive descent with Pratt expression parsing (M1 subset) - Analyzer: symbol resolution, type checking, memory allocation - 6502 Assembler: full opcode encoding table (~150 valid combinations) - Code Generator: AST → 6502 instructions (direct, no IR for M1) - Runtime: NES hardware init, NMI handler, controller read, OAM DMA - Linker: NROM layout, vector table, palette loading, CHR data - ROM Builder: iNES header generation, PRG/CHR padding - CLI: `build` and `check` subcommands via clap 143 tests across all modules: - 22 lexer tests (literals, keywords, operators, error recovery) - 18 parser tests (expressions, statements, game structure, errors) - 7 analyzer tests (symbol resolution, memory allocation, transitions) - 30 assembler tests (every addressing mode, label resolution) - 7 codegen tests (var init, arithmetic, buttons, draw, comparisons) - 11 runtime tests (init sequence, NMI handler, controller read) - 10 ROM builder tests (iNES format, mirroring, banking, validation) - 5 linker tests (vector table, CHR data, palette loading) - 7 integration tests (end-to-end compilation, error detection) CI: GitHub Actions for check, fmt, clippy, test Pre-commit: script for local fmt + clippy + test validation https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
use crate::lexer::Span;
#[derive(Debug, Clone)]
pub struct Program {
pub game: GameDecl,
pub globals: Vec<VarDecl>,
pub constants: Vec<ConstDecl>,
pub functions: Vec<FunDecl>,
pub states: Vec<StateDecl>,
pub sprites: Vec<SpriteDecl>,
pub palettes: Vec<PaletteDecl>,
pub backgrounds: Vec<BackgroundDecl>,
pub banks: Vec<BankDecl>,
Implement NEScript compiler Milestone 1 ("Hello Sprite") Complete implementation of the NEScript compiler pipeline for M1: - Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators - Parser: recursive descent with Pratt expression parsing (M1 subset) - Analyzer: symbol resolution, type checking, memory allocation - 6502 Assembler: full opcode encoding table (~150 valid combinations) - Code Generator: AST → 6502 instructions (direct, no IR for M1) - Runtime: NES hardware init, NMI handler, controller read, OAM DMA - Linker: NROM layout, vector table, palette loading, CHR data - ROM Builder: iNES header generation, PRG/CHR padding - CLI: `build` and `check` subcommands via clap 143 tests across all modules: - 22 lexer tests (literals, keywords, operators, error recovery) - 18 parser tests (expressions, statements, game structure, errors) - 7 analyzer tests (symbol resolution, memory allocation, transitions) - 30 assembler tests (every addressing mode, label resolution) - 7 codegen tests (var init, arithmetic, buttons, draw, comparisons) - 11 runtime tests (init sequence, NMI handler, controller read) - 10 ROM builder tests (iNES format, mirroring, banking, validation) - 5 linker tests (vector table, CHR data, palette loading) - 7 integration tests (end-to-end compilation, error detection) CI: GitHub Actions for check, fmt, clippy, test Pre-commit: script for local fmt + clippy + test validation https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
pub start_state: String,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct SpriteDecl {
pub name: String,
pub chr_source: AssetSource,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct PaletteDecl {
pub name: String,
pub colors: Vec<u8>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct BackgroundDecl {
pub name: String,
pub chr_source: AssetSource,
pub span: Span,
}
#[derive(Debug, Clone)]
pub enum AssetSource {
Chr(String),
Binary(String),
Inline(Vec<u8>),
}
Implement NEScript compiler Milestone 1 ("Hello Sprite") Complete implementation of the NEScript compiler pipeline for M1: - Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators - Parser: recursive descent with Pratt expression parsing (M1 subset) - Analyzer: symbol resolution, type checking, memory allocation - 6502 Assembler: full opcode encoding table (~150 valid combinations) - Code Generator: AST → 6502 instructions (direct, no IR for M1) - Runtime: NES hardware init, NMI handler, controller read, OAM DMA - Linker: NROM layout, vector table, palette loading, CHR data - ROM Builder: iNES header generation, PRG/CHR padding - CLI: `build` and `check` subcommands via clap 143 tests across all modules: - 22 lexer tests (literals, keywords, operators, error recovery) - 18 parser tests (expressions, statements, game structure, errors) - 7 analyzer tests (symbol resolution, memory allocation, transitions) - 30 assembler tests (every addressing mode, label resolution) - 7 codegen tests (var init, arithmetic, buttons, draw, comparisons) - 11 runtime tests (init sequence, NMI handler, controller read) - 10 ROM builder tests (iNES format, mirroring, banking, validation) - 5 linker tests (vector table, CHR data, palette loading) - 7 integration tests (end-to-end compilation, error detection) CI: GitHub Actions for check, fmt, clippy, test Pre-commit: script for local fmt + clippy + test validation https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
#[derive(Debug, Clone)]
pub struct GameDecl {
pub name: String,
pub mapper: Mapper,
pub mirroring: Mirroring,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mapper {
NROM,
MMC1,
UxROM,
MMC3,
Implement NEScript compiler Milestone 1 ("Hello Sprite") Complete implementation of the NEScript compiler pipeline for M1: - Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators - Parser: recursive descent with Pratt expression parsing (M1 subset) - Analyzer: symbol resolution, type checking, memory allocation - 6502 Assembler: full opcode encoding table (~150 valid combinations) - Code Generator: AST → 6502 instructions (direct, no IR for M1) - Runtime: NES hardware init, NMI handler, controller read, OAM DMA - Linker: NROM layout, vector table, palette loading, CHR data - ROM Builder: iNES header generation, PRG/CHR padding - CLI: `build` and `check` subcommands via clap 143 tests across all modules: - 22 lexer tests (literals, keywords, operators, error recovery) - 18 parser tests (expressions, statements, game structure, errors) - 7 analyzer tests (symbol resolution, memory allocation, transitions) - 30 assembler tests (every addressing mode, label resolution) - 7 codegen tests (var init, arithmetic, buttons, draw, comparisons) - 11 runtime tests (init sequence, NMI handler, controller read) - 10 ROM builder tests (iNES format, mirroring, banking, validation) - 5 linker tests (vector table, CHR data, palette loading) - 7 integration tests (end-to-end compilation, error detection) CI: GitHub Actions for check, fmt, clippy, test Pre-commit: script for local fmt + clippy + test validation https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mirroring {
Horizontal,
Vertical,
}
#[derive(Debug, Clone)]
pub struct BankDecl {
pub name: String,
pub bank_type: BankType,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BankType {
Prg,
Chr,
}
Implement NEScript compiler Milestone 1 ("Hello Sprite") Complete implementation of the NEScript compiler pipeline for M1: - Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators - Parser: recursive descent with Pratt expression parsing (M1 subset) - Analyzer: symbol resolution, type checking, memory allocation - 6502 Assembler: full opcode encoding table (~150 valid combinations) - Code Generator: AST → 6502 instructions (direct, no IR for M1) - Runtime: NES hardware init, NMI handler, controller read, OAM DMA - Linker: NROM layout, vector table, palette loading, CHR data - ROM Builder: iNES header generation, PRG/CHR padding - CLI: `build` and `check` subcommands via clap 143 tests across all modules: - 22 lexer tests (literals, keywords, operators, error recovery) - 18 parser tests (expressions, statements, game structure, errors) - 7 analyzer tests (symbol resolution, memory allocation, transitions) - 30 assembler tests (every addressing mode, label resolution) - 7 codegen tests (var init, arithmetic, buttons, draw, comparisons) - 11 runtime tests (init sequence, NMI handler, controller read) - 10 ROM builder tests (iNES format, mirroring, banking, validation) - 5 linker tests (vector table, CHR data, palette loading) - 7 integration tests (end-to-end compilation, error detection) CI: GitHub Actions for check, fmt, clippy, test Pre-commit: script for local fmt + clippy + test validation https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
#[derive(Debug, Clone)]
pub struct StateDecl {
pub name: String,
pub locals: Vec<VarDecl>,
pub on_enter: Option<Block>,
pub on_exit: Option<Block>,
pub on_frame: Option<Block>,
pub on_scanline: Vec<(u8, Block)>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct FunDecl {
pub name: String,
pub params: Vec<Param>,
pub return_type: Option<NesType>,
pub body: Block,
pub is_inline: bool,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct Param {
pub name: String,
pub param_type: NesType,
}
#[derive(Debug, Clone)]
pub struct VarDecl {
pub name: String,
pub var_type: NesType,
pub init: Option<Expr>,
pub placement: Placement,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct ConstDecl {
pub name: String,
pub const_type: NesType,
pub value: Expr,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Placement {
Fast,
Slow,
Auto,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NesType {
U8,
I8,
U16,
Bool,
Array(Box<NesType>, u16),
}
impl std::fmt::Display for NesType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::U8 => write!(f, "u8"),
Self::I8 => write!(f, "i8"),
Self::U16 => write!(f, "u16"),
Self::Bool => write!(f, "bool"),
Self::Array(t, n) => write!(f, "{t}[{n}]"),
}
}
}
#[derive(Debug, Clone)]
pub struct Block {
pub statements: Vec<Statement>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub enum Expr {
IntLiteral(u16, Span),
BoolLiteral(bool, Span),
Ident(String, Span),
ArrayIndex(String, Box<Expr>, Span),
BinaryOp(Box<Expr>, BinOp, Box<Expr>, Span),
UnaryOp(UnaryOp, Box<Expr>, Span),
Call(String, Vec<Expr>, Span),
ButtonRead(Option<Player>, String, Span),
ArrayLiteral(Vec<Expr>, Span),
Cast(Box<Expr>, NesType, Span),
Implement NEScript compiler Milestone 1 ("Hello Sprite") Complete implementation of the NEScript compiler pipeline for M1: - Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators - Parser: recursive descent with Pratt expression parsing (M1 subset) - Analyzer: symbol resolution, type checking, memory allocation - 6502 Assembler: full opcode encoding table (~150 valid combinations) - Code Generator: AST → 6502 instructions (direct, no IR for M1) - Runtime: NES hardware init, NMI handler, controller read, OAM DMA - Linker: NROM layout, vector table, palette loading, CHR data - ROM Builder: iNES header generation, PRG/CHR padding - CLI: `build` and `check` subcommands via clap 143 tests across all modules: - 22 lexer tests (literals, keywords, operators, error recovery) - 18 parser tests (expressions, statements, game structure, errors) - 7 analyzer tests (symbol resolution, memory allocation, transitions) - 30 assembler tests (every addressing mode, label resolution) - 7 codegen tests (var init, arithmetic, buttons, draw, comparisons) - 11 runtime tests (init sequence, NMI handler, controller read) - 10 ROM builder tests (iNES format, mirroring, banking, validation) - 5 linker tests (vector table, CHR data, palette loading) - 7 integration tests (end-to-end compilation, error detection) CI: GitHub Actions for check, fmt, clippy, test Pre-commit: script for local fmt + clippy + test validation https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
}
impl Expr {
pub fn span(&self) -> Span {
match self {
Self::IntLiteral(_, s)
| Self::BoolLiteral(_, s)
| Self::Ident(_, s)
| Self::ArrayIndex(_, _, s)
| Self::BinaryOp(_, _, _, s)
| Self::UnaryOp(_, _, s)
| Self::Call(_, _, s)
| Self::ButtonRead(_, _, s)
| Self::ArrayLiteral(_, s)
| Self::Cast(_, _, s) => *s,
Implement NEScript compiler Milestone 1 ("Hello Sprite") Complete implementation of the NEScript compiler pipeline for M1: - Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators - Parser: recursive descent with Pratt expression parsing (M1 subset) - Analyzer: symbol resolution, type checking, memory allocation - 6502 Assembler: full opcode encoding table (~150 valid combinations) - Code Generator: AST → 6502 instructions (direct, no IR for M1) - Runtime: NES hardware init, NMI handler, controller read, OAM DMA - Linker: NROM layout, vector table, palette loading, CHR data - ROM Builder: iNES header generation, PRG/CHR padding - CLI: `build` and `check` subcommands via clap 143 tests across all modules: - 22 lexer tests (literals, keywords, operators, error recovery) - 18 parser tests (expressions, statements, game structure, errors) - 7 analyzer tests (symbol resolution, memory allocation, transitions) - 30 assembler tests (every addressing mode, label resolution) - 7 codegen tests (var init, arithmetic, buttons, draw, comparisons) - 11 runtime tests (init sequence, NMI handler, controller read) - 10 ROM builder tests (iNES format, mirroring, banking, validation) - 5 linker tests (vector table, CHR data, palette loading) - 7 integration tests (end-to-end compilation, error detection) CI: GitHub Actions for check, fmt, clippy, test Pre-commit: script for local fmt + clippy + test validation https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
Add,
Sub,
Mul,
Div,
Mod,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
ShiftLeft,
ShiftRight,
Eq,
NotEq,
Lt,
Gt,
LtEq,
GtEq,
And,
Or,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Negate,
Not,
BitNot,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Player {
P1,
P2,
}
#[derive(Debug, Clone)]
pub enum Statement {
VarDecl(VarDecl),
Assign(LValue, AssignOp, Expr, Span),
If(Expr, Block, Vec<(Expr, Block)>, Option<Block>, Span),
While(Expr, Block, Span),
Loop(Block, Span),
Break(Span),
Continue(Span),
Return(Option<Expr>, Span),
Draw(DrawStmt),
Transition(String, Span),
WaitFrame(Span),
Call(String, Vec<Expr>, Span),
LoadBackground(String, Span),
SetPalette(String, Span),
Scroll(Expr, Expr, Span),
Implement NEScript compiler Milestone 1 ("Hello Sprite") Complete implementation of the NEScript compiler pipeline for M1: - Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators - Parser: recursive descent with Pratt expression parsing (M1 subset) - Analyzer: symbol resolution, type checking, memory allocation - 6502 Assembler: full opcode encoding table (~150 valid combinations) - Code Generator: AST → 6502 instructions (direct, no IR for M1) - Runtime: NES hardware init, NMI handler, controller read, OAM DMA - Linker: NROM layout, vector table, palette loading, CHR data - ROM Builder: iNES header generation, PRG/CHR padding - CLI: `build` and `check` subcommands via clap 143 tests across all modules: - 22 lexer tests (literals, keywords, operators, error recovery) - 18 parser tests (expressions, statements, game structure, errors) - 7 analyzer tests (symbol resolution, memory allocation, transitions) - 30 assembler tests (every addressing mode, label resolution) - 7 codegen tests (var init, arithmetic, buttons, draw, comparisons) - 11 runtime tests (init sequence, NMI handler, controller read) - 10 ROM builder tests (iNES format, mirroring, banking, validation) - 5 linker tests (vector table, CHR data, palette loading) - 7 integration tests (end-to-end compilation, error detection) CI: GitHub Actions for check, fmt, clippy, test Pre-commit: script for local fmt + clippy + test validation https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
}
#[derive(Debug, Clone)]
pub struct DrawStmt {
pub sprite_name: String,
pub x: Expr,
pub y: Expr,
pub frame: Option<Expr>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub enum LValue {
Var(String),
ArrayIndex(String, Box<Expr>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AssignOp {
Assign,
PlusAssign,
MinusAssign,
AmpAssign,
PipeAssign,
CaretAssign,
ShiftLeftAssign,
ShiftRightAssign,
Implement NEScript compiler Milestone 1 ("Hello Sprite") Complete implementation of the NEScript compiler pipeline for M1: - Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators - Parser: recursive descent with Pratt expression parsing (M1 subset) - Analyzer: symbol resolution, type checking, memory allocation - 6502 Assembler: full opcode encoding table (~150 valid combinations) - Code Generator: AST → 6502 instructions (direct, no IR for M1) - Runtime: NES hardware init, NMI handler, controller read, OAM DMA - Linker: NROM layout, vector table, palette loading, CHR data - ROM Builder: iNES header generation, PRG/CHR padding - CLI: `build` and `check` subcommands via clap 143 tests across all modules: - 22 lexer tests (literals, keywords, operators, error recovery) - 18 parser tests (expressions, statements, game structure, errors) - 7 analyzer tests (symbol resolution, memory allocation, transitions) - 30 assembler tests (every addressing mode, label resolution) - 7 codegen tests (var init, arithmetic, buttons, draw, comparisons) - 11 runtime tests (init sequence, NMI handler, controller read) - 10 ROM builder tests (iNES format, mirroring, banking, validation) - 5 linker tests (vector table, CHR data, palette loading) - 7 integration tests (end-to-end compilation, error detection) CI: GitHub Actions for check, fmt, clippy, test Pre-commit: script for local fmt + clippy + test validation https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
}