use crate::model::*;
use crate::parser::*;
use line_col::LineColLookup;
use std::time::Duration;
grammar(lookup: &LineColLookup<'input>, parser: &mut Parser);
match {
r"\s*" => { }, // The default whitespace skipping is disabled an `ignore pattern` is specified
r"//[^\n\r]*[\n\r]*" => { }, // Skip `// comments`
r"/\*[^*]*\*+(?:[^/*][^*]*\*+)*/" => { }, // Skip `/* comments */`
_
}
//------------------------- Skillset -------------------------
pub Skillset: () = "skillset" <x:Identifier> <types:TypeDef?> "{"
<data:Data>
<resources:Resource>
<events:Event>
<skills:Skill>
"}" => {
let mut skillset = Skillset::new(x.name, Some(x.position));
if let Some(types) = types {
for x in types {
skillset.add_type(x);
}
}
for x in data {
skillset.add_data(x);
}
for x in resources {
skillset.add_resource(x);
}
for x in events {
skillset.add_event(x);
}
for x in skills {
skillset.add_skill(x);
}
parser.skillset = skillset
};
//------------------------- Type -------------------------
TypeDef: Vec<RlType> = "<" <l:IdentifierList> ">" => {
let mut v = vec![];
for x in l {
let t = RlType::new(x.name, Some(x.position));
v.push(t);
}
v
};
TypeRef: Reference<TypeId> = <x:Identifier> => {
Reference::Unresolved(x.name, Some(x.position))
};
//------------------------- Data -------------------------
Data: Vec<Data> = {
<v: DataSingle*> => v,
<v: DataBlock> => v,
};
DataSingle: Data = "data" <d:DataDef> => d;
DataBlock: Vec<Data> = "data" "{" <l:DataDef*> "}" => l;
DataDef: Data = <x:Identifier> ":" <t:TypeRef> <p:Period?> => Data::new(x.name, t, p, Some(x.position));
//------------------------- Resource -------------------------
Resource: Vec<Resource> = {
<v: ResourceSingle*> => v,
<v: ResourceBlock> => v,
};
ResourceSingle: Resource = "resource" <x:ResourceDef> => x;
ResourceBlock: Vec<Resource> = "resource" "{" <l:ResourceDef*> "}" => l;
ResourceDef: Resource = <x:Identifier> "{" <s:StateDef> <i:InitialDef> <t:Transitions> "}" => {
let mut resource = Resource::new(x.name, Some(x.position));
for x in s {
resource.add_state(x);
}
resource.set_initial(i);
resource.set_transitions(t);
resource
};
ResourceRef: Reference<ResourceId> = <x:Identifier> => Reference::Unresolved(x.name, Some(x.position));
//------------------------- State -------------------------
StateDef: Vec<State> = "state" "{" <l:Identifier*> "}" => {
let mut v = Vec::new();
for x in l {
v.push(State::new(x.name, Some(x.position)));
}
v
};
InitialDef: Reference<StateId> = "initial" <s:StateRef> => s;
StateRef: Reference<StateId> = <x:Identifier> => Reference::Unresolved(x.name, Some(x.position));
//------------------------- Transition -------------------------
Transitions: Transitions = {
"transition" "all" => Transitions::All,
"transition" "{" <l:Transition*> "}" => Transitions::List(l),
};
Transition: Transition = <s:StateRef> "->" <d:StateRef> => Transition::new(s, d);
//------------------------- Event -------------------------
Event: Vec<Event> = {
<v: EventSingle*> => v,
<v: EventBlock> => v,
};
EventSingle: Event = "event" <e:EventDef> => e;
EventBlock: Vec<Event> = "event" "{" <l:EventDef*> "}" => l;
EventDef: Event = <x:Identifier> "{" <g:Guard?> <l:Effects> "}" => Event::new(x.name, g, l, Some(x.position));
Guard: Expr = "guard" <e:Expr> => e;
//------------------------- Skill -------------------------
Skill: Vec<Skill> = {
<v: SkillSingle*> => v,
<v: SkillBlock> => v,
};
SkillSingle: Skill = "skill" <s:SkillDef> => s;
SkillBlock: Vec<Skill> = "skill" "{" <l:SkillDef*> "}" => l;
SkillDef: Skill = <x:Identifier> "{"
<inp:Input>
<out:Output>
<pre:Precondition>
<sta:Start?>
<inv:Invariant>
<pro:Progress?>
<int:Interrupt?>
<suc:Success>
<fai:Failure>
"}" => {
let mut skill = Skill::new(x.name, Some(x.position));
for x in inp {
skill.add_input(x);
}
for x in out {
skill.add_output(x);
}
for x in pre {
skill.add_precondition(x);
}
if let Some(e) = sta {
skill.set_start(e);
}
for x in inv {
skill.add_invariant(x);
}
if let Some(progress) = pro {
skill.set_progress(progress);
}
if let Some(int) = int {
skill.set_interrupt(int);
}
for x in suc {
skill.add_success(x);
}
for x in fai {
skill.add_failure(x);
}
//
skill
};
//------------------------- Input -------------------------
Input: Vec<Variable> = {
<v: InputSingle*> => v,
<v: InputBlock> => v,
};
InputSingle: Variable = "input" <v:Variable> => v;
InputBlock: Vec<Variable> = "input" "{" <l:Variable*> "}" => l;
//------------------------- Output -------------------------
Output: Vec<Variable> = {
<v: OutputSingle*> => v,
<v: OutputBlock> => v,
};
OutputSingle: Variable = "output" <v:Variable> => v;
OutputBlock: Vec<Variable> = "output" "{" <l:Variable*> "}" => l;
//------------------------- Precondition -------------------------
Precondition: Vec<Precondition> = {
<v: PreconditionSingle*> => v,
<v: PreconditionBlock> => v,
};
PreconditionSingle: Precondition = "precondition" <p:PreconditionDef> => p;
PreconditionBlock: Vec<Precondition> = "precondition" "{" <l:PreconditionDef*> "}" => l;
PreconditionDef: Precondition = <n:Identifier> ":" <e:Expr> => Precondition::new(n.name, e, Some(n.position));
//------------------------- Precondition -------------------------
Postcondition: Vec<Postcondition> = {
<v: PostconditionSingle*> => v,
<v: PostconditionBlock> => v,
};
PostconditionSingle: Postcondition = "postcondition" <p:PostconditionDef> => p;
PostconditionBlock: Vec<Postcondition> = "postcondition" "{" <l:PostconditionDef*> "}" => l;
PostconditionDef: Postcondition = <n:Identifier> ":" <e:Expr> => Postcondition::new(n.name, e, Some(n.position));
//------------------------- Start -------------------------
Start: Vec<Effect> = {
<v: StartSingle> => v,
<v: StartBlock> => v,
};
StartSingle: Vec<Effect> = "start" <e:Effect> => vec![e];
StartBlock: Vec<Effect> = "start" "{" <l:Effect*> "}" => l;
//------------------------- Invariant -------------------------
Invariant: Vec<Invariant> = {
<v: InvariantSingle*> => v,
<v: InvariantBlock> => v,
};
InvariantSingle: Invariant = "invariant" <i:InvariantDef> => i;
InvariantBlock: Vec<Invariant> = "invariant" "{" <v:InvariantDef*> "}" => v;
InvariantDef: Invariant = <n:Identifier> "{" "guard" <e:Expr> <o:Effects?> "}" => {
let l = match o {
Some(v) => v,
None => Vec::new(),
};
Invariant::new(n.name, e, l, Some(n.position))
};
//------------------------- Progress -------------------------
Progress: Progress = <l:@L>"progress" "{" <p:Period> <m:Message> "}" => {
let position = Position::new(parser.file(), lookup, l);
Progress::new(p, m, Some(position))
};
Message: Vec<Variable> = {
<v: MessageSingle*> => v,
<v: MessageBlock> => v,
};
MessageSingle: Variable = "message" <v:Variable> => v;
MessageBlock: Vec<Variable> = "message" "{" <v:Variable*> "}" => v;
//------------------------- Interrupt -------------------------
Interrupt: Interrupt = <l:@L>"interrupt" "{" <p:Postcondition> <e:Effects> "}" => {
let position = Position::new(parser.file(), lookup, l);
Interrupt::new(p, e, Some(position))
};
//------------------------- Success -------------------------
Success: Vec<Success> = {
<v: SuccessSingle*> => v,
<v: SuccessBlock> => v,
};
SuccessSingle: Success = "success" <i:SuccessDef> => i;
SuccessBlock: Vec<Success> = "success" "{" <v:SuccessDef*> "}" => v;
SuccessDef: Success = <n:Identifier> "{" <p:Postcondition> <e:Effects?> "}" => {
let l = match e {
Some(v) => v,
None => Vec::new(),
};
Success::new(n.name, p, l, Some(n.position))
};
//------------------------- Failure -------------------------
Failure: Vec<Failure> = {
<v: FailureSingle*> => v,
<v: FailureBlock> => v,
};
FailureSingle: Failure = "failure" <i:FailureDef> => i;
FailureBlock: Vec<Failure> = "failure" "{" <v:FailureDef*> "}" => v;
FailureDef: Failure = <n:Identifier> "{" <p:Postcondition> <e:Effects?> "}" => {
let l = match e {
Some(v) => v,
None => Vec::new(),
};
Failure::new(n.name, p, l, Some(n.position))
};
//------------------------- Variable -------------------------
Variable: Variable = <x:Identifier> ":" <t:TypeRef> => Variable::new(x.name, t, Some(x.position));
//------------------------- Effect -------------------------
Effects: Vec<Effect> = {
<v: EffectSingle> => v,
<v: EffectBlock> => v
};
EffectSingle: Vec<Effect> = "effect" <e:Effect> => vec![e];
EffectBlock: Vec<Effect> = "effect" "{" <l:Effect*> "}" => l;
Effect: Effect = <r:ResourceRef> "->" <s:StateRef> => Effect::new(r, s);
//------------------------- BoolValue -------------------------
BoolValue: bool = {
"false" => false,
"true" => true,
};
//------------------------- Expr -------------------------
Expr: Expr = ImpliesExpr;
ImpliesExpr: Expr = {
<left:ImpliesExpr> "=>" <right:OrExpr> => {
Expr::Implies(Box::new(left), Box::new(right))
},
OrExpr,
};
OrExpr: Expr = {
<left:OrExpr> "or" <right:AndExpr> => {
Expr::Or(Box::new(left), Box::new(right))
},
AndExpr,
};
AndExpr: Expr = {
<left:AndExpr> "and" <right:NotExpr> => {
Expr::And(Box::new(left), Box::new(right))
},
NotExpr,
};
NotExpr: Expr = {
"not" <e: NotExpr> => {
Expr::Not(Box::new(e))
},
Term,
};
Term: Expr = {
"false" => Expr::False,
"true" => Expr::True,
<r:ResourceRef> "==" <s:StateRef> => Expr::ResourceEq(r, s),
<r:ResourceRef> "!=" <s:StateRef> => Expr::ResourceNe(r, s),
"(" <Expr> ")",
};
//------------------------- Lexer -------------------------
String: String = <s:r#"".+""#> => s[1..s.len()-1].to_string();
Duration: Duration = {
<i:UInteger> "sec" => Duration::from_secs(i),
<i:UInteger> "ms" => Duration::from_millis(i),
};
Period: Duration = "period" <p:Duration> => p;
UInteger: u64 = <i:r"[0-9]+"> => i.parse::<u64>().unwrap();
Identifier: Identifier = <l:@L> <s:r"[a-zA-Z_][a-zA-Z_0-9]*"> <r:@R> => {
Identifier::new(parser.file(), lookup, s, l)
};
IdentifierList: Vec<Identifier> = <i: Identifier> <l: CommaIdentifier*> => {
let mut v = vec![i];
v.extend(l);
v
};
CommaIdentifier: Identifier = "," <i:Identifier> => {
i
};