use crate::error::SourceLocation;
#[derive(Debug, Clone)]
pub struct Program {
pub rules: Vec<Rule>,
pub functions: Vec<FunctionDef>,
}
impl Program {
pub fn new() -> Self {
Self {
rules: Vec::new(),
functions: Vec::new(),
}
}
}
impl Default for Program {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct Rule {
pub pattern: Option<Pattern>,
pub action: Option<Block>,
pub location: SourceLocation,
}
#[derive(Debug, Clone)]
pub enum Pattern {
Begin,
End,
BeginFile,
EndFile,
Expr(Expr),
Regex(String),
Range {
start: Box<Pattern>,
end: Box<Pattern>,
},
And(Box<Pattern>, Box<Pattern>),
Or(Box<Pattern>, Box<Pattern>),
Not(Box<Pattern>),
}
#[derive(Debug, Clone)]
pub struct FunctionDef {
pub name: String,
pub params: Vec<String>,
pub body: Block,
pub location: SourceLocation,
}
#[derive(Debug, Clone)]
pub struct Block {
pub statements: Vec<Stmt>,
pub location: SourceLocation,
}
impl Block {
pub fn new(statements: Vec<Stmt>, location: SourceLocation) -> Self {
Self {
statements,
location,
}
}
pub fn empty(location: SourceLocation) -> Self {
Self {
statements: Vec::new(),
location,
}
}
}
#[derive(Debug, Clone)]
pub enum Stmt {
Expr(Expr),
Print {
args: Vec<Expr>,
output: Option<OutputRedirect>,
location: SourceLocation,
},
Printf {
format: Expr,
args: Vec<Expr>,
output: Option<OutputRedirect>,
location: SourceLocation,
},
If {
condition: Expr,
then_branch: Box<Stmt>,
else_branch: Option<Box<Stmt>>,
location: SourceLocation,
},
While {
condition: Expr,
body: Box<Stmt>,
location: SourceLocation,
},
DoWhile {
body: Box<Stmt>,
condition: Expr,
location: SourceLocation,
},
For {
init: Option<Box<Stmt>>,
condition: Option<Expr>,
update: Option<Expr>,
body: Box<Stmt>,
location: SourceLocation,
},
ForIn {
var: String,
array: String,
body: Box<Stmt>,
location: SourceLocation,
},
Block(Block),
Break { location: SourceLocation },
Continue { location: SourceLocation },
Next { location: SourceLocation },
Nextfile { location: SourceLocation },
Exit {
code: Option<Expr>,
location: SourceLocation,
},
Return {
value: Option<Expr>,
location: SourceLocation,
},
Delete {
array: String,
index: Vec<Expr>,
location: SourceLocation,
},
Empty,
}
#[derive(Debug, Clone)]
pub enum OutputRedirect {
Truncate(Expr),
Append(Expr),
Pipe(Expr),
}
#[derive(Debug, Clone)]
pub enum GetlineInput {
File(Box<Expr>),
Pipe(Box<Expr>),
}
#[derive(Debug, Clone)]
pub enum Expr {
Number(f64, SourceLocation),
String(String, SourceLocation),
Regex(String, SourceLocation),
Var(String, SourceLocation),
Field(Box<Expr>, SourceLocation),
ArrayAccess {
array: String,
indices: Vec<Expr>,
location: SourceLocation,
},
Binary {
left: Box<Expr>,
op: BinaryOp,
right: Box<Expr>,
location: SourceLocation,
},
Unary {
op: UnaryOp,
operand: Box<Expr>,
location: SourceLocation,
},
Assign {
target: Box<Expr>,
op: AssignOp,
value: Box<Expr>,
location: SourceLocation,
},
PreIncrement(Box<Expr>, SourceLocation),
PreDecrement(Box<Expr>, SourceLocation),
PostIncrement(Box<Expr>, SourceLocation),
PostDecrement(Box<Expr>, SourceLocation),
Ternary {
condition: Box<Expr>,
then_expr: Box<Expr>,
else_expr: Box<Expr>,
location: SourceLocation,
},
Call {
name: String,
args: Vec<Expr>,
location: SourceLocation,
},
InArray {
key: Vec<Expr>,
array: String,
location: SourceLocation,
},
Match {
expr: Box<Expr>,
pattern: Box<Expr>,
negated: bool,
location: SourceLocation,
},
Getline {
var: Option<Box<Expr>>,
input: Option<GetlineInput>,
location: SourceLocation,
},
Group(Box<Expr>, SourceLocation),
}
impl Expr {
pub fn location(&self) -> SourceLocation {
match self {
Expr::Number(_, loc)
| Expr::String(_, loc)
| Expr::Regex(_, loc)
| Expr::Var(_, loc)
| Expr::Field(_, loc)
| Expr::ArrayAccess { location: loc, .. }
| Expr::Binary { location: loc, .. }
| Expr::Unary { location: loc, .. }
| Expr::Assign { location: loc, .. }
| Expr::PreIncrement(_, loc)
| Expr::PreDecrement(_, loc)
| Expr::PostIncrement(_, loc)
| Expr::PostDecrement(_, loc)
| Expr::Ternary { location: loc, .. }
| Expr::Call { location: loc, .. }
| Expr::InArray { location: loc, .. }
| Expr::Match { location: loc, .. }
| Expr::Getline { location: loc, .. }
| Expr::Group(_, loc) => *loc,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Mod,
Pow,
Lt,
Le,
Gt,
Ge,
Eq,
Ne,
And,
Or,
Concat,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Neg, Pos, Not, }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AssignOp {
Assign, AddAssign, SubAssign, MulAssign, DivAssign, ModAssign, PowAssign, }