#[derive(Debug, Clone, PartialEq)]
pub struct Function {
pub params: Vec<String>,
pub is_vararg: bool,
pub body: Block,
}
pub type Block = Vec<Stat>;
#[derive(Debug, Clone, PartialEq)]
pub enum Stat {
LocalAssign {
names: Vec<String>,
exprs: Vec<Expr>,
},
Assign {
targets: Vec<Expr>,
values: Vec<Expr>,
},
Call(CallExpr),
DoBlock(Block),
While {
cond: Expr,
body: Block,
},
Repeat {
body: Block,
cond: Expr,
},
If {
cond: Expr,
then_block: Block,
elseif_clauses: Vec<(Expr, Block)>,
else_block: Option<Block>,
},
NumericFor {
name: String,
start: Expr,
limit: Expr,
step: Option<Expr>,
body: Block,
},
GenericFor {
names: Vec<String>,
iterators: Vec<Expr>,
body: Block,
},
Return(Vec<Expr>),
Break,
Comment(String),
}
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
Nil,
Bool(bool),
Number(NumLit),
StringLit(Vec<u8>),
VarArg,
Name(String),
Index(Box<Expr>, Box<Expr>),
Field(Box<Expr>, String),
MethodCall(Box<CallExpr>),
FuncCall(Box<CallExpr>),
BinOp(BinOp, Box<Expr>, Box<Expr>),
UnOp(UnOp, Box<Expr>),
FunctionDef(Box<Function>),
Table(Vec<TableField>),
Register(u32),
Upvalue(u32),
Global(String),
}
#[derive(Debug, Clone, PartialEq)]
pub enum NumLit {
Int(i64),
Float(f64),
}
#[derive(Debug, Clone, PartialEq)]
pub struct CallExpr {
pub func: Expr,
pub args: Vec<Expr>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TableField {
IndexField(Expr, Expr),
NameField(String, Expr),
Value(Expr),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
Add,
Sub,
Mul,
Div,
Mod,
Pow,
Concat,
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
And,
Or,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnOp {
Neg,
Not,
Len,
}
impl BinOp {
pub fn precedence(self) -> u8 {
match self {
BinOp::Or => 1,
BinOp::And => 2,
BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => 3,
BinOp::Concat => 4,
BinOp::Add | BinOp::Sub => 5,
BinOp::Mul | BinOp::Div | BinOp::Mod => 6,
BinOp::Pow => 7,
}
}
pub fn is_right_assoc(self) -> bool {
matches!(self, BinOp::Pow | BinOp::Concat)
}
pub fn symbol(self) -> &'static str {
match self {
BinOp::Add => "+",
BinOp::Sub => "-",
BinOp::Mul => "*",
BinOp::Div => "/",
BinOp::Mod => "%",
BinOp::Pow => "^",
BinOp::Concat => "..",
BinOp::Eq => "==",
BinOp::Ne => "~=",
BinOp::Lt => "<",
BinOp::Le => "<=",
BinOp::Gt => ">",
BinOp::Ge => ">=",
BinOp::And => "and",
BinOp::Or => "or",
}
}
}
impl UnOp {
pub fn precedence(self) -> u8 {
8 }
pub fn symbol(self) -> &'static str {
match self {
UnOp::Neg => "-",
UnOp::Not => "not ",
UnOp::Len => "#",
}
}
}