// This grammar describes a single line of Redcode, without handling comments
// or multi-line `EQU` and `FOR` macros.
// Top-level definitions
WHITESPACE = _{ " " | "\t" }
Line = _{ LabelDeclaration? ~ Statement? }
Statement = _{ Instruction | EquStatement | LabelUsage }
Expression = { Expr }
// Redcode instructions
Instruction = { Operation ~ Field ~ ("," ~ Field)? }
Operation = ${ Opcode ~ ("." ~ Modifier)? ~ !ASCII_ALPHANUMERIC }
Field = { AddressMode? ~ Expression }
Opcode = {
^"DAT" | ^"MOV" | ^"ADD" | ^"SUB" | ^"MUL" | ^"DIV" | ^"MOD" |
^"JMP" | ^"JMZ" | ^"JMN" | ^"DJN" | ^"CMP" | ^"SEQ" | ^"SNE" |
^"SLT" | ^"SPL" | ^"NOP" | ^"ORG" | ^"END"
}
Modifier = { ^"AB" | ^"BA" | ^"A" | ^"B" | ^"F" | ^"X" | ^"I" }
AddressMode = { "#" | "$" | "*" | "@" | "{" | "<" | "}" | ">" }
// Substitutions
LabelDeclaration = _{ !(Instruction | EquStatement) ~ Label ~ (":")? }
LabelUsage = _{ Label }
EquStatement = _{ ^"EQU" ~ Substitution }
Substitution = { ANY* }
// Expressions
Expr = _{ Value ~ BooleanExpr* }
Value = { Sum ~ CompareExpr* }
BooleanExpr = _{ BooleanOp ~ Value }
Sum = { Product ~ AddExpr* }
CompareExpr = _{ CompareOp ~ Sum }
Product = { UnaryExpr ~ MultiplyExpr* }
UnaryExpr = { UnaryOp* ~ (Atom | ParenExpr) }
MultiplyExpr = _{ MultiplyOp ~ UnaryExpr }
AddExpr = _{ AddOp ~ Product }
Atom = _{ Number | LabelUsage }
ParenExpr = _{ "(" ~ Expression ~ ")" }
MultiplyOp = { "*" | "/" | "%" }
AddOp = {"+" | "-" }
UnaryOp = { "-" | "+" | "!" }
CompareOp = { "<=" | "<" | ">=" | ">" | "==" | "!=" }
BooleanOp = { "&&" | "||" }
// Terminal rules
Number = @{ ASCII_DIGIT+ }
Alpha = _{ ASCII_ALPHA | "_" }
Alphanumeral = _{ ASCII_ALPHANUMERIC | "_" }
Label = @{ Alpha ~ Alphanumeral* }