use crate::ast::*;
grammar;
// Macros
List<T, Delim>: Vec<T> = <mut items:(<T> Delim)*> <last_item:T?> => match last_item {
Some(item) => {
items.push(item);
items
},
_ => items,
};
// Literals
RawNone = "none";
RawBool = {"true", "false"};
RawDec = r"[0-9][0-9_]*";
RawHex = r"0[xX][0-9a-fA-F][0-9a-fA-F_]*";
RawBin = r"0[bB][01][01_]*";
RawOct = r"0[oO][0-7][0-7_]*";
RawFloat = r"[0-9][0-9_]*((\\.[0-9][0-9_]*)?[eE][-+]?[0-9][0-9_]*|\\.[0-9][0-9_]*)";
RawIdent = r"[_\p{XIDStart}]\p{XIDContinue}*";
RawAtom = r":\p{XIDContinue}*";
RawStr = r#""([^\\"]|\\.)*""#;
// Literal expressions
None: None = <start:@L> RawNone <end:@R> => None::new(start..end);
Bool: Bool<'input> = <start:@L> <value:RawBool> <end:@R> => Bool::new(start..end, value);
Num: Num<'input> = {
<start:@L> <value:RawDec> <end:@R> => Num::dec(start..end, value),
<start:@L> <value:RawHex> <end:@R> => Num::hex(start..end, value),
<start:@L> <value:RawBin> <end:@R> => Num::bin(start..end, value),
<start:@L> <value:RawOct> <end:@R> => Num::oct(start..end, value),
<start:@L> <value:RawFloat> <end:@R> => Num::float(start..end, value),
};
Ident: Ident<'input> = <start:@L> <value:RawIdent> <end:@R> => Ident::new(start..end, value);
Atom: Atom<'input> = <start:@L> <value:RawAtom> <end:@R> => Atom::new(start..end, value);
Str: Str<'input> = <start:@L> <value:RawStr> <end:@R> => Str::new(start..end, value);
// Expressions
pub Expr: Expr<'input> = OrExpr;
LitExpr: Expr<'input> = {
<expr:None> => Expr::None(expr),
<expr:Bool> => Expr::Bool(expr),
<expr:Num> => Expr::Num(expr),
<expr:Ident> => Expr::Ident(expr),
<expr:Atom> => Expr::Atom(expr),
<expr:Str> => Expr::Str(expr),
"(" <Expr> ")",
};
AccessOp: BinaryOp = {
"." => BinaryOp::ObjIdx,
"::" => BinaryOp::StaticIdx,
};
AccessExpr: Expr<'input> = {
<LitExpr>,
<start:@L> <left:AccessExpr> <op:AccessOp> <right:LitExpr> <end:@R> => Expr::binary(start..end, left, op, right),
<start:@L> <left:AccessExpr> "[" <right:LitExpr> "]" <end:@R> => Expr::binary(start..end, left, BinaryOp::ExprIdx, right),
<start:@L> <fun:AccessExpr> "(" <args:List<Expr, ",">> ")" <end:@R> => Expr::call(start..end, fun, args),
<start:@L> <subject:AccessExpr> "." "deref" <end:@R> => Expr::unary(start..end, UnaryOp::Deref, subject),
<start:@L> <subject:AccessExpr> "." "cloned" <end:@R> => Expr::unary(start..end, UnaryOp::Cloned, subject),
};
UnaryOp: UnaryOp = {
"+" => UnaryOp::Pos,
"-" => UnaryOp::Neg,
"!" => UnaryOp::Not,
"~" => UnaryOp::BitNot,
};
UnaryExpr: Expr<'input> = {
<AccessExpr>,
<start:@L> <op:UnaryOp> <subject:UnaryExpr> <end:@R> => Expr::unary(start..end, op, subject),
};
MulOp: BinaryOp = {
"*" => BinaryOp::Mul,
"/" => BinaryOp::Div,
"%" => BinaryOp::Mod,
};
MulExpr: Expr<'input> = {
<UnaryExpr>,
<start:@L> <left:MulExpr> <op:MulOp> <right:UnaryExpr> <end:@R> => Expr::binary(start..end, left, op, right),
};
AddOp: BinaryOp = {
"+" => BinaryOp::Add,
"-" => BinaryOp::Sub,
};
AddExpr: Expr<'input> = {
<MulExpr>,
<start:@L> <left:AddExpr> <op:AddOp> <right:MulExpr> <end:@R> => Expr::binary(start..end, left, op, right),
};
ShOp: BinaryOp = {
"<<" => BinaryOp::Shl,
">>" => BinaryOp::Shr,
};
ShExpr: Expr<'input> = {
<AddExpr>,
<start:@L> <left:ShExpr> <op:ShOp> <right:AddExpr> <end:@R> => Expr::binary(start..end, left, op, right),
};
BitAndExpr: Expr<'input> = {
<ShExpr>,
<start:@L> <left:BitAndExpr> "&" <right:ShExpr> <end:@R> => Expr::binary(start..end, left, BinaryOp::BitAnd, right),
};
BitXorExpr: Expr<'input> = {
<ShExpr>,
<start:@L> <left:BitXorExpr> "^" <right:BitAndExpr> <end:@R> => Expr::binary(start..end, left, BinaryOp::BitXor, right),
};
BitOrExpr: Expr<'input> = {
<BitXorExpr>,
<start:@L> <left:BitOrExpr> "|" <right:BitXorExpr> <end:@R> => Expr::binary(start..end, left, BinaryOp::BitOr, right),
};
CmpOp: BinaryOp = {
"==" => BinaryOp::Eq,
"!=" => BinaryOp::Neq,
"<" => BinaryOp::Lt,
">" => BinaryOp::Gt,
"<=" => BinaryOp::LtEq,
">=" => BinaryOp::GtEq,
};
CmpExpr: Expr<'input> = {
<BitOrExpr>,
<start:@L> <left:CmpExpr> <op:CmpOp> <right:BitOrExpr> <end:@R> => Expr::binary(start..end, left, op, right),
};
AndExpr: Expr<'input> = {
<CmpExpr>,
<start:@L> <left:AndExpr> "&&" <right:CmpExpr> <end:@R> => Expr::binary(start..end, left, BinaryOp::And, right),
};
OrExpr: Expr<'input> = {
<AndExpr>,
<start:@L> <left:OrExpr> "||" <right:AndExpr> <end:@R> => Expr::binary(start..end, left, BinaryOp::Or, right),
};
AssignOp: AssignOp = {
"=" => AssignOp::Assign,
"+=" => AssignOp::AssignAdd,
"-=" => AssignOp::AssignSub,
"*=" => AssignOp::AssignMul,
"/=" => AssignOp::AssignDiv,
"%=" => AssignOp::AssignMod,
"|=" => AssignOp::AssignBitOr,
"^=" => AssignOp::AssignBitXor,
"<<=" => AssignOp::AssignShl,
">>=" => AssignOp::AssignShr,
};
AssignExpr: Expr<'input> = <start:@L> <left:AccessExpr> <op:AssignOp> <right:Expr> <end:@R> => Expr::assign(start..end, left, op, right);