use crate::ast::*; use crate::lalrpop::parser::InstructionError; use lalrpop_util::ErrorRecovery; use std::rc::Rc; grammar<'err>(errors: &'err mut Vec, InstructionError>>); extern { type Error = InstructionError; } pub Instr: Box> = { "(" "seq" ")" => Box::new(Instruction::Seq(Seq(l, r))), "(" "par" ")" => Box::new(Instruction::Par(Par(l, r))), "(" "xor" ")" => Box::new(Instruction::Xor(Xor(l, r))), "(" "call" ")" => { let output = output.unwrap_or(CallOutput::None); Box::new(Instruction::Call(Call{peer_part: p, function_part: f, args, output})) }, "(" "fold" ")" => { let instruction = Rc::new(*i); Box::new(Instruction::Fold(Fold{ iterable, iterator, instruction })) }, "(" "next" ")" => Box::new(Instruction::Next(Next(i))), "(" "null" ")" => Box::new(Instruction::Null(Null)), ! => { errors.push(<>); Box::new(Instruction::Error) }, } Args: Vec> = { "[" )*> "]" => args } FPart: FunctionPart<'input> = { => FunctionPart::FuncName(f), "(" ")" => FunctionPart::ServiceIdWithFuncName(sid, f), } PeerPart: PeerPart<'input> = { => PeerPart::PeerPk(pid), "(" ")" => PeerPart::PeerPkWithServiceId(pid, sid), } Output: CallOutput<'input> = { => CallOutput::Scalar(o), => CallOutput::Accumulator(&o[..o.len()-2]), }; Function = Value; PeerId = Value; ServiceId = Value; Arg = Value; Value: Value<'input> = { "\"" "\"" => Value::Literal(""), // TODO: signal absence somehow? "\"" "\"" => Value::Literal(v), => Value::Variable(v), => { let mut path = v.splitn(2, "."); let variable = path.next().expect("must contain dot"); let path = path.next().expect("contain component after dot"); Value::JsonPath { variable, path } }, CURRENT_PEER_ID => Value::CurrentPeerId, INIT_PEER_ID => Value::InitPeerId, } Alphanumeric = ALPHANUMERIC; match { r"[\w_-]+" => ALPHANUMERIC, r"[\w_-]+\[\]" => ACCUMULATOR, r#"[\w_-]+\.*\$([\w._-]*(\[[\w"]+\])*)+"# => JSON_PATH, r#"%current_peer_id%"# => CURRENT_PEER_ID, r#"%init_peer_id%"# => INIT_PEER_ID, "seq", "call", "null", "par", "xor", "fold", "next", } else { _ }