#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum VarRef {
Global(u32),
Local(u32),
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub(super) enum BinOp {
Add,
Sub,
Mul,
Div,
Mod,
Pow,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub(super) enum CmpOp {
Lt,
Le,
Gt,
Ge,
Eq,
Ne,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub(super) enum Bi {
Length,
Substr,
Index,
Split,
Sub,
Gsub,
Gensub,
Match,
Sprintf,
Sin,
Cos,
Atan2,
Exp,
Log,
Sqrt,
Int,
Rand,
Srand,
Tolower,
Toupper,
System,
Close,
Fflush,
Strtonum,
Systime,
Strftime,
Mktime,
Asort,
Asorti,
Typeof,
Isarray,
And,
Or,
Xor,
Lshift,
Rshift,
Compl,
Patsplit,
}
impl Bi {
pub(super) fn from_name(name: &str) -> Option<Bi> {
Some(match name {
"length" => Bi::Length,
"substr" => Bi::Substr,
"index" => Bi::Index,
"split" => Bi::Split,
"sub" => Bi::Sub,
"gsub" => Bi::Gsub,
"gensub" => Bi::Gensub,
"match" => Bi::Match,
"sprintf" => Bi::Sprintf,
"sin" => Bi::Sin,
"cos" => Bi::Cos,
"atan2" => Bi::Atan2,
"exp" => Bi::Exp,
"log" => Bi::Log,
"sqrt" => Bi::Sqrt,
"int" => Bi::Int,
"rand" => Bi::Rand,
"srand" => Bi::Srand,
"tolower" => Bi::Tolower,
"toupper" => Bi::Toupper,
"system" => Bi::System,
"close" => Bi::Close,
"fflush" => Bi::Fflush,
"strtonum" => Bi::Strtonum,
"systime" => Bi::Systime,
"strftime" => Bi::Strftime,
"mktime" => Bi::Mktime,
"asort" => Bi::Asort,
"asorti" => Bi::Asorti,
"typeof" => Bi::Typeof,
"isarray" => Bi::Isarray,
"and" => Bi::And,
"or" => Bi::Or,
"xor" => Bi::Xor,
"lshift" => Bi::Lshift,
"rshift" => Bi::Rshift,
"compl" => Bi::Compl,
"patsplit" => Bi::Patsplit,
_ => return None,
})
}
pub(super) fn array_args(self) -> &'static [usize] {
match self {
Bi::Split | Bi::Patsplit => &[1, 3],
Bi::Match => &[2],
Bi::Asort | Bi::Asorti => &[0, 1],
_ => &[],
}
}
}
#[derive(Debug, Clone)]
pub(super) enum GetlineSrc {
Main,
File(Box<Expr>),
Cmd(Box<Expr>),
}
#[derive(Debug, Clone)]
pub(super) enum Expr {
Num(f64),
Str(String),
Regex(u32),
Var(VarRef),
Elem(VarRef, Vec<Vec<Expr>>),
Field(Box<Expr>),
Assign(Box<Expr>, Option<BinOp>, Box<Expr>),
Neg(Box<Expr>),
Plus(Box<Expr>),
Not(Box<Expr>),
Binary(BinOp, Box<Expr>, Box<Expr>),
Cmp(CmpOp, Box<Expr>, Box<Expr>),
Match(bool, Box<Expr>, Box<Expr>),
And(Box<Expr>, Box<Expr>),
Or(Box<Expr>, Box<Expr>),
Cond(Box<Expr>, Box<Expr>, Box<Expr>),
Concat(Box<Expr>, Box<Expr>),
In(Vec<Expr>, Box<Expr>),
IncDec(Box<Expr>, f64, bool),
Call(u32, Vec<Expr>),
Indirect(Box<Expr>, Vec<Expr>),
Builtin(Bi, Vec<Expr>),
Getline(GetlineSrc, Option<Box<Expr>>),
Group(Box<Expr>),
List(Vec<Expr>),
}
impl Expr {
pub(super) fn is_lvalue(&self) -> bool {
matches!(self, Expr::Var(_) | Expr::Elem(..) | Expr::Field(_))
}
}
#[derive(Debug, Clone)]
pub(super) enum Redirect {
File(Expr),
Append(Expr),
Pipe(Expr),
}
#[derive(Debug, Clone)]
pub(super) struct Stmt {
pub(super) kind: StmtKind,
pub(super) loc: u32,
}
pub(super) type Block = Vec<Stmt>;
#[derive(Debug, Clone)]
pub(super) enum StmtKind {
Expr(Expr),
Print(Vec<Expr>, Option<Redirect>),
Printf(Vec<Expr>, Option<Redirect>),
If(Expr, Block, Option<Block>),
While(Expr, Block),
Do(Block, Expr),
For(Option<Box<Stmt>>, Option<Expr>, Option<Box<Stmt>>, Block),
ForIn(Expr, Expr, Block),
Block(Block),
Next,
NextFile,
Exit(Option<Expr>),
Return(Option<Expr>),
Break,
Continue,
Delete(Expr),
Switch(Expr, Vec<(CaseLabel, Block)>),
}
#[derive(Debug, Clone)]
pub(super) enum CaseLabel {
Value(Expr),
Regex(u32),
Default,
}
#[derive(Debug, Clone)]
pub(super) enum Pattern {
All,
Expr(Expr),
Range(Expr, Expr, usize),
}
#[derive(Debug, Clone)]
pub(super) struct Rule {
pub(super) pattern: Pattern,
pub(super) body: Option<Block>,
}
#[derive(Debug, Clone, Default)]
pub(super) struct Func {
pub(super) name: String,
pub(super) params: Vec<String>,
pub(super) body: Block,
pub(super) array_params: Vec<bool>,
pub(super) defined: bool,
}
#[derive(Debug, Clone)]
pub(super) struct Source {
pub(super) name: String,
pub(super) start: usize,
}
#[derive(Debug, Clone, Default)]
pub(super) struct Program {
pub(super) begin: Vec<Block>,
pub(super) end: Vec<Block>,
pub(super) beginfile: Vec<Block>,
pub(super) endfile: Vec<Block>,
pub(super) rules: Vec<Rule>,
pub(super) funcs: Vec<Func>,
pub(super) globals: Vec<String>,
pub(super) regexes: Vec<String>,
pub(super) locs: Vec<(String, u32)>,
pub(super) ranges: usize,
}
pub(super) mod special {
pub(crate) const NAMES: &[&str] = &[
"NR",
"NF",
"FNR",
"FS",
"OFS",
"ORS",
"RS",
"FILENAME",
"SUBSEP",
"RSTART",
"RLENGTH",
"CONVFMT",
"OFMT",
"ENVIRON",
"ARGC",
"ARGV",
"RT",
"IGNORECASE",
"FIELDWIDTHS",
"FPAT",
"PROCINFO",
"ERRNO",
"SYMTAB",
];
pub(crate) const NR: u32 = 0;
pub(crate) const NF: u32 = 1;
pub(crate) const FNR: u32 = 2;
pub(crate) const FS: u32 = 3;
pub(crate) const OFS: u32 = 4;
pub(crate) const ORS: u32 = 5;
pub(crate) const RS: u32 = 6;
pub(crate) const FILENAME: u32 = 7;
pub(crate) const SUBSEP: u32 = 8;
pub(crate) const RSTART: u32 = 9;
pub(crate) const RLENGTH: u32 = 10;
pub(crate) const CONVFMT: u32 = 11;
pub(crate) const OFMT: u32 = 12;
pub(crate) const ENVIRON: u32 = 13;
pub(crate) const ARGC: u32 = 14;
pub(crate) const ARGV: u32 = 15;
pub(crate) const RT: u32 = 16;
pub(crate) const IGNORECASE: u32 = 17;
pub(crate) const FIELDWIDTHS: u32 = 18;
pub(crate) const FPAT: u32 = 19;
pub(crate) const PROCINFO: u32 = 20;
pub(crate) const ERRNO: u32 = 21;
pub(crate) const SYMTAB: u32 = 22;
pub(crate) const COUNT: u32 = 23;
}