use pest::iterators::Pair;
use crate::{ccarp::error::{rule_err, rule_mismatch, safe_unwrap, CCErr, Result}, ccarp_rust::defs::sum};
use super::{decl::{InitialiserList, TypeName}, defs::{bin_ast, list_ast, Rule, AST}, tt::{Identifier, Literal}};
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum PrimaryExpr {
Literal(Literal), Ident(Identifier), Expr(Box<Expression>) }
impl AST for PrimaryExpr {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::primary_expr => {
let pair=safe_unwrap!(pair.into_inner().next(),"Primary Expression");
match pair.as_rule() {
Rule::tok_lit => Ok(Self::Literal(Literal::take(pair)?)), Rule::tok_ident => Ok(Self::Ident(Identifier::take(pair)?)), Rule::expr => Ok(Self::Expr(Box::new(Expression::take(pair)?))), _ => Err(rule_mismatch!(pair))
}
},
_ => Err(rule_mismatch!(pair,primary_expr))
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ArgumentExprList(pub Vec<AssignmentExpr>);
list_ast!(ArgumentExprList : AssignmentExpr where arg_expr_list => assign_expr);
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Postfix {
Brackets(Box<Expression>), Function(ArgumentExprList), Dot(Identifier), Arrow(Identifier), Inc, Dec, }
impl AST for Postfix {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::postfix => {
let mut inner=pair.into_inner();
let pair=safe_unwrap!(inner.next(),"Postfix Expression");
match pair.as_rule() {
Rule::expr => Ok(Self::Brackets(Box::new(Expression::take(pair)?))), Rule::op_parent => {
let pair=safe_unwrap!(inner.next(),"Open Parenthesis");
match pair.as_rule() {
Rule::cl_parent => Ok(Self::Function(ArgumentExprList(vec![]))), Rule::arg_expr_list => Ok(Self::Function(ArgumentExprList::take(pair)?)), _ => Err(rule_mismatch!(pair))
}
}
Rule::dot => {
let pair=safe_unwrap!(inner.next(),"Right-hand-side of Postfix Expression");
if matches!(pair.as_rule(),Rule::tok_ident) { Ok(Self::Dot(Identifier::take(pair)?)) } else { Err(rule_mismatch!(pair,tok_ident)) }
},
Rule::arrow => {
let pair=safe_unwrap!(inner.next(),"Right-hand-side of Postfix Expression");
if matches!(pair.as_rule(),Rule::tok_ident) { Ok(Self::Arrow(Identifier::take(pair)?)) } else { Err(rule_mismatch!(pair,tok_ident)) }
}
Rule::inc => Ok(Self::Inc), Rule::dec => Ok(Self::Dec), _ => Err(rule_mismatch!(pair))
}
},
_ => Err(rule_mismatch!(pair,postfix))
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum PostfixExpr {
Primary(Box<PrimaryExpr>,Vec<Postfix>), List(Box<TypeName>,Vec<InitialiserList>) }
impl AST for PostfixExpr {
fn take(pair: Pair<Rule>) -> Result<Self> {
sum!(PrimaryOrTy;PrimaryExpr;TypeName);
let mut postfix=vec![];
let mut init=vec![];
match pair.as_rule() {
Rule::postfix_expr => {
let mut inner=pair.into_inner();
let pair=safe_unwrap!(inner.next(),"Postfix Expression");
let primary_or_ty=
match pair.as_rule() {
Rule::primary_expr => PrimaryOrTy::A(PrimaryExpr::take(pair)?), Rule::type_name => PrimaryOrTy::B(TypeName::take(pair)?), _ => return Err(rule_mismatch!(pair))
};
for pair in inner {
match pair.as_rule() {
Rule::postfix => postfix.push(Postfix::take(pair)?), Rule::init_list => init.push(InitialiserList::take(pair)?), _ => return Err(rule_mismatch!(pair))
}
}
match primary_or_ty {
PrimaryOrTy::A(primary_expr) => Ok(Self::Primary(Box::new(primary_expr), postfix)),
PrimaryOrTy::B(type_name) => Ok(Self::List(Box::new(type_name), init)),
}
},
_ => Err(rule_mismatch!(pair,postfix_expr))
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum UnaryExpr {
Postfix(Box<PostfixExpr>),
Inc(Box<UnaryExpr>), Dec(Box<UnaryExpr>), Ref(Box<CastExpr>), Deref(Box<CastExpr>), Plus(Box<CastExpr>), Minus(Box<CastExpr>), Bnot(Box<CastExpr>), Not(Box<CastExpr>), Sizeof(Box<UnaryExpr>), SizeofType(Box<TypeName>) }
impl AST for UnaryExpr {
fn take(pair: Pair<Rule>) -> Result<Self> {
macro_rules! ret {
($i:ident, $ty:ty, $inner:expr, $e:expr) => {
Ok(Self::$i(Box::new(<$ty>::take(safe_unwrap!($inner.next(),$e))?)))
};
}
match pair.as_rule() {
Rule::unary_expr => {
let mut inner=pair.into_inner();
let pair=safe_unwrap!(inner.next(),"Unary Expression");
match pair.as_rule() {
Rule::postfix_expr => Ok(Self::Postfix(Box::new(PostfixExpr::take(pair)?))),
Rule::inc => ret!(Inc,Self,inner,"Unary Inc Expression"), Rule::dec => ret!(Dec,Self,inner,"Unary Dec Expression"), Rule::sizeof => {
let pair=safe_unwrap!(inner.next(),"Unary Sizeof Expression");
match pair.as_rule() {
Rule::unary_expr => Ok(Self::Sizeof(Box::new(Self::take(pair)?))), Rule::type_name => Ok(Self::SizeofType(Box::new(TypeName::take(pair)?))), _ => Err(rule_mismatch!(pair))
}
},
Rule::band => ret!(Ref,CastExpr,inner,"Unary Ref Expression"), Rule::mul => ret!(Deref,CastExpr,inner,"Unary Deref Expression"), Rule::plus => ret!(Plus,CastExpr,inner,"Unary Plus Expression"), Rule::minus => ret!(Minus,CastExpr,inner,"Unary Minus Expression"), Rule::bnot => ret!(Bnot,CastExpr,inner,"Unary Bnot Expression"), Rule::not => ret!(Not,CastExpr,inner,"Unary Not Expression"), _ => Err(rule_mismatch!(pair))
}
},
_ => Err(rule_mismatch!(pair,unary_expr))
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum CastExpr {
Unary(UnaryExpr),
Cast(Box<TypeName>,Box<CastExpr>) }
impl AST for CastExpr {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::cast_expr => {
let mut inner=pair.into_inner();
let pair=safe_unwrap!(inner.next(),"Cast Expression");
match pair.as_rule() {
Rule::unary_expr => Ok(Self::Unary(UnaryExpr::take(pair)?)), Rule::type_name => Ok(
Self::Cast(Box::new(TypeName::take(pair)?),
Box::new(Self::take(safe_unwrap!(inner.next(),"Cast Expression"))?))
), _ => Err(rule_mismatch!(pair))
}
},
_ => Err(rule_mismatch!(pair,cast_expr))
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct MulExpr(pub Box<CastExpr>,pub Vec<(MulOp,CastExpr)>);
bin_ast!(MulExpr : CastExpr where mul_expr => cast_expr, mul => MulOp::Mul, div => MulOp::Div, modulo => MulOp::Mod; if "MulExpr");
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
pub enum MulOp {
#[default]
Mul,
Div,
Mod
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct AddExpr(pub Box<MulExpr>,pub Vec<(AddOp,MulExpr)>);
bin_ast!(AddExpr : MulExpr where add_expr => mul_expr, plus => AddOp::Add, minus => AddOp::Sub; if "AddExpr");
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
pub enum AddOp {
#[default]
Add,
Sub
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ShiftExpr(pub Box<AddExpr>,pub Vec<(ShiftOp,AddExpr)>);
bin_ast!(ShiftExpr : AddExpr where shift_expr => add_expr, lshift => ShiftOp::LShift, rshift => ShiftOp::RShift; if "ShiftExpr");
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
pub enum ShiftOp {
#[default]
LShift,
RShift
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct RelExpr(pub Box<ShiftExpr>,pub Vec<(RelOp,ShiftExpr)>);
bin_ast!(RelExpr : ShiftExpr where rel_expr => shift_expr, gt => RelOp::Gt, lt => RelOp::Lt, gte => RelOp::Gte, lte => RelOp::Lte; if "RelExpr");
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
pub enum RelOp {
#[default]
Gt,
Lt,
Gte,
Lte
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct EqExpr(pub Box<RelExpr>,pub Vec<(EqOp,RelExpr)>);
bin_ast!(EqExpr : RelExpr where eq_expr => rel_expr, eq => EqOp::Eq, neq => EqOp::Neq; if "EqExpr");
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
pub enum EqOp {
#[default]
Eq,
Neq
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct AndExpr(pub Vec<EqExpr>);
list_ast!(AndExpr : EqExpr where and_expr => eq_expr);
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct XorExpr(pub Vec<AndExpr>);
list_ast!(XorExpr : AndExpr where xor_expr => and_expr);
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct OrExpr(pub Vec<XorExpr>);
list_ast!(OrExpr : XorExpr where or_expr => xor_expr);
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct LogAndExpr(pub Vec<OrExpr>);
list_ast!(LogAndExpr : OrExpr where log_and_expr => or_expr);
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct LogOrExpr(pub Vec<LogAndExpr>);
list_ast!(LogOrExpr : LogAndExpr where log_or_expr => log_and_expr);
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CondExpr(pub Vec<(LogOrExpr,Box<Expression>)>,pub Box<LogOrExpr>);
impl AST for CondExpr {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::cond_expr => {
let mut last=None;
let mut v=vec![];
for pair in pair.into_inner() {
match pair.as_rule() {
Rule::log_or_expr => last=Some(LogOrExpr::take(pair)?), Rule::expr => { v.push(
(
safe_unwrap!(last,"Ternary Expression"),
Box::new(Expression::take(pair)?)
)
); last=None; }, _ => return Err(rule_mismatch!(pair))
}
}
Ok(Self(v,Box::new(safe_unwrap!(last,"Ternary Expression"))))
},
_ => Err(rule_mismatch!(pair,cond_expr))
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ConstExpr(pub CondExpr);
impl AST for ConstExpr {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::const_expr => {
let pair=safe_unwrap!(pair.into_inner().next(),"Constant Expression");
match pair.as_rule() {
Rule::cond_expr => Ok(Self(CondExpr::take(pair)?)),
_ => Err(rule_mismatch!(pair,cond_expr))
}
},
_ => Err(rule_mismatch!(pair,const_expr))
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum AssignmentExpr {
Cond(CondExpr),
Assign(UnaryExpr,Box<AssignmentExpr>), MulAssign(UnaryExpr,Box<AssignmentExpr>), DivAssign(UnaryExpr,Box<AssignmentExpr>), ModAssign(UnaryExpr,Box<AssignmentExpr>), AddAssign(UnaryExpr,Box<AssignmentExpr>), SubAssign(UnaryExpr,Box<AssignmentExpr>), LShiftAssign(UnaryExpr,Box<AssignmentExpr>), RShiftAssign(UnaryExpr,Box<AssignmentExpr>), AndAssign(UnaryExpr,Box<AssignmentExpr>), XorAssign(UnaryExpr,Box<AssignmentExpr>), OrAssign(UnaryExpr,Box<AssignmentExpr>) }
impl AST for AssignmentExpr {
fn take(pair: Pair<Rule>) -> Result<Self> {
macro_rules! ret {
($id:ident,$unary:expr,$inner:expr,$e:expr) => {
Ok(Self::$id($unary, Box::new(Self::take(safe_unwrap!($inner.next(),$e))?)))
};
}
match pair.as_rule() {
Rule::assign_expr => {
let mut inner=pair.into_inner();
let pair=safe_unwrap!(inner.next(),"Assignment Expression");
match pair.as_rule() {
Rule::cond_expr => Ok(Self::Cond(CondExpr::take(pair)?)),
Rule::unary_expr => {
let unary=UnaryExpr::take(pair)?;
let pair=safe_unwrap!(inner.next(),"Right-hand-side of Assignment Expression");
match pair.as_rule() {
Rule::assign => ret!(Assign,unary,inner,"Assign Expression"),
Rule::mul_assign => ret!(MulAssign,unary,inner,"MulAssign Expression"),
Rule::div_assign => ret!(DivAssign,unary,inner,"DivAssign Expression"),
Rule::mod_assign => ret!(ModAssign,unary,inner,"ModAssign Expression"),
Rule::add_assign => ret!(AddAssign,unary,inner,"AddAssign Expression"),
Rule::sub_assign => ret!(SubAssign,unary,inner,"SubAssign Expression"),
Rule::lshift_assign => ret!(LShiftAssign,unary,inner,"LShiftAssign Expression"),
Rule::rshift_assign => ret!(RShiftAssign,unary,inner,"RShiftAssign Expression"),
Rule::and_assign => ret!(AndAssign,unary,inner,"AndAssign Expression"),
Rule::xor_assign => ret!(XorAssign,unary,inner,"XorAssign Expression"),
Rule::or_assign => ret!(OrAssign,unary,inner,"OrAssign Expression"),
_ => Err(rule_mismatch!(pair))
}
},
_ => Err(rule_mismatch!(pair))
}
},
_ => Err(rule_mismatch!(pair,assign_expr))
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Expression(pub Vec<AssignmentExpr>);
list_ast!(Expression : AssignmentExpr where expr => assign_expr);