From 4451df9a9f33bcd81ab9b4ddd085c4b57d27bc29 Mon Sep 17 00:00:00 2001 From: bnewbold Date: Sun, 18 Dec 2016 23:44:18 -0800 Subject: parser: more features --- .../examples/modelica_models/heat_tank.mo | 28 ++++----- modelica-parser-lalrpop/src/ast.rs | 16 ++--- modelica-parser-lalrpop/src/parser.lalrpop | 69 ++++++++++++++++------ 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, pub component_clauses: Vec, - pub public_component_clauses: Option>, - pub protected_component_clauses: Option>, + pub public_component_clauses: Vec, + pub protected_component_clauses: Vec, pub equations: Vec, pub connections: Vec, pub extends: Vec, @@ -88,7 +88,7 @@ pub struct ComponentDeclaration { pub dimensions: Option>, pub value: Option, pub quantity: Option, - pub units: Option, + pub mods: HashMap, pub description: Option, } @@ -99,7 +99,7 @@ pub struct Component { pub specifier: String, pub name: String, pub value: Option, - pub units: Option, + pub mods: HashMap, pub description: Option, } @@ -120,6 +120,7 @@ pub enum Expr { Integer(i64), Float(f64), Boolean(bool), + StringLiteral(String), Ident(String), Der(Box), Sign(Box), @@ -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 { 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[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" "=" ";" => 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" + "partial"? "model" + connector* "equation" @@ -116,24 +120,21 @@ pub model: ModelicaModel = { extends:vec![] }, }; -value_declaration: Expr = { - "=" => value -}; - -units_declaration: String = { - "(" "unit" "=" ")" => units -}; - component_clause: ComponentClause = { - ";" => - ComponentClause { prefix:prefix, specifier:specifier, declarations:declarations }, + + + ";" => + ComponentClause { + prefix:prefix, + specifier:specifier, + declarations:declarations }, }; component_declaration: ComponentDeclaration = { - - + + (",")? => 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 = { + "=" => <>, +}; + +class_mod: HashMap = { + "(" ","?)+> ")" => { + let mut out: HashMap = HashMap::new(); + for ca in calist { + out.insert(ca.0, ca.1); + } + out + } +}; + +component_assign: (String, Expr) = { + "=" => (i, e), +}; + +annotation: () = { + "annotation" class_mod? => (), +}; + // TODO: this is very partial/cludgy array_dimensions: Vec = { "[" ","?)+> "]" => dimensions, @@ -198,6 +229,7 @@ term: Expr = { boolean => Expr::Boolean(<>), float => Expr::Float(<>), identifier => Expr::Ident(<>), + string_literal => Expr::StringLiteral(<>), "der" "(" ")" => Expr::Der(Box::new(e)), "abs" "(" ")" => Expr::MathUnaryExpr(MathUnaryFunc::Abs, Box::new(e)), "sqrt" "(" ")" => Expr::MathUnaryExpr(MathUnaryFunc::Sqrt, Box::new(e)), @@ -216,6 +248,7 @@ term: Expr = { "(" ")" => e, // Obviously a hack here, only supporting up to 4 elements in an array "[" "]" => Expr::Array(vec![e]), + "[" ";" "]" => Expr::Array(vec![e1, e2]), "[" "," "]" => Expr::Array(vec![e1, e2]), "[" "," "," "]" => Expr::Array(vec![e1, e2, e3]), "[" "," "," "," "]" => Expr::Array(vec![e1, e2, e3, e4]), -- cgit v1.2.3