// use std::str::FromStr;
//use std::collections::HashMap;
// use crate::ast_utils::Syntax;
use crate::parser_utils::{dec_node_into_exp, get_one};
use crate::ast::{BinAnnotWasHoisted, hoist_right_type_annotation as hrta, Class, Node, NodeData, Source, SourceKnown, Id, Id_, ToId, Pat, Pat_, PatField, PatField_, Exp, Exp_, ExpField, Function, ObjSort, Type, Type_, TypeField, TypeField_, TypeBind, TypeBind_, BindSort, TypeTag, TypeTag_, ValTypeField, TypePath, TypePath_, PrimType, Literal, Case, Case_, Cases, Decs, Dec, Dec_, UnOp, BinOp, RelOp, Delim, Mut, SortPat, Sugar, Vis, Vis_, Stab, Stab_, DecField, DecField_, DecFields, ProjIndex};
use crate::value::PrimFunction;
// use crate::lexer_types::Token;
use line_col::LineColLookup;
use im_rc::vector;
use crate::shared::{Share};
use std::rc::Rc;
grammar(lookup: &LineColLookup<'input>);
#[inline]
Node<T>: Node<T> = {
<start:@L> <t:T> <end:@R> => {
let (line, col) = lookup.get(start);
NodeData::new(t, Source::Known(Rc::new(SourceKnown{ span: start..end, line, col }))).share()
},
}
/// One or more `T`s, delimited by interposed separator `S`.
Delim1<T, S>: Delim<T> = {
T => {
Delim{ vec:vector!(<>), has_trailing: false }
},
<mut v:(<T> S)+> <e:T?> => match e {
None => {
Delim{ vec:v.into(), has_trailing: true }
},
Some(e) => {
v.push(e);
Delim{ vec:v.into(), has_trailing: false }
}
}
};
/// Zero or more `T`s, delimited by interposed separator `S`.
Delim0<T, S>: Delim<T> = {
<mut v:(<T> S)*> <e:T?> => match e {
None => {
let has_trailing = v.len() > 0;
Delim{ vec:v.into(), has_trailing }
},
Some(e) => {
v.push(e);
Delim{ vec:v.into(), has_trailing: false }
}
}
};
Bl : Exp = {
// no productions.
}
Ob : Exp = {
ExpObj
}
// --- Terminals --- //
NatIndex: usize = {
r"[0-9]([0-9_]*[0-9])?" => <>.replace('_', "").parse().unwrap(),
}
FloatIndex: String = {
r"[+-]?[0-9]([0-9_]*[0-9])?\.([0-9]([0-9_]*[0-9])?)?([Ee][0-9]([0-9_]*[0-9])?)?" => <>.to_string(), // exponential with decimal
}
Id: Id = {
r"[@]?[a-zA-Z_][a-zA-Z_0-9]*" => <>.to_id(),
};
#[inline]
Id_: Id_ = Node<Id>;
// --- Literals --- //
#[inline]
Literal_: Node<Literal> = Node<Literal>;
pub Literal: Literal = {
"null" => Literal::Null,
"true" => Literal::Bool(true),
"false" => Literal::Bool(false),
"(" ")" => Literal::Unit,
r"[+-]?[0-9]([0-9_]*[0-9])?[Ee][0-9]([0-9_]*[0-9])?" => Literal::Float(<>.to_string()), // exponential without decimal
r"[+-]?[0-9]([0-9_]*[0-9])?\.([0-9]([0-9_]*[0-9])?)?([Ee][0-9]([0-9_]*[0-9])?)?" => Literal::Float(<>.to_string()), // exponential with decimal
r"0x[0-9a-fA-F]([0-9a-fA-F_]*[0-9a-fA-F])?" => Literal::Nat(<>.to_string()), // hexadecimal
r"[0-9]([0-9_]*[0-9])?" => Literal::Nat(<>.to_string()),
r"'(?:[^\\'\s]|\\.)*'|' '" => Literal::Char(<>.to_string()), // TODO: more test cases
<s:StringLiteral> => Literal::Text(s),
}
StringLiteral: String = {
r#""(?:[^\\"]|\\.)*""# => <>.to_string(), // TODO more test cases
}
// --- Patterns --- //
#[inline]
PatPlain_: Pat_ = Node<PatPlain>;
PatPlain: Pat = {
"_" => Pat::Wild,
Id_ => Pat::Var(<>),
Literal => Pat::Literal(<>),
"(" <ps:Delim1<PatBin_, ",">> ")" => get_one(ps).map(Pat::Paren).unwrap_or_else(Pat::Tuple),
}
#[inline]
PatNullary_: Pat_ = Node<PatNullary>;
PatNullary: Pat = {
PatPlain,
"{" <d:Delim0<PatField_, ";">> "}" => Pat::Object(d),
}
#[inline]
PatBin_: Pat_ = Node<PatBin>;
PatBin: Pat = {
PatUn,
<p:PatBin_> ":" <t:Type_> => Pat::AnnotPat(p, t),
<p1:PatBin_> "or" <p2:PatUn_> => Pat::Or(p1, p2),
}
#[inline]
PatUn_: Pat_ = Node<PatUn>;
PatUn: Pat = {
PatNullary,
"#" <s:Id_> => Pat::Variant(s, None),
"#" <s:Id_> <p:PatNullary_> => Pat::Variant(s, Some(p)),
"?" <p:PatUn_> => Pat::Optional(p),
<u:UnOp_> <l:Literal_> => Pat::UnOpLiteral(u, l),
}
#[inline]
Pat_: Pat_ = Node<Pat>;
pub Pat: Pat = {
PatBin,
}
#[inline]
PatField_: PatField_ = Node<PatField>;
PatField: PatField = {
<id:Id_> => PatField{ id, pat:None },
<id:Id_> ":" <t:Type_> => PatField{ id:id.clone(), pat:Some(Pat::Annot(t)) },
<id:Id_> "=" <pat:Pat> => PatField{ id, pat:Some(pat) },
<id:Id_> ":" <t:Type_> "=" <pat:Pat_> => PatField{ id, pat:Some(Pat::AnnotPat(pat, t ))}
}
PatOpt: Pat = {
PatPlain,
=> Pat::Wild,
}
// --- Types --- //
TypeFields: Delim<TypeField_> = {
"{" <tfs:Delim0<TypeField_, ";">> "}" => tfs,
}
TypeObj: Type = {
"{" <tfs:Delim0<TypeField_, ";">> "}" => Type::Object(ObjSort::Object, tfs),
}
TypeVariant: Type = {
"{" "#" "}" => Type::Variant(Delim::new()),
"{" <tts:Delim1<TypeTag_, ";">> "}" => Type::Variant(tts),
}
#[inline]
TypeTag_: TypeTag_ = Node<TypeTag>;
TypeTag: TypeTag = {
"#" <id:Id_> <typ:(":" <Type_>)?> => TypeTag{ id, typ },
}
#[inline]
TypeBind_: TypeBind_ = Node<TypeBind>;
TypeBind: TypeBind = {
<var:Id_> => TypeBind{ var, sort:BindSort::Type, bound: None },
<var:Id_> "<:" <t:Type_> => TypeBind{ var, sort:BindSort::Type, bound: Some(t) },
}
#[inline]
TypeField_: TypeField_ = Node<TypeField>;
TypeField: TypeField = {
// "type" <id:Id_> <tps:TypeParamsOpt> "=" <t:Type_> => TypeField::Type,
<mut_:VarOpt> <id:Id_> ":" <typ:Type_> => TypeField::Val(ValTypeField{mut_, id, typ }),
// <id:Id_> <tps:TypeParamsOpt> <t1:TypeNullary_> ":" <t2:Type_> => TypeField::Type,
}
#[inline]
TypeNullary_: Type_ = Node<TypeNullary>;
pub TypeNullary: Type = {
"(" <ts:Delim1<TypeItem_, ",">> ")" => Type::Tuple(ts),
"(" ")" => Type::Prim(PrimType::Unit),
<id:Id_> <ta:TypeArgs> => Type::id_type_args(id, ta),
<p:TypePath_> "." <id:Id_> <ta:TypeArgs> => Type::Path(TypePath::Dot(p, id), ta),
"[" <vo:VarOpt> <t:Type_> "]" => Type::Array(vo, t),
TypeObj,
TypeVariant
}
#[inline]
TypePath_: TypePath_ = Node<TypePath>;
TypePath: TypePath = {
Id_ => TypePath::Id(<>),
<p:TypePath_> "." <id:Id_> => TypePath::Dot(p, id),
}
#[inline]
TypeUn_: Type_ = Node<TypeUn>;
pub TypeUn: Type = {
TypeNullary,
"?" <t:TypeUn_> => Type::Optional(t),
}
#[inline]
TypePre_: Type_ = Node<TypePre>;
pub TypePre: Type = {
TypeUn,
"prim" <t:StringLiteral> => Type::prim(&t),
"async" <t:TypePre_> => Type::Async(t),
"actor" <to:TypeFields> => Type::Object(ObjSort::Actor, to),
"object" <to:TypeFields> => Type::Object(ObjSort::Object, to),
"module" <to:TypeFields> => Type::Object(ObjSort::Module, to),
}
#[inline]
TypeNoBin_: Type_ = Node<TypeNoBin>;
pub TypeNoBin: Type = {
TypePre,
<fso:FuncSortOpt> <tps:TypeParamsOpt> <t1:TypeUn_> "->" <t2:TypeNoBin_> =>
Type::Function(fso, tps, t1, t2),
}
#[inline]
Type_: Type_ = Node<Type>;
pub Type: Type = {
TypeNoBin,
}
#[inline]
TypeItem_: Type_ = Node<TypeItem>;
pub TypeItem: Type = {
<id:Id_> ":" <t:Type_> => Type::Item(id, t),
Type,
}
pub TypeArgs: Option<Delim<Type_>> = {
=> None,
"<" <d:Delim0<Type_, ",">> ">" => Some(d)
}
// --- Programs --- //
pub Prog: Decs = {
Decs,
}
// --- Expressions --- //
#[inline]
ExpIfNoElse_<E>: Exp_ = Node<ExpIfNoElse<E>>;
ExpIfNoElse<E>: Exp = {
"if" <e1:ExpNullary_<Ob>> <e2:ExpNest_> => Exp::If(e1, e2, None),
E,
}
#[inline]
Exp_<B>: Exp_ = Node<Exp<B>>;
Exp<B>: Exp = {
ExpNonVar<B>,
DecVar_ => dec_node_into_exp(<>),
}
#[inline]
ExpNonVar_<B>: Exp_ = Node<ExpNonVar<B>>;
ExpNonVar<B>: Exp = {
ExpNonDec<B>,
DecNonVar_ => dec_node_into_exp(<>),
}
#[inline]
DecVar_: Dec_ = Node<DecVar>;
DecVar: Dec = {
"var" <p:Pat_> "=" <e:Exp_<Ob>> => Dec::Var(p, e),
}
#[inline]
ExpNonDec0_<B>: Exp_ = Node<ExpNonDec0<B>>;
ExpNonDec0<B>: Exp = {
"if" <e1:ExpNullary_<Ob>> <e2:ExpNest_> => Exp::If(e1, e2, None),
ExpNonDec<B>,
}
#[inline]
ExpNonDec_<B>: Exp_ = Node<ExpNonDec<B>>;
ExpNonDec<B>: Exp = {
ExpBin0<B>,
<e1:ExpBin0_<B>> ":=" <e2:Exp_<Ob>> => Exp::Assign(e1, e2),
<e1:ExpBin0_<B>> <b:BinAssign> <e2:Exp_<Ob>> => Exp::BinAssign(e1, b, e2),
"if" <e1:ExpNullary_<Ob>> <e2:ExpNest_> "else" <e3:ExpNest_> => Exp::If(e1, e2, Some(e3)),
"return" <e:Exp_<B>?> => Exp::Return(e),
"async" <e:ExpNest_> => Exp::Async(e),
"async*" <e:Block_> => Exp::AsyncStar(e),
"await" <e:ExpNest_> => Exp::Async(e),
"await*" <e:ExpNest_> => Exp::AsyncStar(e),
"switch" <e:ExpNullary_<Ob>> "{" <cs:Cases> "}" => Exp::Switch(e, cs),
"loop" <e:ExpNest_> => Exp::Loop(e, None),
"while" <e1:ExpNullary_<Ob>> <e2:ExpNest_> => Exp::While(e1, e2),
"for" "(" <p:Pat_> "in" <e1:Exp_<Ob>> ")" <e2:ExpNest_> => Exp::For(p, e1, e2),
"ignore" <e:ExpNest_> => Exp::Ignore(e),
"do" <e:Block_> => Exp::Do(e),
"do" "?" <e:Block_> => Exp::DoOpt(e),
"assert" <e:ExpNest_> => Exp::Assert(e),
"label" <id:Id_> <t:(":" <Type_>)?> <e:ExpNest_> => Exp::Label(id, t, e),
"debug" <e:ExpNest_> => Exp::Debug(e),
"import" <txt:StringLiteral> => Exp::Import(txt),
"try" <e1:ExpNest_> <c:Catch_> => Exp::Try(e1, c),
}
#[inline]
Catch_: Case_ = Node<Catch>;
Catch: Case = {
"catch" <pat:PatNullary_> <exp:ExpNest_> => Case{ pat, exp },
}
#[inline]
ExpNullary_<B>: Exp_ = Node<ExpNullary<B>>;
ExpNullary<B>: Exp = {
B,
ExpPlain,
Id => Exp::Var(<>),
"prim" <t:StringLiteral> => Exp::Prim(PrimFunction::resolve(t)),
}
#[inline]
ExpPlain_: Exp_ = Node<ExpPlain>;
ExpPlain: Exp = {
Literal => Exp::Literal(<>),
"(" <es:Delim1<ExpIfNoElse_<Exp<Ob>>, ",">> ")" => get_one(es).map(Exp::Paren).unwrap_or_else(Exp::Tuple),
}
#[inline]
ExpNest_: Exp_ = Node<ExpNest>;
ExpNest: Exp = {
Block,
Exp<Bl>,
}
#[inline]
Block_: Exp_ = Node<Block>;
Block: Exp = {
"{" <ds:Decs> "}" => Exp::Block(ds)
}
#[inline]
ExpPost_<B>: Exp_ = Node<ExpPost<B>>;
ExpPost<B>: Exp = {
ExpNullary<B>,
"[" <v:VarOpt> <es:Delim0<ExpNonVar_<Ob>, ",">> "]" => Exp::Array(v, es),
<e1:ExpPost_<B>> "[" <e2:Exp_<Ob>> "]" => Exp::Index(e1, e2),
<e1:ExpPost_<B>> "." <i:NatIndex> => Exp::Proj(e1, ProjIndex::Usize(i)),
<e1:ExpPost_<B>> "." <f:FloatIndex> => Exp::Proj(e1, ProjIndex::FloatLike(f)),
<e1:ExpPost_<B>> "." <i:Id_> => Exp::Dot(e1, i),
<e1:ExpPost_<B>> "<" <inst:Delim0<Type_, ",">> ">" <e2:ExpNullary_<Ob>> => Exp::Call(e1, Some(inst), e2),
<e1:ExpPost_<B>> <e2:ExpNullary_<Ob>> => Exp::Call(e1, None, e2),
<e:ExpPost_<B>> "!" => Exp::Bang(e),
}
VarOpt: Mut = {
"var" => Mut::Var,
=> Mut::Const,
}
#[inline]
ExpUn_<B>: Exp_ = Node<ExpUn<B>>;
ExpUn<B>: Exp = {
ExpPost<B>,
"#" <x:Id_> <e:(ExpNullary_<B>)?> => Exp::Variant(x, e),
"?" <e:ExpUn_<Ob>> => Exp::Opt(e),
"actor" <e:ExpPlain_> => Exp::ActorUrl(e),
<u:UnOp> <e:ExpUn_<B>> => Exp::Un(u, e),
"not" <e:ExpUn_<B>> => Exp::Not(e),
"debug_show" <e:ExpUn_<B>> => Exp::DebugShow(e),
"to_candid" "(" <d:Delim1<Exp_<Ob>, ",">> ")" => Exp::ToCandid(d),
"from_candid" <e:ExpUn_<B>> => Exp::FromCandid(e),
}
ExpObj: Exp = {
// Object syntax.
//
// We want to use this concise rule, like in the Menhir version of
// the Motoko parser:
//
// "{" <fs:Delim0<ExpField_, ";">> "}" => Exp::Object(None, None, Some(fs)),
//
// But, we cannot parse the first field directly as a FieldExp,
// like the ones that may follow it. It is ambiguous here, sadly.
// (It conflicts with the new rules for record base-extension
// syntax, in the singleton-var case `{ x }`). This limitation
// comes from the LALR(1) language of lalrpop in contrast to the
// LR(1) language of menhir. To bridge this gap, we parse the
// first field in a more case-by-case way.
//
"{" "}" => Exp::Object(None, None),
"{" <field1:ExpFieldNoBareId_> <fields:(";" <Delim0<ExpField_, ";">>)?> "}" => Exp::obj_field_fields(field1, fields),
"{" <id:Id_> ";" <fields:Delim1<ExpField_, ";">> "}" => Exp::obj_id_fields(id, fields),
"{" <base1:ExpPost_<Ob>> <bases:("and" <Delim1<ExpPost_<Ob>, "and">>)?> <efs:("with" <Delim1<ExpField_, ";">>)?> "}" => Exp::obj_base_bases(base1, bases, efs),
}
#[inline]
ExpField_: Node<ExpField> = Node<ExpField>;
ExpField: ExpField = {
<mut_:VarOpt> <id:Id_> <typ:(":" <Type_>)?> <exp:("=" <ExpIfNoElse_<Exp<Ob>>>)?> => ExpField{ mut_, id, exp, typ }
}
#[inline]
ExpFieldNoBareId_: Node<ExpField> = Node<ExpFieldNoBareId>;
ExpFieldNoBareId: ExpField = { // like ExpField, except that a "bare" Id is not permitted. Helps disambiguate the parse tree.
"var" <id:Id_> <typ:(":" <TypeNoBin_>)?> "=" <exp:ExpIfNoElse_<Exp<Ob>>> => ExpField{ mut_:Mut::Var, id, exp:Some(exp), typ },
<id:Id_> ":" <typ:TypeNoBin_> <exp:("=" <ExpIfNoElse_<Exp<Ob>>>)?> => ExpField{ mut_:Mut::Const, id, exp, typ:Some(typ) },
<id:Id_> "=" <exp:ExpIfNoElse_<Exp<Ob>>> => ExpField{ mut_:Mut::Const, id, exp:Some(exp), typ:None },
}
#[inline]
BinAssign: BinOp = {
"+=" => BinOp::Add,
"-=" => BinOp::Sub,
"*=" => BinOp::Mul,
"/=" => BinOp::Div,
"%=" => BinOp::Mod,
"**=" => BinOp::Pow,
"&=" => BinOp::BitAnd,
"|=" => BinOp::BitOr,
"^=" => BinOp::Xor,
"<<=" => BinOp::ShL,
">>=" => BinOp::ShR,
"<<>=" => BinOp::RotL,
"<>>=" => BinOp::RotR,
"+%=" => BinOp::WAdd,
"-%=" => BinOp::WSub,
"*%=" => BinOp::WMul,
"**%=" => BinOp::WPow,
"#=" => BinOp::Cat,
}
#[inline]
ExpBin0_<B>: Exp_ = Node<ExpBin0<B>>;
ExpBin0<B>: Exp = {
<e1:ExpBin0_<B>> "or" <e2:ExpBin1_<B>> => hrta(Exp::Or(e1, e2)),
ExpBin1<B>,
}
#[inline]
ExpBin1_<B>: Exp_ = Node<ExpBin1<B>>;
ExpBin1<B>: Exp = {
<e1:ExpBin1_<B>> "and" <e2:ExpBin2_<B>> => hrta(Exp::And(e1, e2)),
ExpBin2<B>,
}
#[inline]
ExpBin2_<B>: Exp_ = Node<ExpBin2<B>>;
ExpBin2<B>: Exp = {
<e1:ExpBin2_<B>> "==" <e2:ExpBin3_<B>> => hrta(Exp::Rel(e1, RelOp::Eq, e2)),
<e1:ExpBin2_<B>> "!=" <e2:ExpBin3_<B>> => hrta(Exp::Rel(e1, RelOp::Neq, e2)),
<e1:ExpBin2_<B>> "<=" <e2:ExpBin3_<B>> => hrta(Exp::Rel(e1, RelOp::Le, e2)),
<e1:ExpBin2_<B>> ">=" <e2:ExpBin3_<B>> => hrta(Exp::Rel(e1, RelOp::Ge, e2)),
<e1:ExpBin2_<B>> " < " <e2:ExpBin3_<B>> => hrta(Exp::Rel(e1, RelOp::Lt, e2)),
<e1:ExpBin2_<B>> " > " <e2:ExpBin3_<B>> => hrta(Exp::Rel(e1, RelOp::Gt, e2)),
ExpBin3<B>,
}
#[inline]
ExpBin3_<B>: Exp_ = Node<ExpBin3<B>>;
ExpBin3<B>: Exp = {
<e1:ExpBin3_<B>> "+" <e2:ExpBin4_<B>> => hrta(Exp::Bin(e1, BinOp::Add, e2)),
<e1:ExpBin3_<B>> "+%" <e2:ExpBin4_<B>> => hrta(Exp::Bin(e1, BinOp::WAdd, e2)),
<e1:ExpBin3_<B>> "-" <e2:ExpBin4_<B>> => hrta(Exp::Bin(e1, BinOp::Sub, e2)),
<e1:ExpBin3_<B>> "-%" <e2:ExpBin4_<B>> => hrta(Exp::Bin(e1, BinOp::WSub, e2)),
<e1:ExpBin3_<B>> "#" <e2:ExpBin4_<B>> => hrta(Exp::Bin(e1, BinOp::Cat, e2)),
ExpBin4<B>,
}
#[inline]
ExpBin4_<B>: Exp_ = Node<ExpBin4<B>>;
ExpBin4<B>: Exp = {
<e1:ExpBin4_<B>> "*" <e2:ExpBin5_<B>> => hrta(Exp::Bin(e1, BinOp::Mul, e2)),
<e1:ExpBin4_<B>> "*%" <e2:ExpBin5_<B>> => hrta(Exp::Bin(e1, BinOp::WMul, e2)),
<e1:ExpBin4_<B>> "/" <e2:ExpBin5_<B>> => hrta(Exp::Bin(e1, BinOp::Div, e2)),
<e1:ExpBin4_<B>> "%" <e2:ExpBin5_<B>> => hrta(Exp::Bin(e1, BinOp::Mod, e2)),
ExpBin5<B>,
}
#[inline]
ExpBin5_<B>: Exp_ = Node<ExpBin5<B>>;
ExpBin5<B>: Exp = {
<e1:ExpBin5_<B>> "|" <e2:ExpBin6_<B>> => hrta(Exp::Bin(e1, BinOp::BitOr, e2)),
ExpBin6<B>,
}
#[inline]
ExpBin6_<B>: Exp_ = Node<ExpBin6<B>>;
ExpBin6<B>: Exp = {
<e1:ExpBin6_<B>> "&" <e2:ExpBin7_<B>> => hrta(Exp::Bin(e1, BinOp::BitAnd, e2)),
ExpBin7<B>,
}
#[inline]
ExpBin7_<B>: Exp_ = Node<ExpBin7<B>>;
ExpBin7<B>: Exp = {
<e1:ExpBin7_<B>> "^" <e2:ExpBin8_<B>> => hrta(Exp::Bin(e1, BinOp::Xor, e2)),
ExpBin8<B>,
}
#[inline]
ExpBin8_<B>: Exp_ = Node<ExpBin8<B>>;
ExpBin8<B>: Exp = {
<e1:ExpBin9_<B>> " << " <e2:ExpBin9_<B>> => hrta(Exp::Bin(e1, BinOp::ShL, e2)),
<e1:ExpBin9_<B>> " >> " <e2:ExpBin9_<B>> => hrta(Exp::Bin(e1, BinOp::ShR, e2)),
<e1:ExpBin9_<B>> "<<>" <e2:ExpBin9_<B>> => hrta(Exp::Bin(e1, BinOp::RotL, e2)),
<e1:ExpBin9_<B>> "<>>" <e2:ExpBin9_<B>> => hrta(Exp::Bin(e1, BinOp::RotR, e2)),
ExpBin9<B>,
}
#[inline]
ExpBin9_<B>: Exp_ = Node<ExpBin9<B>>;
ExpBin9<B>: Exp = {
<e1:ExpBin9_<B>> "**" <e2:ExpUn_<B>> => hrta(Exp::Bin(e1, BinOp::Pow, e2)),
<e1:ExpBin9_<B>> "**%" <e2:ExpUn_<B>> => hrta(Exp::Bin(e1, BinOp::WPow, e2)),
<e1:ExpBin9_<B>> ":" <t:TypeNoBin_> => Exp::Annot(BinAnnotWasHoisted(false), e1, t),
ExpUn<B>,
}
Cases: Cases = {
Delim0<Node<Case>, ";">
}
Case: Case = {
"case" <pat:PatNullary_> <exp:ExpIfNoElse_<ExpNest>> => Case{pat, exp},
}
Decs: Decs = {
Delim0<Dec_, ";">
}
#[inline]
Dec_: Dec_ = Node<Dec>;
Dec: Dec = {
DecVar,
DecNonVar,
ExpNonDec0_<Ob> => Dec::Exp(<>),
}
#[inline]
DecNonVar_: Dec_ = Node<DecNonVar>;
DecNonVar: Dec = {
"import" <p:PatNullary_> <s:"="?> <txt:StringLiteral> => Dec::LetImport(p, Sugar(s.is_some()), txt),
"let" <p:Pat_> "=" <e:Exp_<Ob>> => Dec::Let(p, e),
"type" <id:Id_> <tps:TypeParamsOpt> "=" <t:Type_> => Dec::Type(id, tps, t),
<sp:SharedPatOpt> "class" <oso:ObjSortOpt> <id1:(Id_)?> <tpo:TypeParamsOpt> <p:PatPlain_> <t:(":" <Type_>)?> "=" <id2:(Id_)?> <b:ObjBody> => Dec::Class(Class {
shared: sp,
sort: oso,
typ_id: id1,
binds: tpo,
input: p,
typ: t,
name: id2,
fields: b
}),
"module" <i:(Id_)?> <s:"="?> <ob:ObjBody> => Dec::LetModule(i, Sugar(s.is_some()), ob),
"actor" <i:(Id_)?> <s:"="?> <ob:ObjBody> => Dec::LetActor(i, Sugar(s.is_some()), ob),
"object" <i:(Id_)?> <s:"="?> <ob:ObjBody> => Dec::LetObject(i, Sugar(s.is_some()), ob),
<sp:SharedPatOpt> "func" <i:(Id_)?> <tpo:TypeParamsOpt> <p:PatPlain_> <t:(":" Type_)?> <b:Block_> => Dec::Func(Function {
name: i, shared: sp, binds: tpo, input: p, output: t.map(|t|{t.1}), sugar: Sugar(false), exp: b,
}),
<sp:SharedPatOpt> "func" <i:(Id_)?> <tpo:TypeParamsOpt> <p:PatPlain_> <t:(":" Type_)?> "=" <e:Exp_<Ob>> => Dec::Func(Function {
name: i, shared: sp, binds: tpo, input: p, output: t.map(|t|{t.1}), sugar: Sugar(true), exp: e,
}),
<sp:SharedPatOpt> "class" <oso:ObjSortOpt> <id:(Id_)?> <tpo:TypeParamsOpt> <p:PatPlain_> <t:(":" <Type_>)?> <b:ObjBody> => Dec::Class(Class {
shared: sp,
sort: oso,
typ_id: id,
binds: tpo,
input: p,
typ: t,
name: None,
fields: b
})
}
ObjSortOpt: Option<ObjSort> = {
=> None,
"object" => Some(ObjSort::Object),
"module" => Some(ObjSort::Module),
"actor" => Some(ObjSort::Actor),
}
#[inline]
TypeParamsOpt: Option<Delim<TypeBind_>> = {
=> None,
"<" <ts:Delim0<TypeBind, ",">> ">" => None, // to do -- produce AST.
}
#[inline]
SharedPatOpt: Option<SortPat> = {
=> None,
"shared" => None, // to do -- produce AST.
"shared" "query" <op:PatOpt> => None, // to do -- produce AST.
"query" <op:PatOpt> => None, // to do -- produce AST.
}
#[inline]
FuncSortOpt: Option<SortPat> = {
<q:"query"?> => None, // to do -- produce AST.
"shared" <q:"query"?> => None, // to do -- produce AST.
}
#[inline]
UnOp_: Node<UnOp> = Node<UnOp>;
UnOp: UnOp = {
"+" => UnOp::Pos,
"-" => UnOp::Neg,
"^" => UnOp::Not,
}
BinOp: BinOp = {
"+" => BinOp::Add,
"-" => BinOp::Sub,
"*" => BinOp::Mul,
"/" => BinOp::Div,
"%" => BinOp::Mod,
"**" => BinOp::Pow,
"+%" => BinOp::WAdd,
"-%" => BinOp::WSub,
"*%" => BinOp::WMul,
"**%" => BinOp::WPow,
"&" => BinOp::And,
"|" => BinOp::Or,
"^" => BinOp::Xor,
" << " => BinOp::ShL,
" >> " => BinOp::ShR,
"<<>" => BinOp::RotL,
"<>>" => BinOp::RotR,
"#" => BinOp::Cat,
}
ObjBody: DecFields = {
"{" <dfs:Delim0<DecField_, ";">> "}" => dfs
}
#[inline]
Vis_: Vis_ = Node<Vis>;
Vis: Vis = {
"public" => Vis::Public(None),
"private" => Vis::Private,
}
#[inline]
Stab_: Stab_ = Node<Stab>;
Stab: Stab = {
"stable" => Stab::Stable,
"flexible" => Stab::Flexible,
}
#[inline]
DecField_: DecField_ = Node<DecField>;
DecField: DecField = {
<vis:(Vis_)?> <stab:(Stab_)?> <dec:Dec_> => DecField{ vis, stab, dec }
}