mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-13 11:15:33 +00:00
94 lines
2.6 KiB
Plaintext
94 lines
2.6 KiB
Plaintext
use crate::ast::*;
|
|
use crate::lalrpop::parser::InstructionError;
|
|
|
|
use lalrpop_util::ErrorRecovery;
|
|
use std::rc::Rc;
|
|
|
|
grammar<'err>(errors: &'err mut Vec<ErrorRecovery<usize, Token<'input>, InstructionError>>);
|
|
|
|
extern {
|
|
type Error = InstructionError;
|
|
}
|
|
|
|
pub Instr: Box<Instruction<'input>> = {
|
|
"(" "seq" <l:Instr> <r:Instr> ")" => Box::new(Instruction::Seq(Seq(l, r))),
|
|
"(" "par" <l:Instr> <r:Instr> ")" => Box::new(Instruction::Par(Par(l, r))),
|
|
"(" "xor" <l:Instr> <r:Instr> ")" => Box::new(Instruction::Xor(Xor(l, r))),
|
|
|
|
"(" "call" <p:PeerPart> <f:FPart> <args:Args> <output:Output?> ")" => {
|
|
let output = output.unwrap_or(CallOutput::None);
|
|
Box::new(Instruction::Call(Call{peer_part: p, function_part: f, args, output}))
|
|
},
|
|
|
|
"(" "fold" <iterable:Value> <iterator:Alphanumeric> <i:Instr> ")" => {
|
|
let instruction = Rc::new(*i);
|
|
Box::new(Instruction::Fold(Fold{ iterable, iterator, instruction }))
|
|
},
|
|
|
|
"(" "next" <i:Alphanumeric> ")" => Box::new(Instruction::Next(Next(i))),
|
|
"(" "null" ")" => Box::new(Instruction::Null(Null)),
|
|
! => { errors.push(<>); Box::new(Instruction::Error) },
|
|
}
|
|
|
|
Args: Vec<Value<'input>> = {
|
|
"[" <args:(<Arg>)*> "]" => args
|
|
}
|
|
|
|
|
|
FPart: FunctionPart<'input> = {
|
|
<f:Function> => FunctionPart::FuncName(f),
|
|
"(" <sid:ServiceId> <f:Function> ")" => FunctionPart::ServiceIdWithFuncName(sid, f),
|
|
}
|
|
|
|
|
|
PeerPart: PeerPart<'input> = {
|
|
<pid:PeerId> => PeerPart::PeerPk(pid),
|
|
"(" <pid:PeerId> <sid:ServiceId> ")" => PeerPart::PeerPkWithServiceId(pid, sid),
|
|
}
|
|
|
|
Output: CallOutput<'input> = {
|
|
<o:Alphanumeric> => CallOutput::Scalar(o),
|
|
<o:ACCUMULATOR> => CallOutput::Accumulator(&o[..o.len()-2]),
|
|
};
|
|
|
|
Function = Value;
|
|
PeerId = Value;
|
|
ServiceId = Value;
|
|
Arg = Value;
|
|
|
|
Value: Value<'input> = {
|
|
"\"" "\"" => Value::Literal(""), // TODO: signal absence somehow?
|
|
"\"" <v: Alphanumeric> "\"" => Value::Literal(v),
|
|
<v:Alphanumeric> => Value::Variable(v),
|
|
<v:JSON_PATH> => {
|
|
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 {
|
|
_
|
|
}
|
|
|