xlang-syntax 0.0.1-alpha

The xlang parser and syntax utilities.
Documentation
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);