use crate::ast;
use crate::error::LexicalError;
use crate::lexer;
use crate::location;
grammar;
pub InputFile: ast::File = StartFile <u:Use*> <m:Model> => ast::File {
uses: u,
model: m,
};
Use: ast::Use = "use" <m:name+> <o:UseOrigin> "\n" => ast::Use {
model: m.join(" "),
origin: o,
};
UseOrigin: ast::UseOrigin = {
"by" <s:string> => ast::UseOrigin::Site(s),
"by" <u:name+> => ast::UseOrigin::User(u.join(" ")),
=> ast::UseOrigin::Local,
}
Model: ast::Model = <e:IsExtern> "[" <n:name+> "]" "\n" <i:ModelInner> => ast::Model {
name: n.join(" "),
inner: i,
is_extern: e,
};
IsExtern: bool = {
"extern" => true,
=> false,
}
ModelInner: ast::ModelInner = {
Indent <v:Variable*> <c:Model*> <g:Graph*> Dedent => ast::ModelInner {
variables: v,
children: c,
graph: g,
},
=> ast::ModelInner::default(),
}
Variable: ast::Variable = {
"*" <nd:VariableNameDesc> <v:MaybeValue> "\n" => ast::Variable {
name: nd.name,
description: nd.description,
default: v,
is_model: false,
},
"*" "[" <nd:VariableNameDesc> "]" <v:MaybeValueModel> "\n" => ast::Variable {
name: nd.name,
description: nd.description,
default: v,
is_model: true,
},
};
VariableNameDesc: ast::temp::VariableNameDesc = {
<n:name> ":" <d:name+> => ast::temp::VariableNameDesc {
name: Some(n),
description: d.join(" "),
},
<d:name+> => ast::temp::VariableNameDesc {
name: None,
description: d.join(" "),
},
}
MaybeValue: Option<ast::Value> = {
"=" <v:Value> => Some(v),
=> None,
}
MaybeValueModel: Option<ast::Value> = {
"=" <m: name+> => Some(ast::Value::Model(m.join(" "))),
=> None,
}
Value: ast::Value = {
<b: Bool> => ast::Value::Bool(b),
<i: int> => ast::Value::Int(i),
<u: uint> => ast::Value::UInt(u),
<r: float> => ast::Value::Real(r),
}
Graph: ast::Graph = {
<n:Node> <p:OneOrMore<GraphPass, "+">> <s:Shapes> "\n" => ast::Graph {
id: n,
passes: p,
inline: None,
shapes: s,
},
<n:Node> <m:Model> => ast::Graph {
id: n,
passes: vec![ast::GraphPass {
name: m.name.clone(),
repeat: 1,
..Default::default()
}],
inline: Some(m),
shapes: None,
},
}
GraphPass: ast::GraphPass = {
<n:name+> <a:GraphPassArgs> <r:GraphPassRepeat> => ast::GraphPass {
name: n.join(" "),
args: a,
repeat: r,
},
}
GraphPassArgs: Vec<ast::GraphPassArg> = {
"(" <a:OneOrMore<GraphPassArg, ",">> ")" => a,
=> vec![],
}
GraphPassArg: ast::GraphPassArg = {
<n:OneOrMore<NodeArg, "+">> => ast::GraphPassArg::NodeArg(n),
<n:name> "=" <v:Value> => ast::GraphPassArg::Keyword {
name: n,
value: v,
},
}
GraphPassRepeat: u64 = {
"*" <n:uint> => n,
=> 1,
}
Shapes: Option<ast::Shapes> = {
"=" <s: OneOrMore<IndexedShape, ",">> => Some(ast::Shapes::many(s)),
"=" <s: Shape> => Some(ast::Shapes::one(s)),
=> None,
}
IndexedShape: (u64, ast::Shape) = "[" <i: uint> ":" <s: Shape> "]" => (i, s);
Shape: ast::Shape = <d: OneOrMore<DimExpr, ",">> => ast::Shape(d);
DimExpr: ast::Dim = {
<lhs:DimExpr> "+" <rhs:DimTerm> => ast::Dim::Expr {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
op: ast::DimOp::Add,
},
<lhs:DimExpr> "-" <rhs:DimTerm> => ast::Dim::Expr {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
op: ast::DimOp::Sub,
},
<t:DimTerm> => t,
}
DimTerm: ast::Dim = {
<lhs:DimTerm> "*" <rhs:DimAtom> => ast::Dim::Expr {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
op: ast::DimOp::Mul,
},
<lhs:DimTerm> "/" <rhs:DimAtom> => ast::Dim::Expr {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
op: ast::DimOp::Div,
},
"(" <e:DimExpr> ")" => e,
<a:DimAtom> => a,
}
DimAtom: ast::Dim = {
<u:uint> => ast::Dim::Fixed(u),
<n:name> => ast::Dim::Semantic(n),
}
Node: ast::Node = "#" <u:uint> => u;
NodeArg: ast::NodeArg = {
<n: Node> ":" <a: uint> => ast::NodeArg {
node: n,
arg: a,
},
<n: Node> => ast::NodeArg {
node: n,
arg: 0,
},
};
int: i64 = "-" <u:uint> => u as i64;
Bool: bool = {
"yes" => true,
"no" => false,
}
#[inline]
OneOrMore<T, S>: Vec<T> = {
<i1: T> <i2:(S T)*> S? => {
let mut items = vec![i1];
items.extend(i2.into_iter().map(|e| e.1));
items
}
};
// Hook external lexer:
extern {
type Location = location::Location;
type Error = LexicalError;
enum lexer::Tok {
Indent => lexer::Tok::Indent,
Dedent => lexer::Tok::Dedent,
uint => lexer::Tok::UInt { value: <u64> },
float => lexer::Tok::Float { value: <f64> },
string => lexer::Tok::String { value: <String> },
bytes => lexer::Tok::Bytes { value: <Vec<u8>> },
name => lexer::Tok::Name { name: <String> },
StartFile => lexer::Tok::StartFile,
"\n" => lexer::Tok::Newline,
"=" => lexer::Tok::Equal,
"#" => lexer::Tok::Number,
"." => lexer::Tok::Dot,
"," => lexer::Tok::Comma,
"(" => lexer::Tok::Lpar,
")" => lexer::Tok::Rpar,
"[" => lexer::Tok::Lbracket,
"]" => lexer::Tok::Rbracket,
":" => lexer::Tok::Colon,
"+" => lexer::Tok::Add,
"-" => lexer::Tok::Sub,
"*" => lexer::Tok::Mul,
"/" => lexer::Tok::Div,
"**" => lexer::Tok::Pow,
"--" => lexer::Tok::Seq,
"yes" => lexer::Tok::BoolYes,
"no" => lexer::Tok::BoolNo,
"use" => lexer::Tok::Use,
"by" => lexer::Tok::By,
"extern" => lexer::Tok::Extern,
}
}