diff options
| author | bnewbold <bnewbold@robocracy.org> | 2016-10-29 16:29:35 -0700 | 
|---|---|---|
| committer | bnewbold <bnewbold@robocracy.org> | 2016-10-29 16:32:14 -0700 | 
| commit | 6915fb25b46cb9d7356caec384ab824ea78c5e4c (patch) | |
| tree | b51466034eb45a2334348588670af132e2d2d2b4 | |
| parent | df2a28f0381971cbc48ced38d9c12a780bf6f09f (diff) | |
| download | modelthing-6915fb25b46cb9d7356caec384ab824ea78c5e4c.tar.gz modelthing-6915fb25b46cb9d7356caec384ab824ea78c5e4c.zip  | |
stub out routines for loading model+metadata from file
| -rw-r--r-- | src/lib.rs | 113 | ||||
| -rw-r--r-- | src/modelica_parser.lalrpop.full | 171 | 
2 files changed, 284 insertions, 0 deletions
@@ -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 +};  | 
