1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
use std::str::FromStr;
use ast::{ModelicaModel, ComponentDeclaration, ComponentClause, ComponentPrefix, Connection,
SimpleEquation, Expr, BinOperator, MathUnaryFunc};
// This is an incomplete, non-standards-compliant, minimum-viable parser
// Based on the Modelica 3.3r1 Spec
grammar;
// === Lexical Tokens ===
// Roughly (but possibly not exactly) follows B.1
pub identifier: String = {
r"[a-zA-Z_][a-zA-Z_0-9]*" => <>.to_string(),
};
string_literal: String = {
r#""[^"\\]*""# => <>.to_string(),
//<s:r#""[^"\\]*""#> => &s[1..s.len()-1],
};
pub integer: i64 = {
r"[+-]?\d+" => i64::from_str(<>).unwrap(),
};
pub float: f64 = {
r"[+-]?\d+\.\d*([eE][-+]?\d+)?" => f64::from_str(<>).unwrap(),
};
pub boolean: bool = {
"true" => true,
"false" => false,
};
// Grammar
pub model: ModelicaModel = {
"model" <n:identifier> <desc:string_literal?> <cpc:component_clause*> "equation" <cc:connect_clause*> <se:simple_equation*> "end" identifier ";" =>
ModelicaModel { name:n, description:desc, component_clauses:cpc, connections:cc, equations:se, extends:vec![] },
};
value_declaration: Expr = {
"=" <value:expr> => value
};
units_declaration: String = {
"(" "unit" "=" <units:string_literal> ")" => units
};
component_clause: ComponentClause = {
<prefix:component_prefix?> <specifier:identifier> <declarations:component_declaration+> ";" =>
ComponentClause { prefix:prefix, specifier:specifier, declarations:declarations },
};
component_declaration: ComponentDeclaration = {
<name:identifier> <units:units_declaration?> <value:value_declaration?> <desc:string_literal?> (",")? =>
ComponentDeclaration { name:name, description:desc, value:value, units:units, quantity:None },
};
component_prefix: ComponentPrefix = {
"flow" => ComponentPrefix::Flow,
"stream" => ComponentPrefix::Stream,
"input" => ComponentPrefix::Input,
"output" => ComponentPrefix::Output,
"discrete" => ComponentPrefix::Discrete,
"parameter" => ComponentPrefix::Parameter,
"constant" => ComponentPrefix::Constant,
};
simple_equation: SimpleEquation = {
<lhs:expr> ":=" <rhs:expr> ";" => SimpleEquation {lhs:lhs, rhs:rhs},
<lhs:expr> "=" <rhs:expr> ";" => SimpleEquation {lhs:lhs, rhs:rhs},
};
connect_clause: Connection = {
"connect" "(" <a:identifier> "," <b:identifier> ")" ";" =>
Connection { a: a.to_string(), b: b.to_string()},
};
// This weird expr/factor/term hierarchy is for binary operator precedence
expr: Expr = {
<lhs:expr> "+" <rhs:factor> =>
Expr::BinExpr(BinOperator::Add, Box::new(lhs), Box::new(rhs)),
<lhs:expr> "-" <rhs:factor> =>
Expr::BinExpr(BinOperator::Subtract, Box::new(lhs), Box::new(rhs)),
factor,
};
factor: Expr = {
<lhs:factor> "*" <rhs:term> =>
Expr::BinExpr(BinOperator::Multiply, Box::new(lhs), Box::new(rhs)),
<lhs:factor> "/" <rhs:term> =>
Expr::BinExpr(BinOperator::Divide, Box::new(lhs), Box::new(rhs)),
<lhs:factor> "^" <rhs:term> =>
Expr::BinExpr(BinOperator::Divide, Box::new(lhs), Box::new(rhs)),
"-" <t:term> =>
Expr::BinExpr(BinOperator::Multiply, Box::new(Expr::Integer(-1)), Box::new(t)),
term,
};
// TODO: elementwise operators (".+", "./", ".*", ".-")
term: Expr = {
integer => Expr::Integer(<>),
float => Expr::Float(<>),
identifier => Expr::Ident(<>),
"der" "(" <e:expr> ")" => Expr::Der(Box::new(e)),
"abs" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Abs, Box::new(e)),
"sqrt" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Sqrt, Box::new(e)),
"sin" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Sin, Box::new(e)),
"cos" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Cos, Box::new(e)),
"tan" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Tan, Box::new(e)),
"asin" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Asin, Box::new(e)),
"acos" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Acos, Box::new(e)),
"atan" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Atan, Box::new(e)),
"sinh" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Sinh, Box::new(e)),
"cosh" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Cosh, Box::new(e)),
"tanh" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Tanh, Box::new(e)),
"exp" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Exp, Box::new(e)),
"log" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Log, Box::new(e)),
"log10" "(" <e:expr> ")" => Expr::MathUnaryExpr(MathUnaryFunc::Log10, Box::new(e)),
"(" <e:expr> ")" => e,
};
|