aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2016-10-29 16:29:35 -0700
committerbnewbold <bnewbold@robocracy.org>2016-10-29 16:32:14 -0700
commit6915fb25b46cb9d7356caec384ab824ea78c5e4c (patch)
treeb51466034eb45a2334348588670af132e2d2d2b4
parentdf2a28f0381971cbc48ced38d9c12a780bf6f09f (diff)
downloadmodelthing-6915fb25b46cb9d7356caec384ab824ea78c5e4c.tar.gz
modelthing-6915fb25b46cb9d7356caec384ab824ea78c5e4c.zip
stub out routines for loading model+metadata from file
-rw-r--r--src/lib.rs113
-rw-r--r--src/modelica_parser.lalrpop.full171
2 files changed, 284 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 8d3f928..392f373 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,120 @@
+#[macro_use]
+extern crate log;
+
pub mod modelica_parser;
pub mod modelica_ast;
+use std::path::Path;
+use std::fs;
+use std::io::Read;
+use std::fs::File;
+
+#[derive(Debug, PartialEq)]
+struct ModelMetadata {
+ slug: String,
+ name_en: String,
+ description_en: Option<String>,
+ vars: Vec<ModelVar>,
+}
+
+#[derive(Debug, PartialEq)]
+enum ModelVarType {
+ Independent,
+ Dependent,
+ Constant,
+}
+
+#[derive(Debug, PartialEq)]
+struct ModelVar {
+ slug: String,
+ name_en: String,
+ vtype: Option<ModelVarType>,
+ latex: Option<String>,
+ units_si: Option<String>,
+}
+
+#[derive(Debug, PartialEq)]
+struct ModelEntry {
+ ast: modelica_ast::ModelicaModel,
+ metadata: ModelMetadata,
+ markdown: String,
+}
+
+// TODO: this
+fn parse_metadata(s: String) -> Result<ModelMetadata,String> {
+ Ok(ModelMetadata {
+ slug: "dummy".to_string(),
+ name_en: "Bogus Dummy Model".to_string(),
+ description_en: None,
+ vars: vec![],
+ })
+}
+
+fn load_model_entry(p: &Path) -> Result<ModelEntry,String> {
+ debug!("Attempting to load model from: {:?}", p);
+
+ let ast = {
+ let mut s = String::new();
+ try!(File::open(p.join("model.modelica")).and_then(|mut f| f.read_to_string(&mut s)).map_err(|e| e.to_string()));
+ try!(modelica_parser::parse_model(&s).map_err(|e| format!("{:?}", e)))
+ };
+
+ let metadata = {
+ let mut s = String::new();
+ try!(File::open(p.join("metadata.toml")).and_then(|mut f| f.read_to_string(&mut s)).map_err(|e| e.to_string()));
+ parse_metadata(s).unwrap()
+ };
+
+ let markdown = {
+ let mut s = String::new();
+ try!(File::open(p.join("page.md")).and_then(|mut f| f.read_to_string(&mut s)).map_err(|e| e.to_string()));
+ s
+ };
+
+ Ok(ModelEntry {
+ ast: ast,
+ metadata: metadata,
+ markdown: markdown,
+ })
+}
+
+// TODO: have this check for model.modelica etc
+fn search_models(p: &Path) -> Vec<String> {
+ if fs::metadata(p).unwrap().is_dir() {
+ fs::read_dir(p).unwrap()
+ .map(|x| x.unwrap())
+ .filter(|x| x.metadata().unwrap().is_dir())
+ .map(|x| x.path().to_string_lossy().to_string())
+ .collect()
+ } else {
+ vec![]
+ }
+}
+
+/* ******************************** Tests ******************************* */
+
+#[test]
+fn test_parse_metadata() {
+ assert_eq!(parse_metadata("asdf".to_string()).unwrap(),
+ ModelMetadata {
+ slug: "dummy".to_string(),
+ name_en: "Bogus Dummy Model".to_string(),
+ description_en: None,
+ vars: vec![],
+ });
+}
+
+#[test]
+fn test_load_model_entry() {
+ load_model_entry(Path::new("./examples/classic_gravitation/")).unwrap();
+}
+
+#[test]
+fn test_search_models() {
+ assert_eq!(search_models(Path::new("./examples/")).len() > 1, true);
+}
+
#[test]
fn test_lexical() {
assert_eq!(&format!("{:?}", modelica_parser::parse_integer("+123").unwrap()),
diff --git a/src/modelica_parser.lalrpop.full b/src/modelica_parser.lalrpop.full
new file mode 100644
index 0000000..d453bc7
--- /dev/null
+++ b/src/modelica_parser.lalrpop.full
@@ -0,0 +1,171 @@
+use std::str::FromStr;
+
+// Based on the Modelica 3.3r1 Spec
+
+grammar;
+
+//// B.1 Lexical Convetions
+
+//digit: = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+//q_ident = "’" ( q_char | s_escape ) { q_char | s_escape } "’"
+//nondigit = "_" | letters "a" to "z" | letters "A" to "Z"
+//s_char = any member of the Unicode character set (http://www.unicode.org; see Section 13.2.2 for storing as UTF-8 on files) except double-quote """, and backslash "\"
+//q_char = nondigit | digit | "!" | "#" | "$" | "%" | "&" | "(" | ")" | "*" | "+" | "," | "-" | "." | "/" | ":" | ";" | "<" | ">" | "=" | "?" | "@" | "[" | "]" | "^" | "{" | "}" | "|" | "~" | " "
+//s_escape = "\’" | "\"" | "\?" | "\\" | "\a" | "\b" | "\f" | "\n" | "\r" | "\t" | "\v"
+//
+//ident = nondigit { digit | nondigit } | q_ident
+//string = """ { s_char | s_escape } """
+//unsigned_integer = digit { digit }
+//unsigned_number = unsigned_integer [ "." [ unsigned_integer ] ] [ ( "e" | "E" ) [ "+" | "-" ] unsigned_integer ]
+
+IDENT: () = {
+ r"[a-zA-Z_][a-zA-Z_0-9]*",
+ // TODO: quoted identifier: "’" ... "’"
+};
+
+STRING: () = {
+ //"\"" r"[^\"^\\]*" "\"",
+ "\"" r"[^\\]*" "\"", // XXX: not \ and not "
+};
+
+UNSIGNED_INTEGER: () = {
+ r"\d+",
+};
+
+UNSIGNED_NUMBER: () = {
+ UNSIGNED_INTEGER,
+ r"\d+\.?\d*([eE][-+]?\d+)?",
+};
+
+
+//// B.2 Grammar
+
+//// B.2.1
+
+//stored_definition:
+// [ within [ name ] ";" ]
+// { [ final ] class_definition ";" }
+
+//// B.2.2 Class Definition
+
+
+//// B.2.7 Expressions
+
+expression: () = {
+ simple_expression,
+ if expression then expression { elseif expression then expression } else expression
+};
+
+simple_expression: () = {
+ logical_expression [ ":" logical_expression [ ":" logical_expression ] ]
+};
+
+logical_expression: () = {
+ logical_term { or logical_term }
+};
+
+logical_term: () = {
+ logical_factor { and logical_factor }
+};
+
+logical_factor: () = {
+ [ not ] relation
+};
+
+relation: () = {
+ arithmetic_expression [ rel_op arithmetic_expression ]
+};
+
+rel_op: () = {
+ "<", "<=", ">", ">=", "==", "<>"
+};
+
+arithmetic_expression: () = {
+ [ add_op ] term { add_op term }
+};
+
+add_op: () = {
+ "+", "-", ".+", ".-"
+};
+
+term: () = {
+ factor { mul_op factor }
+};
+
+mul_op: () = {
+ "*", "/", ".*", "./"
+};
+
+factor: () = {
+ primary [ ("^" | ".^") primary ]
+};
+
+primary: () = {
+ UNSIGNED_NUMBER,
+ STRING,
+ false,
+ true,
+ ( name | der | initial ) function_call_args,
+ component_reference,
+ "(" output_expression_list ")",
+ "[" expression_list { ";" expression_list } "]",
+ "{" function_arguments "}",
+ end,
+};
+
+name: () = {
+ [ "." ] IDENT { "." IDENT }
+};
+
+component_reference: () = {
+ [ "." ] IDENT [ array_subscripts ] { "." IDENT [ array_subscripts ] }
+};
+
+function_call_args: () = {
+ "(" [ function_arguments ] ")",
+ function_arguments,
+ function_argument [ "," function_arguments | for for_indices ],
+ named_arguments,
+};
+
+named_arguments: () = {
+ named_argument [ "," named_arguments ]
+};
+
+named_argument:
+ IDENT "=" function_argument
+};
+
+function_argument: () = {
+ function name "(" [ named_arguments ] ")" | expression
+};
+
+
+output_expression_list:
+ [ expression ] { "," [ expression ] }
+
+expression_list: () = {
+ expression { "," expression }
+};
+
+array_subscripts: () = {
+ "[" subscript { "," subscript } "]"
+
+};
+
+subscript: () = {
+ ":" | expression
+
+};
+
+comment: () = {
+ string_comment [ annotation ]
+};
+
+string_comment: () = {
+ [ STRING { "+" STRING } ]
+};
+
+annotation: () = {
+ annotation class_modification
+};