use std::fmt;
pub mod g;
pub mod walk;
#[derive(Clone, Debug, PartialEq)]
pub enum Stmt {
Block(Vec<Stmt>),
Expr(Expr),
If(Expr, Box<Stmt>, Option<Box<Stmt>>),
Return(Option<Expr>),
Var(String, Option<Expr>),
While(Expr, Box<Stmt>),
}
#[derive(Clone, Debug, PartialEq)]
pub enum Expr {
Array(Vec<Expr>),
Assign(String, Box<Expr>),
Binary(BinaryOperator, Box<Expr>, Box<Expr>),
Bool(bool),
Call(Box<Expr>, Vec<Expr>),
Function(Vec<String>, Vec<Stmt>),
Member(Box<Expr>, Box<Expr>),
Null,
Number(f64),
Object(Vec<(String, Expr)>),
String(String),
This,
Unary(UnaryOperator, Box<Expr>),
Undefined,
Var(String),
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum UnaryOperator {
Add,
BitwiseNot,
Delete,
Not,
Sub,
Typeof,
Void,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BinaryOperator {
Add,
And,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
Div,
Eq,
Eqq,
Gt,
Gte,
In,
InstanceOf,
Lt,
Lte,
Mod,
Mul,
NotEq,
NotEqq,
Or,
Shl,
Shr,
Sub,
UnsignedShr,
}
impl fmt::Display for Stmt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Stmt::*;
match self {
Block(stmts) => {
write!(f, "{{")?;
for stmt in stmts {
stmt.fmt(f)?;
}
write!(f, "}}")
}
Expr(expr) => {
expr.fmt(f)?;
write!(f, ";")
}
If(expr, then, else_) => {
write!(f, "if({}){}", expr, then)?;
if let Some(else_) = else_ {
write!(f, "else{}", else_)?;
}
Ok(())
}
Return(Some(expr)) => write!(f, "return {};", expr),
Return(None) => write!(f, "return;"),
Var(name, expr) => match expr {
Some(expr) => write!(f, "var {}={};", name, expr),
None => write!(f, "var {};", name),
},
While(expr, stmt) => write!(f, "while({}){{{}}}", expr, stmt),
}
}
}
impl fmt::Display for Expr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Expr::*;
match self {
Array(exprs) => {
write!(f, "[")?;
for (i, expr) in exprs.iter().enumerate() {
if i > 0 {
write!(f, ",")?;
}
write!(f, "{}", expr)?;
}
write!(f, "]")
}
Assign(name, expr) => write!(f, "{}={}", name, expr),
Binary(op, left, right) => write!(f, "({}{}{})", left, op, right),
Bool(bool) => write!(f, "{}", bool),
Call(func, args) => {
write!(f, "{}(", func)?;
for (i, arg) in args.iter().enumerate() {
if i > 0 {
write!(f, ",")?;
}
write!(f, "{}", arg)?;
}
write!(f, ")")
}
Function(params, body) => {
write!(f, "function(")?;
for (i, param) in params.iter().enumerate() {
if i > 0 {
write!(f, ",")?;
}
write!(f, "{}", param)?;
}
write!(f, "){{")?;
for stmt in body {
write!(f, "{}", stmt)?;
}
write!(f, "}}")
}
Member(expr, field) => match field.as_ref() {
String(string) if is_identifier(string) => write!(f, "{}.{}", expr, string),
_ => write!(f, "{}[{}]", expr, field),
},
Null => write!(f, "null"),
Number(f64) => write!(f, "{}", f64),
Object(kvs) => {
write!(f, "{{")?;
for (i, (k, v)) in kvs.iter().enumerate() {
if i > 0 {
write!(f, ",")?;
}
write!(f, "{:?}:{}", k, v)?;
}
write!(f, "}}")
}
String(string) => write!(f, "{:?}", string),
This => write!(f, "this"),
Unary(op, expr) => write!(f, "{}{}", op, expr),
Undefined => write!(f, "undefined"),
Var(name) => write!(f, "{}", name),
}
}
}
impl fmt::Display for UnaryOperator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use UnaryOperator::*;
write!(
f,
"{}",
match self {
Add => "+",
BitwiseNot => "~",
Delete => "delete ",
Not => "!",
Sub => "-",
Typeof => "typeof ",
Void => "void ",
}
)
}
}
impl fmt::Display for BinaryOperator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use BinaryOperator::*;
write!(
f,
"{}",
match self {
Add => "+",
And => "&&",
BitwiseAnd => "&",
BitwiseOr => "|",
BitwiseXor => "^",
Div => "/",
Eq => "==",
Eqq => "===",
Gt => ">",
Gte => ">=",
In => " in ",
InstanceOf => " instanceof ",
Lt => "<",
Lte => "<=",
Mod => "%",
Mul => "*",
NotEq => "!=",
NotEqq => "!==",
Or => "||",
Shl => "<<",
Shr => ">>",
Sub => "-",
UnsignedShr => ">>>",
}
)
}
}
fn is_identifier(str: &str) -> bool {
str.chars().enumerate().all(|(index, ch)| match ch {
'a'...'z' | 'A'...'Z' | '$' | '_' => true,
'0'...'9' => index > 0,
_ => false,
})
}