analisar 0.4.0

A Lua parser for Rust
Documentation
use bstr::BStr;
use std::borrow::Cow;

#[derive(Debug, PartialEq)]
pub struct Block<'a>(pub Vec<Statement<'a>>);
impl<'a> Block<'a> {
    pub fn empty() -> Self {
        Self(Vec::new())
    }
}

#[derive(Debug, PartialEq)]
pub enum Statement<'a> {
    Empty,
    Expression(Expression<'a>),
    Assignment {
        local: bool,
        targets: Vec<Expression<'a>>,
        values: Vec<Expression<'a>>,
    },
    Label(Name<'a>),
    Break,
    GoTo(Name<'a>),
    Do {
        block: Block<'a>,
    },
    While {
        exp: Expression<'a>,
        block: Block<'a>,
    },
    Repeat {
        block: Block<'a>,
        exp: Expression<'a>,
    },
    If(If<'a>),
    For(ForLoop<'a>),
    ForIn(ForInLoop<'a>),
    Function {
        local: bool,
        name: FuncName<'a>,
        body: FuncBody<'a>,
    },
    Return(RetStatement<'a>),
}

impl<'a> Statement<'a> {
    pub fn func_call(subject: Expression<'a>, args: Args<'a>) -> Self {
        Self::Expression(Expression::func_call(subject, args))
    }
    pub fn method_call(subject: Expression<'a>, args: Args<'a>) -> Self {
        Self::Expression(Expression::method_call(subject, args))
    }
}

#[derive(Debug, PartialEq)]
pub struct FunctionCall<'a> {
    pub prefix: Box<Expression<'a>>,
    pub args: Args<'a>,
    pub method: bool,
}

#[derive(Debug, PartialEq)]
pub enum Args<'a> {
    ExpList(Vec<Expression<'a>>),
    Table(Table<'a>),
    String(LiteralString<'a>),
}

impl<'a> Args<'a> {
    pub fn exp_list(exps: Vec<Expression<'a>>) -> Self {
        Self::ExpList(exps)
    }
    pub fn empty() -> Self {
        Self::ExpList(Vec::new())
    }
}

#[derive(Debug, PartialEq)]
pub struct FuncName<'a> {
    pub dot_separated: Vec<Name<'a>>,
    pub method: Option<Name<'a>>,
}

#[derive(Debug, PartialEq)]
pub struct If<'a> {
    pub test: Expression<'a>,
    pub block: Block<'a>,
    pub else_ifs: Vec<ElseIf<'a>>,
    pub catch_all: Option<Block<'a>>,
}

#[derive(Debug, PartialEq)]
pub struct ElseIf<'a> {
    pub test: Expression<'a>,
    pub block: Block<'a>,
}

#[derive(Debug, PartialEq)]
pub struct ForLoop<'a> {
    pub init_name: Name<'a>,
    pub init: Expression<'a>,
    pub limit: Expression<'a>,
    pub step: Option<Expression<'a>>,
    pub block: Block<'a>,
}

#[derive(Debug, PartialEq)]
pub struct ForInLoop<'a> {
    pub name_list: NameList<'a>,
    pub exp_list: Vec<Expression<'a>>,
    pub block: Block<'a>,
}

#[derive(Debug, PartialEq)]
pub struct RetStatement<'a>(pub Vec<Expression<'a>>);

#[derive(Debug, PartialEq)]
pub enum Expression<'a> {
    Nil,
    False,
    True,
    Numeral(Numeral<'a>),
    LiteralString(LiteralString<'a>),
    Name(Name<'a>),
    VarArgs,
    FunctionDef(FuncBody<'a>),
    TableCtor(Box<Table<'a>>),
    BinOp {
        left: Box<Expression<'a>>,
        op: BinaryOperator,
        right: Box<Expression<'a>>,
    },
    UnaryOp {
        op: UnaryOperator,
        exp: Box<Expression<'a>>,
    },
    FuncCall(FunctionCall<'a>),
    Suffixed(Box<Suffixed<'a>>),
}

impl<'a> Expression<'a> {
    pub fn string(s: &'a str) -> Self {
        let bs: &BStr = s.as_bytes().into();
        Self::LiteralString(LiteralString(Cow::Borrowed(bs)))
    }
    pub fn func_call(subject: Expression<'a>, args: Args<'a>) -> Self {
        Self::FuncCall(FunctionCall {
            prefix: Box::new(subject),
            args,
            method: false,
        })
    }
    pub fn method_call(subject: Expression<'a>, args: Args<'a>) -> Self {
        Self::FuncCall(FunctionCall {
            prefix: Box::new(subject),
            args,
            method: true,
        })
    }
    pub fn binary(left: Expression<'a>, op: BinaryOperator, right: Expression<'a>) -> Self {
        Self::BinOp {
            left: Box::new(left),
            op,
            right: Box::new(right),
        }
    }

    pub fn unary(op: UnaryOperator, exp: Expression<'a>) -> Self {
        Self::UnaryOp {
            op,
            exp: Box::new(exp),
        }
    }
    pub fn name_from(s: &'a str) -> Self {
        Self::Name(Name::new(Cow::Borrowed(s)))
    }
    pub fn numeral_from(s: &'a str) -> Self {
        Self::Numeral(Numeral(Cow::Borrowed(s)))
    }
}

#[derive(Debug, PartialEq)]
pub struct Suffixed<'a> {
    pub subject: Expression<'a>,
    pub property: Expression<'a>,
    pub computed: bool,
    pub method: bool,
}

#[derive(Debug, PartialEq)]
pub struct NameList<'a>(pub Vec<Name<'a>>);

#[derive(Debug, PartialEq)]
pub struct ParList<'a> {
    pub names: NameList<'a>,
    pub var_args: bool,
}
impl<'a> ParList<'a> {
    pub fn empty() -> Self {
        Self {
            names: NameList(Vec::new()),
            var_args: false,
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct LiteralString<'a>(pub Cow<'a, BStr>);

impl<'a> From<&'a str> for LiteralString<'a> {
    fn from(s: &'a str) -> Self {
        let b: &BStr = s.as_bytes().into();
        Self(Cow::Borrowed(b))
    }
}
#[derive(Debug, PartialEq)]
pub struct Numeral<'a>(pub Cow<'a, str>);

#[derive(Debug, PartialEq)]
pub struct FuncBody<'a> {
    pub par_list: ParList<'a>,
    pub block: Block<'a>,
}

#[derive(Debug, PartialEq)]
pub struct Table<'a> {
    pub field_list: Vec<Field<'a>>,
}

#[derive(Debug, PartialEq)]
pub enum Field<'a> {
    Record {
        name: Expression<'a>,
        value: Expression<'a>,
    },
    List(Expression<'a>),
}

#[derive(Debug, PartialEq)]
pub struct Name<'a> {
    pub name: Cow<'a, str>,
    pub attr: Option<Cow<'a, str>>,
}

impl<'a> Name<'a> {
    pub fn new(name: Cow<'a, str>) -> Self {
        Self { name, attr: None }
    }

    pub fn new_with_attr(name: Cow<'a, str>, attr: Cow<'a, str>) -> Self {
        Self {
            name,
            attr: Some(attr),
        }
    }
}

impl<'a> From<&'a str> for Name<'a> {
    fn from(s: &'a str) -> Self {
        Self::new(Cow::Borrowed(s))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOperator {
    Add,
    Subtract,
    Multiply,
    Divide,
    FloorDivide,
    Power,
    Modulo,
    BitwiseAnd,
    BitwiseXor,
    BitwiseOr,
    RightShift,
    LeftShift,
    Concatenate,
    GreaterThan,
    GreaterThanEqual,
    LessThan,
    LessThanEqual,
    Equal,
    NotEqual,
    And,
    Or,
}

impl BinaryOperator {
    pub fn priority(self) -> (u8, u8) {
        match self {
            Self::Power => (14, 13),
            Self::Multiply | Self::Modulo | Self::Divide | Self::FloorDivide => (11, 11),
            Self::Add | Self::Subtract => (10, 10),
            Self::Concatenate => (9, 8),
            Self::RightShift | Self::LeftShift => (7, 7),
            Self::BitwiseAnd => (6, 6),
            Self::BitwiseXor => (5, 5),
            Self::BitwiseOr => (4, 4),
            Self::GreaterThan
            | Self::GreaterThanEqual
            | Self::LessThan
            | Self::LessThanEqual
            | Self::Equal
            | Self::NotEqual => (3, 3),
            Self::And => (2, 2),
            Self::Or => (1, 1),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOperator {
    Negate,
    Not,
    Length,
    BitwiseNot,
}