aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2016-12-18 23:44:18 -0800
committerbnewbold <bnewbold@robocracy.org>2016-12-18 23:44:18 -0800
commit4451df9a9f33bcd81ab9b4ddd085c4b57d27bc29 (patch)
treec8a60bd419f3ce873ff377227b01ad44c2258d76
parent25ec87c63a5ba79846e147e3d153bf8d884a664e (diff)
downloadmodelthing-4451df9a9f33bcd81ab9b4ddd085c4b57d27bc29.tar.gz
modelthing-4451df9a9f33bcd81ab9b4ddd085c4b57d27bc29.zip
parser: more features
-rw-r--r--modelica-parser-lalrpop/examples/modelica_models/heat_tank.mo28
-rw-r--r--modelica-parser-lalrpop/src/ast.rs16
-rw-r--r--modelica-parser-lalrpop/src/parser.lalrpop69
3 files changed, 74 insertions, 39 deletions
diff --git a/modelica-parser-lalrpop/examples/modelica_models/heat_tank.mo b/modelica-parser-lalrpop/examples/modelica_models/heat_tank.mo
index dde1ae0..320c3f5 100644
--- a/modelica-parser-lalrpop/examples/modelica_models/heat_tank.mo
+++ b/modelica-parser-lalrpop/examples/modelica_models/heat_tank.mo
@@ -1,17 +1,17 @@
model HeatTankT
- parameter Area=1;
- connector TankStream
- Real pressure;
- flow Real volumeFlowRate;
- Real temp;
- end TankStream;
- TankStream Inlet, Outlet;
- Real level;
- Real temp;
+ parameter Real Area=1;
+ connector TankStream
+ Real pressure;
+ flow Real volumeFlowRate;
+ Real temp;
+ end TankStream;
+ TankStream Inlet, Outlet;
+ Real level;
+ Real temp;
equation
- Area*der(level) = Inlet.volumeFlowRate + Outlet.volumeFlowRate;
- Outlet.pressure = Inlet.pressure;
-Area*level*der(temp) = Inlet.volumeFlowRate*Inlet.temp +
- Outlet.volumeFlowRate*Outlet.temp;
-Outlet.temp = temp;
+ Area*der(level) = Inlet.volumeFlowRate + Outlet.volumeFlowRate;
+ Outlet.pressure = Inlet.pressure;
+ Area*level*der(temp) = Inlet.volumeFlowRate*Inlet.temp +
+ Outlet.volumeFlowRate*Outlet.temp;
+ Outlet.temp = temp;
end HeatTankT;
diff --git a/modelica-parser-lalrpop/src/ast.rs b/modelica-parser-lalrpop/src/ast.rs
index addb90f..e367b10 100644
--- a/modelica-parser-lalrpop/src/ast.rs
+++ b/modelica-parser-lalrpop/src/ast.rs
@@ -7,7 +7,7 @@ use std::collections::HashMap;
// A valid .mo file will be a sequence of these
#[derive(Clone, PartialEq)]
pub enum ModelicaCode {
- Class, // unimpl
+ Class, // unimpl; generic
Model(ModelicaModel),
Record, // unimpl
Block(ModelicaBlock),
@@ -39,8 +39,8 @@ pub struct ModelicaBlock {
pub name: String,
pub description: Option<String>,
pub component_clauses: Vec<ComponentClause>,
- pub public_component_clauses: Option<Vec<ComponentClause>>,
- pub protected_component_clauses: Option<Vec<ComponentClause>>,
+ pub public_component_clauses: Vec<ComponentClause>,
+ pub protected_component_clauses: Vec<ComponentClause>,
pub equations: Vec<SimpleEquation>,
pub connections: Vec<Connection>,
pub extends: Vec<String>,
@@ -88,7 +88,7 @@ pub struct ComponentDeclaration {
pub dimensions: Option<Vec<i64>>,
pub value: Option<Expr>,
pub quantity: Option<String>,
- pub units: Option<String>,
+ pub mods: HashMap<String, Expr>,
pub description: Option<String>,
}
@@ -99,7 +99,7 @@ pub struct Component {
pub specifier: String,
pub name: String,
pub value: Option<Expr>,
- pub units: Option<String>,
+ pub mods: HashMap<String, Expr>,
pub description: Option<String>,
}
@@ -120,6 +120,7 @@ pub enum Expr {
Integer(i64),
Float(f64),
Boolean(bool),
+ StringLiteral(String),
Ident(String),
Der(Box<Expr>),
Sign(Box<Expr>),
@@ -172,7 +173,7 @@ impl ModelicaModel {
specifier: clause.specifier.clone(),
name: dec.name.clone(),
value: dec.value.clone(),
- units: dec.units.clone(),
+ mods: dec.mods.clone(),
description: dec.description.clone(),
}))
}
@@ -237,7 +238,7 @@ impl Expr {
pub fn identifiers(&self) -> Vec<String> {
use self::Expr::*;
match *self {
- Integer(_) | Float(_) | Boolean(_) => vec![],
+ Integer(_) | Float(_) | Boolean(_) | StringLiteral(_) => vec![],
Ident(ref s) => vec![s.clone()],
Der(ref e) | Sign(ref e) => e.identifiers(),
MathUnaryExpr(_, ref e) => e.identifiers(),
@@ -342,6 +343,7 @@ impl Debug for Expr {
Integer(e) => write!(fmt, "{}", e),
Float(e) => write!(fmt, "{}", e),
Boolean(e) => write!(fmt, "{}", e),
+ StringLiteral(ref e) => write!(fmt, "\"{}\"", e),
Ident(ref e) => write!(fmt, "{}", e),
Der(ref e) => write!(fmt, "der({:?})", e),
Sign(ref e) => write!(fmt, "sign({:?})", e),
diff --git a/modelica-parser-lalrpop/src/parser.lalrpop b/modelica-parser-lalrpop/src/parser.lalrpop
index 447c51f..b05ad76 100644
--- a/modelica-parser-lalrpop/src/parser.lalrpop
+++ b/modelica-parser-lalrpop/src/parser.lalrpop
@@ -1,4 +1,5 @@
use std::str::FromStr;
+use std::collections::HashMap;
use ast::{ModelicaCode, ModelicaPackage, ModelicaBlock, ModelicaConnector, ModelicaType, ModelicaModel, ComponentDeclaration,
ComponentClause, ComponentPrefix, Connection, SimpleEquation, Expr,
BinOperator, MathUnaryFunc};
@@ -6,18 +7,20 @@ use ast::{ModelicaCode, ModelicaPackage, ModelicaBlock, ModelicaConnector, Model
// 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(),
+ r"[a-zA-Z_][a-zA-Z_0-9]*\.[a-zA-Z_0-9]*" => <>.to_string(),
};
string_literal: String = {
r#""[^"\\]*""# => <>.to_string(),
- //<s:r#""[^"\\]*""#> => &s[1..s.len()-1],
};
pub integer: i64 = {
@@ -71,7 +74,7 @@ pub connector: ModelicaConnector = {
component_clauses:cpc, },
};
-pub type_declaration: ModelicaType = {
+type_declaration: ModelicaType = {
"type" <n:identifier> <desc:string_literal?>
"=" <cpd:component_declaration> ";" =>
ModelicaType {
@@ -93,16 +96,17 @@ pub block: ModelicaBlock = {
name:n,
description:desc,
component_clauses:cpc,
- public_component_clauses:public,
- protected_component_clauses:protected,
+ public_component_clauses: { public.unwrap_or(vec![]) },
+ protected_component_clauses: { protected.unwrap_or(vec![]) },
connections:cc,
equations:se,
extends:vec![] },
};
pub model: ModelicaModel = {
- "model" <n:identifier> <desc:string_literal?>
+ "partial"? "model" <n:identifier> <desc:string_literal?>
<cpc:component_clause*>
+ connector*
"equation"
<cc:connect_clause*>
<se:simple_equation*>
@@ -116,24 +120,21 @@ pub model: ModelicaModel = {
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 },
+ <prefix:component_prefix?>
+ <specifier:identifier>
+ <declarations:component_declaration+> ";" =>
+ ComponentClause {
+ prefix:prefix,
+ specifier:specifier,
+ declarations:declarations },
};
component_declaration: ComponentDeclaration = {
<name:identifier>
<ad:array_dimensions?>
- <units:units_declaration?>
- <value:value_declaration?>
+ <mods:class_mod?>
+ <value:assignment_mod?>
<desc:string_literal?>
(",")? =>
ComponentDeclaration {
@@ -141,10 +142,40 @@ component_declaration: ComponentDeclaration = {
dimensions:ad,
description:desc,
value:value,
- units:units,
+ mods: { mods.unwrap_or(HashMap::new()) },
quantity:None },
};
+// component_assigns happen in:
+// component declarations
+// argument lists
+// class_modifications (parens) happen in the above plus:
+// annotations
+// extends
+// RHS of single-line class defs
+
+assignment_mod: Expr = {
+ "=" <expr> => <>,
+};
+
+class_mod: HashMap<String, Expr> = {
+ "(" <calist:(<component_assign> ","?)+> ")" => {
+ let mut out: HashMap<String, Expr> = HashMap::new();
+ for ca in calist {
+ out.insert(ca.0, ca.1);
+ }
+ out
+ }
+};
+
+component_assign: (String, Expr) = {
+ <i:identifier> "=" <e:expr> => (i, e),
+};
+
+annotation: () = {
+ "annotation" class_mod? => (),
+};
+
// TODO: this is very partial/cludgy
array_dimensions: Vec<i64> = {
"[" <dimensions:(<integer> ","?)+> "]" => dimensions,
@@ -198,6 +229,7 @@ term: Expr = {
boolean => Expr::Boolean(<>),
float => Expr::Float(<>),
identifier => Expr::Ident(<>),
+ string_literal => Expr::StringLiteral(<>),
"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)),
@@ -216,6 +248,7 @@ term: Expr = {
"(" <e:expr> ")" => e,
// Obviously a hack here, only supporting up to 4 elements in an array
"[" <e:expr> "]" => Expr::Array(vec![e]),
+ "[" <e1:expr> ";" <e2:expr> "]" => Expr::Array(vec![e1, e2]),
"[" <e1:expr> "," <e2:expr> "]" => Expr::Array(vec![e1, e2]),
"[" <e1:expr> "," <e2:expr> "," <e3:expr> "]" => Expr::Array(vec![e1, e2, e3]),
"[" <e1:expr> "," <e2:expr> "," <e3:expr> "," <e4:expr> "]" => Expr::Array(vec![e1, e2, e3, e4]),