aboutsummaryrefslogtreecommitdiffstats
path: root/src/modelica_parser.lalrpop
blob: f5d795866e643c33c75f19ffdf1d435cd107ec41 (plain)
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
use std::str::FromStr;
use modelica_ast::{ModelicaModel,Component, ComponentPrefix, Connection,
    SimpleEquation, Expr, BinOperator};

// This is an incomplete, non-standards-compliant, minimum-viable parser

grammar;

// Lexical Tokens

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(),
};


// Grammar

pub model: ModelicaModel = {
    "model" <n:identifier> <cd:component_declaration*> "equation" <cc:connect_clause*> <se:simple_equation*> "end" identifier ";" =>
        ModelicaModel { name:n, components: cd, connections: cc, equations: se, extends: vec![] },
};

value_declaration: Expr = {
    "=" <value:expr> => value
};

units_declaration: String = {
    "(" "unit" "=" <units:string_literal> ")" => units
};

component_declaration: Component = {
    <prefix:component_prefix?> <specifier:identifier> <name:identifier> <units:units_declaration?> <value:value_declaration?> <desc:string_literal?> ";" =>
        Component { prefix:prefix, specifier:specifier, name:name, description:desc, value:value, units:units },
};

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},
};

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,
};

term: Expr = {
    integer => Expr::Integer(<>),
    float => Expr::Float(<>),
    identifier => Expr::Ident(<>),
    "der" "(" <e:expr> ")" => Expr::Der(Box::new(e)),
    "abs" "(" <e:expr> ")" => Expr::Abs(Box::new(e)),
    "(" <e:expr> ")" => e,
};