use crate::lexer::span::{ Loc, Span, LineColumn, };
use crate::lexer::token::{
Identifier, LiteralNull, LiteralBoolean, LiteralString, LiteralNumeric,
LiteralRegularExpression,
Punctuator, Keyword, Comment,
};
use crate::lexer::operator::{ PrefixOperator, InfixOperator, PostfixOperator, AssignmentOperator, };
use crate::ast::numberic::{ Float, Numberic, };
use crate::ast::class::ClassExpression;
use crate::ast::function::{ FunctionExpression, ArrowFunctionExpression, };
use crate::ast::jsx::{ JSXFragment, JSXElement, };
use crate::ast::pattern::{
ObjectLiteral, ArrayLiteral, BindingPattern, AssignmentPattern,
ObjectBindingPattern, ArrayBindingPattern,
ObjectAssignmentPattern, ArrayAssignmentPattern,
};
use std::fmt;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Direction {
LeftToRight,
RightToLeft,
}
impl Default for Direction {
fn default() -> Self {
Direction::LeftToRight
}
}
#[derive(PartialEq, Clone, Copy)]
pub enum Expression<'ast> {
This(&'ast Keyword),
Spread(&'ast SpreadExpression<'ast>),
Super(&'ast Keyword),
Identifier(&'ast Identifier<'ast>),
Null(&'ast LiteralNull),
Boolean(&'ast LiteralBoolean),
String(&'ast LiteralString<'ast>),
Numeric(&'ast LiteralNumeric<'ast>),
RegularExpression(&'ast LiteralRegularExpression<'ast>),
Template(&'ast LiteralTemplateExpression<'ast>),
ArrayLiteral(&'ast ArrayLiteral<'ast>),
ObjectLiteral(&'ast ObjectLiteral<'ast>),
Function(&'ast FunctionExpression<'ast>),
ArrowFunction(&'ast ArrowFunctionExpression<'ast>),
Class(&'ast ClassExpression<'ast>),
Parenthesized(&'ast ParenthesizedExpression<'ast>),
Member(&'ast MemberExpression<'ast>),
TaggedTemplate(&'ast TaggedTemplateExpression<'ast>),
NewTarget(&'ast NewTargetExpression),
Call(&'ast CallExpression<'ast>),
New(&'ast NewExpression<'ast>),
Prefix(&'ast PrefixExpression<'ast>),
Infix(&'ast InfixExpression<'ast>),
Postfix(&'ast PostfixExpression<'ast>),
Assignment(&'ast AssignmentExpression<'ast>),
Conditional(&'ast ConditionalExpression<'ast>),
Yield(&'ast YieldExpression<'ast>),
Comma(&'ast CommaExpression<'ast>),
AssignmentPattern(&'ast AssignmentPattern<'ast>),
BindingPattern(&'ast BindingPattern<'ast>),
JSXFragment(&'ast JSXFragment<'ast>),
JSXElement(&'ast JSXElement<'ast>),
}
impl<'ast> fmt::Debug for Expression<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Expression::This(inner) => fmt::Debug::fmt(inner, f),
Expression::Spread(inner) => fmt::Debug::fmt(inner, f),
Expression::Super(inner) => fmt::Debug::fmt(inner, f),
Expression::Identifier(inner) => fmt::Debug::fmt(inner, f),
Expression::Null(inner) => fmt::Debug::fmt(inner, f),
Expression::Boolean(inner) => fmt::Debug::fmt(inner, f),
Expression::String(inner) => fmt::Debug::fmt(inner, f),
Expression::Numeric(inner) => fmt::Debug::fmt(inner, f),
Expression::RegularExpression(inner) => fmt::Debug::fmt(inner, f),
Expression::Template(inner) => fmt::Debug::fmt(inner, f),
Expression::ArrayLiteral(inner) => fmt::Debug::fmt(inner, f),
Expression::ObjectLiteral(inner) => fmt::Debug::fmt(inner, f),
Expression::Function(inner) => fmt::Debug::fmt(inner, f),
Expression::ArrowFunction(inner) => fmt::Debug::fmt(inner, f),
Expression::Class(inner) => fmt::Debug::fmt(inner, f),
Expression::Parenthesized(inner) => fmt::Debug::fmt(inner, f),
Expression::Member(inner) => fmt::Debug::fmt(inner, f),
Expression::TaggedTemplate(inner) => fmt::Debug::fmt(inner, f),
Expression::NewTarget(inner) => fmt::Debug::fmt(inner, f),
Expression::Call(inner) => fmt::Debug::fmt(inner, f),
Expression::New(inner) => fmt::Debug::fmt(inner, f),
Expression::Prefix(inner) => fmt::Debug::fmt(inner, f),
Expression::Infix(inner) => fmt::Debug::fmt(inner, f),
Expression::Postfix(inner) => fmt::Debug::fmt(inner, f),
Expression::Assignment(inner) => fmt::Debug::fmt(inner, f),
Expression::Conditional(inner) => fmt::Debug::fmt(inner, f),
Expression::Yield(inner) => fmt::Debug::fmt(inner, f),
Expression::Comma(inner) => fmt::Debug::fmt(inner, f),
Expression::AssignmentPattern(inner) => fmt::Debug::fmt(inner, f),
Expression::BindingPattern(inner) => fmt::Debug::fmt(inner, f),
Expression::JSXFragment(inner) => fmt::Debug::fmt(inner, f),
Expression::JSXElement(inner) => fmt::Debug::fmt(inner, f),
}
}
}
impl<'ast> Expression<'ast> {
pub fn loc(&self) -> Loc {
match *self {
Expression::This(inner) => inner.loc,
Expression::Spread(inner) => inner.loc,
Expression::Super(inner) => inner.loc,
Expression::Identifier(inner) => inner.loc,
Expression::Null(inner) => inner.loc,
Expression::Boolean(inner) => inner.loc,
Expression::String(inner) => inner.loc,
Expression::Numeric(inner) => inner.loc,
Expression::RegularExpression(inner) => inner.loc,
Expression::Template(inner) => inner.loc,
Expression::ArrayLiteral(inner) => inner.loc,
Expression::ObjectLiteral(inner) => inner.loc,
Expression::Function(inner) => inner.loc,
Expression::ArrowFunction(inner) => inner.loc,
Expression::Class(inner) => inner.loc,
Expression::Parenthesized(inner) => inner.loc,
Expression::Member(inner) => inner.loc,
Expression::TaggedTemplate(inner) => inner.loc,
Expression::NewTarget(inner) => inner.loc,
Expression::Call(inner) => inner.loc,
Expression::New(inner) => inner.loc,
Expression::Prefix(inner) => inner.loc,
Expression::Infix(inner) => inner.loc,
Expression::Postfix(inner) => inner.loc,
Expression::Assignment(inner) => inner.loc,
Expression::Conditional(inner) => inner.loc,
Expression::Yield(inner) => inner.loc,
Expression::Comma(inner) => inner.loc,
Expression::AssignmentPattern(inner) => inner.loc(),
Expression::BindingPattern(inner) => inner.loc(),
Expression::JSXFragment(inner) => inner.loc(),
Expression::JSXElement(inner) => inner.loc(),
}
}
pub fn span(&self) -> Span {
match *self {
Expression::This(inner) => inner.span,
Expression::Spread(inner) => inner.span,
Expression::Super(inner) => inner.span,
Expression::Identifier(inner) => inner.span,
Expression::Null(inner) => inner.span,
Expression::Boolean(inner) => inner.span,
Expression::String(inner) => inner.span,
Expression::Numeric(inner) => inner.span,
Expression::RegularExpression(inner) => inner.span,
Expression::Template(inner) => inner.span,
Expression::ArrayLiteral(inner) => inner.span,
Expression::ObjectLiteral(inner) => inner.span,
Expression::Function(inner) => inner.span,
Expression::ArrowFunction(inner) => inner.span,
Expression::Class(inner) => inner.span,
Expression::Parenthesized(inner) => inner.span,
Expression::Member(inner) => inner.span,
Expression::TaggedTemplate(inner) => inner.span,
Expression::NewTarget(inner) => inner.span,
Expression::Call(inner) => inner.span,
Expression::New(inner) => inner.span,
Expression::Prefix(inner) => inner.span,
Expression::Infix(inner) => inner.span,
Expression::Postfix(inner) => inner.span,
Expression::Assignment(inner) => inner.span,
Expression::Conditional(inner) => inner.span,
Expression::Yield(inner) => inner.span,
Expression::Comma(inner) => inner.span,
Expression::AssignmentPattern(inner) => inner.span(),
Expression::BindingPattern(inner) => inner.span(),
Expression::JSXFragment(inner) => inner.span(),
Expression::JSXElement(inner) => inner.span(),
}
}
pub fn is_primitive_literal(&self) -> bool {
unimplemented!()
}
pub fn is_numeric_literal(&self) -> bool {
match *self {
Expression::Numeric(_) => true,
_ => false,
}
}
pub fn is_identifier(&self) -> bool {
match *self {
Expression::Identifier(_) => true,
_ => false,
}
}
pub fn is_prefix_increment(&self) -> bool {
match *self {
Expression::Prefix(inner) => inner.operator == PrefixOperator::Increment,
_ => false,
}
}
pub fn is_prefix_decrement(&self) -> bool {
match *self {
Expression::Prefix(inner) => inner.operator == PrefixOperator::Decrement,
_ => false,
}
}
pub fn is_postfix_increment(&self) -> bool {
match *self {
Expression::Postfix(inner) => inner.operator == PostfixOperator::Increment,
_ => false,
}
}
pub fn is_postfix_decrement(&self) -> bool {
match *self {
Expression::Postfix(inner) => inner.operator == PostfixOperator::Decrement,
_ => false,
}
}
pub fn is_member_expression(&self) -> bool {
match *self {
Expression::Member(_) => true,
_ => false,
}
}
pub fn is_comma_expression(&self) -> bool {
match *self {
Expression::Comma(_) => true,
_ => false,
}
}
pub fn is_parenthesized_expression(&self) -> bool {
match *self {
Expression::Parenthesized(_) => true,
_ => false,
}
}
pub fn is_call_expression(&self) -> bool {
match *self {
Expression::Call(_) => true,
_ => false,
}
}
pub fn is_function_expression(&self) -> bool {
match *self {
Expression::Function(_) => true,
_ => false,
}
}
pub fn is_arrow_function_expression(&self) -> bool {
match *self {
Expression::ArrowFunction(_) => true,
_ => false,
}
}
pub fn is_primary_expression(&self) -> bool {
unimplemented!()
}
pub fn is_left_hand_side_expression(&self) -> bool {
unimplemented!()
}
pub fn is_assignment_expression(&self) -> bool {
unimplemented!()
}
pub fn precedence(&self) -> i8 {
match *self {
Expression::This(inner) => -1,
Expression::Spread(inner) => 1,
Expression::Super(inner) => -1,
Expression::Identifier(inner) => -1,
Expression::Null(inner) => -1,
Expression::Boolean(inner) => -1,
Expression::String(inner) => -1,
Expression::Numeric(inner) => -1,
Expression::RegularExpression(inner) => -1,
Expression::Template(inner) => -1,
Expression::ArrayLiteral(inner) => -1,
Expression::ObjectLiteral(inner) => -1,
Expression::Function(inner) => -1,
Expression::ArrowFunction(inner) => -1,
Expression::Class(inner) => -1,
Expression::Parenthesized(inner) => 20,
Expression::Member(inner) => 19,
Expression::TaggedTemplate(inner) => 19,
Expression::NewTarget(inner) => -1,
Expression::Call(inner) => 19,
Expression::New(inner) => if inner.arguments.is_some() { 19 } else { 18 },
Expression::Prefix(inner) => 16,
Expression::Infix(inner) => inner.operator.precedence(),
Expression::Postfix(inner) => 17,
Expression::Assignment(inner) => 3,
Expression::Conditional(inner) => 4,
Expression::Yield(inner) => 2,
Expression::Comma(inner) => 0,
Expression::AssignmentPattern(inner) => -1,
Expression::BindingPattern(inner) => -1,
Expression::JSXFragment(inner) => -1,
Expression::JSXElement(inner) => -1,
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct SpreadExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub item: Expression<'ast>,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct LiteralTemplateExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub strings: &'ast [ LiteralString<'ast> ],
pub bounds: &'ast [ Expression<'ast> ],
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct ParenthesizedExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub items: &'ast [ Expression<'ast> ],
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct MemberExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub left: Expression<'ast>,
pub right: Expression<'ast>,
pub computed: bool,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct TaggedTemplateExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub tag: Expression<'ast>,
pub template: LiteralTemplateExpression<'ast>,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct NewTargetExpression {
pub loc: Loc,
pub span: Span,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct CallExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub callee: Expression<'ast>,
pub arguments: ParenthesizedExpression<'ast>,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct NewExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub callee: Expression<'ast>,
pub arguments: Option<ParenthesizedExpression<'ast>>,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct PrefixExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub operator: PrefixOperator,
pub operand: Expression<'ast>,
}
#[derive(PartialEq, Clone, Copy)]
pub struct InfixExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub left: Expression<'ast>,
pub operator: InfixOperator,
pub right: Expression<'ast>,
}
impl<'ast> fmt::Debug for InfixExpression<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("InfixExpression")
.field("left", &self.left)
.field("operator", &self.operator)
.field("right", &self.right)
.finish()
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct PostfixExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub operator: PostfixOperator,
pub operand: Expression<'ast>,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct ConditionalExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub condition: Expression<'ast>,
pub and_then: Expression<'ast>,
pub or_else: Expression<'ast>,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct YieldExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub star: bool,
pub item: Expression<'ast>,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct AssignmentExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub left: Expression<'ast>,
pub operator: AssignmentOperator,
pub right: Expression<'ast>,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct CommaExpression<'ast> {
pub loc: Loc,
pub span: Span,
pub items: &'ast [ Expression<'ast> ],
}