mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-14 19:45:39 +00:00
91 lines
2.5 KiB
Plaintext
91 lines
2.5 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" <peer:PeerPart> <f:FPart> <args:Args> <output:Output> ")" =>
|
||
|
Box::new(Instruction::Call(Call{peer, f, args, output})),
|
||
|
|
||
|
"(" "fold" <iterable:Alphanumeric> <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),
|
||
|
}
|
||
|
|
||
|
// TODO: make output one of _ () "" and absence
|
||
|
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,
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
Alphanumeric = ALPHANUMERIC;
|
||
|
|
||
|
match {
|
||
|
r"[\w_-]+" => ALPHANUMERIC,
|
||
|
r"[\w_-]+\[\]" => ACCUMULATOR,
|
||
|
r"[\w_-]+\.\$[^ ]+" => JSON_PATH,
|
||
|
"%current_peer_id%" => CURRENT_PEER_ID,
|
||
|
"seq",
|
||
|
"call",
|
||
|
"null",
|
||
|
"par",
|
||
|
"xor",
|
||
|
"fold",
|
||
|
"next",
|
||
|
} else {
|
||
|
_
|
||
|
}
|
||
|
|