use crate::pat::Pat;
use crate::{Class, Function, FunctionArg, FunctionBody, Identifier};
#[derive(PartialEq, Debug, Clone)]
pub enum Expr {
Array(ArrayExpr),
ArrowFunction(ArrowFunctionExpr),
ArrowParamPlaceHolder(Vec<FunctionArg>, bool),
Assignment(AssignmentExpr),
Await(Box<Expr>),
Binary(BinaryExpr),
Class(Class),
Call(CallExpr),
Conditional(ConditionalExpr),
Function(Function),
Ident(Identifier),
Literal(Literal),
Logical(LogicalExpr),
Member(MemberExpr),
MetaProperty(MetaProperty),
New(NewExpr),
Object(ObjectExpr),
Sequence(SequenceExpr),
Spread(Box<Expr>),
Super,
TaggedTemplate(TaggedTemplateExpr),
This,
Unary(UnaryExpr),
Update(UpdateExpr),
Yield(YieldExpr),
}
impl Expr {
pub fn ident(name: &str) -> Self {
Expr::Ident(name.to_string())
}
pub fn string(val: &str) -> Self {
Expr::Literal(Literal::string(val))
}
pub fn number(val: &str) -> Self {
Expr::Literal(Literal::number(val))
}
pub fn boolean(val: bool) -> Self {
Expr::Literal(Literal::Boolean(val))
}
pub fn regex(pattern: &str, flags: &str) -> Self {
Expr::Literal(Literal::regex(pattern, flags))
}
pub fn binary(left: Expr, operator: BinaryOperator, right: Expr) -> Self {
Expr::Binary(BinaryExpr::new(left, operator, right))
}
pub fn call(callee: Expr, arguments: Vec<Expr>) -> Self {
Expr::Call(CallExpr::new(callee, arguments))
}
pub fn member(object: Expr, property: Expr, computed: bool) -> Self {
Expr::Member(MemberExpr::new(object, property, computed))
}
pub fn logical(left: Expr, operator: LogicalOperator, right: Expr) -> Self {
Expr::Logical(LogicalExpr::new(operator, left, right))
}
pub fn function(
id: Option<String>,
params: Vec<FunctionArg>,
body: FunctionBody,
generator: bool,
is_async: bool,
) -> Self {
Expr::Function(Function {
id,
params,
body,
generator,
is_async,
})
}
pub fn yield_expr(arg: Option<Expr>, delegate: bool) -> Self {
Expr::Yield(YieldExpr::new(arg, delegate))
}
pub fn yield_with_arg(arg: Expr, delegate: bool) -> Self {
Expr::Yield(YieldExpr::new(Some(arg), delegate))
}
pub fn empty_yield(delegate: bool) -> Self {
Expr::Yield(YieldExpr::new(None, delegate))
}
}
pub type ArrayExpr = Vec<Option<Expr>>;
pub type ObjectExpr = Vec<ObjectProperty>;
#[derive(PartialEq, Debug, Clone)]
pub enum ObjectProperty {
Property(Property),
Spread(Box<Expr>),
}
impl ObjectProperty {
pub fn number(id: &str, value: &str) -> Self {
let id = PropertyKey::Expr(
Expr::ident(id)
);
let init = PropertyValue::Expr(Expr::Literal(Literal::Number(String::from(value))));
ObjectProperty::Property(Property::new(id, init, PropertyKind::Init, false, false, false, false))
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct Property {
pub key: PropertyKey,
pub value: PropertyValue,
pub kind: PropertyKind,
pub method: bool,
pub computed: bool,
pub short_hand: bool,
pub is_static: bool,
}
impl Property {
pub fn new(key: PropertyKey, value: PropertyValue, kind: PropertyKind, method: bool, computed: bool, short_hand: bool, is_static: bool) -> Self {
Self {
key,
value,
kind,
method,
computed,
short_hand,
is_static,
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub enum PropertyKey {
Literal(Literal),
Expr(Expr),
Pat(Pat),
}
#[derive(PartialEq, Debug, Clone)]
pub enum PropertyValue {
Expr(Expr),
Pat(Pat),
None,
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum PropertyKind {
Init,
Get,
Set,
Ctor,
Method,
}
#[derive(PartialEq, Debug, Clone)]
pub struct UnaryExpr {
pub operator: UnaryOperator,
pub prefix: bool,
pub argument: Box<Expr>,
}
impl UnaryExpr {
pub fn new(operator: UnaryOperator, prefix: bool, argument: Expr) -> Self {
Self {
operator,
prefix,
argument: Box::new(argument),
}
}
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum UnaryOperator {
Minus,
Plus,
Not,
Tilde,
TypeOf,
Void,
Delete,
}
#[derive(PartialEq, Debug, Clone)]
pub struct UpdateExpr {
pub operator: UpdateOperator,
pub argument: Box<Expr>,
pub prefix: bool,
}
impl UpdateExpr {
pub fn new(operator: UpdateOperator, arg: Expr, prefix: bool) -> Self {
Self {
operator,
argument: Box::new(arg),
prefix,
}
}
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum UpdateOperator {
Increment,
Decrement,
}
#[derive(PartialEq, Debug, Clone)]
pub struct BinaryExpr {
pub operator: BinaryOperator,
pub left: Box<Expr>,
pub right: Box<Expr>,
}
impl BinaryExpr {
pub fn new(left: Expr, operator: BinaryOperator, right: Expr) -> Self {
Self {
operator,
left: Box::new(left),
right: Box::new(right),
}
}
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum BinaryOperator {
Equal,
NotEqual,
StrictEqual,
StrictNotEqual,
LessThan,
GreaterThan,
LessThanEqual,
GreaterThanEqual,
LeftShift,
RightShift,
UnsignedRightShift,
Plus,
Minus,
Times,
Over,
Mod,
Or,
XOr,
And,
In,
InstanceOf,
PowerOf,
}
#[derive(PartialEq, Debug, Clone)]
pub struct AssignmentExpr {
pub operator: AssignmentOperator,
pub left: AssignmentLeft,
pub right: Box<Expr>,
}
impl AssignmentExpr {
pub fn new(operator: AssignmentOperator, left: AssignmentLeft, right: Expr) -> Self {
AssignmentExpr {
operator,
left,
right: Box::new(right),
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub enum AssignmentLeft {
Pat(Pat),
Expr(Box<Expr>),
}
impl AssignmentLeft {
pub fn expr(expr: Expr) -> Self {
AssignmentLeft::Expr(Box::new(expr))
}
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum AssignmentOperator {
Equal,
PlusEqual,
MinusEqual,
TimesEqual,
DivEqual,
ModEqual,
LeftShiftEqual,
RightShiftEqual,
UnsignedRightShiftEqual,
OrEqual,
XOrEqual,
AndEqual,
PowerOfEqual,
}
#[derive(PartialEq, Debug, Clone)]
pub struct LogicalExpr {
pub operator: LogicalOperator,
pub left: Box<Expr>,
pub right: Box<Expr>,
}
impl LogicalExpr {
pub fn new(operator: LogicalOperator, left: Expr, right: Expr) -> Self {
Self {
operator,
left: Box::new(left),
right: Box::new(right),
}
}
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum LogicalOperator {
Or,
And,
}
#[derive(PartialEq, Debug, Clone)]
pub struct MemberExpr {
pub object: Box<Expr>,
pub property: Box<Expr>,
pub computed: bool,
}
impl MemberExpr {
pub fn new(obj: Expr, prop: Expr, computed: bool) -> Self {
MemberExpr {
object: Box::new(obj),
property: Box::new(prop),
computed,
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct ConditionalExpr {
pub test: Box<Expr>,
pub alternate: Box<Expr>,
pub consequent: Box<Expr>,
}
impl ConditionalExpr {
pub fn new(test: Expr, alternate: Expr, consequent: Expr) -> Self {
ConditionalExpr {
test: Box::new(test),
alternate: Box::new(alternate),
consequent: Box::new(consequent),
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct CallExpr {
pub callee: Box<Expr>,
pub arguments: Vec<Expr>,
}
impl CallExpr {
pub fn new(callee: Expr, arguments: Vec<Expr>) -> Self {
CallExpr {
callee: Box::new(callee),
arguments
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct NewExpr {
pub callee: Box<Expr>,
pub arguments: Vec<Expr>,
}
impl NewExpr {
pub fn new(callee: Expr, arguments: Vec<Expr>) -> Self {
NewExpr {
callee: Box::new(callee),
arguments,
}
}
}
pub type SequenceExpr = Vec<Expr>;
#[derive(PartialEq, Debug, Clone)]
pub struct ArrowFunctionExpr {
pub id: Option<String>,
pub params: Vec<FunctionArg>,
pub body: ArrowFunctionBody,
pub expression: bool,
pub generator: bool,
pub is_async: bool,
}
impl ArrowFunctionExpr {
pub fn new(id: Option<String>, params: Vec<FunctionArg>, body: ArrowFunctionBody, expression: bool, generator: bool, is_async: bool) -> Self {
ArrowFunctionExpr {
id,
params,
body,
expression,
generator,
is_async,
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub enum ArrowFunctionBody {
FunctionBody(FunctionBody),
Expr(Box<Expr>),
}
impl ArrowFunctionBody {
pub fn function_body(bod: FunctionBody) -> Self {
ArrowFunctionBody::FunctionBody(bod)
}
pub fn expr(expr: Expr) -> Self {
ArrowFunctionBody::Expr(Box::new(expr))
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct YieldExpr {
pub argument: Option<Box<Expr>>,
pub delegate: bool,
}
impl YieldExpr {
pub fn new(argument: Option<Expr>, delegate: bool) -> YieldExpr {
YieldExpr {
argument: argument.map(|a| Box::new(a)),
delegate
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct TaggedTemplateExpr {
pub tag: Box<Expr>,
pub quasi: TemplateLiteral,
}
impl TaggedTemplateExpr {
pub fn new(tag: Expr, quasi: TemplateLiteral) -> Self {
TaggedTemplateExpr {
tag: Box::new(tag),
quasi,
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct TemplateLiteral {
pub quasis: Vec<TemplateElement>,
pub expressions: Vec<Expr>,
}
impl TemplateLiteral {
pub fn new(quasis: Vec<TemplateElement>, expressions: Vec<Expr>) -> Self {
TemplateLiteral {
quasis,
expressions,
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct TemplateElement {
pub tail: bool,
pub cooked: String,
pub raw: String,
}
impl TemplateElement {
pub fn new(tail: bool, cooked: String, raw: String) -> Self {
TemplateElement {
tail,
cooked,
raw,
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct MetaProperty {
pub meta: Identifier,
pub property: Identifier,
}
impl MetaProperty {
pub fn new(meta: Identifier, property: Identifier) -> Self {
MetaProperty {
meta,
property,
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub enum Literal {
Null,
String(String),
Number(String),
Boolean(bool),
RegEx(RegEx),
Template(TemplateLiteral),
}
impl Literal {
pub fn string(string: &str) -> Self {
Literal::String(string.to_string())
}
pub fn number(num: &str) -> Self {
Literal::Number(num.to_string())
}
pub fn regex(pattern: &str, flags: &str) -> Self {
let inner = RegEx::new(pattern, flags);
Literal::RegEx(inner)
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct RegEx {
pub pattern: String,
pub flags: String,
}
impl RegEx {
pub fn new(body: &str, flags: &str) -> Self {
RegEx {
pattern: String::from(body),
flags: String::from(flags),
}
}
}