yang_rs/
substmt.rs

1//
2// YANG - YANG sub statement
3//  Copyright (C) 2021 Toshiaki Takada
4//
5
6use std::collections::HashMap;
7
8use super::core::*;
9use super::error::*;
10use super::parser::*;
11use super::stmt::UnknownStmt;
12
13pub type StmtKeywordFn = fn() -> Keyword;
14pub type SelectionKeywordFn = fn() -> Vec<Keyword>;
15
16#[derive(Debug, Clone)]
17pub enum SubStmtWith {
18    Stmt(StmtKeywordFn),
19    Selection(SelectionKeywordFn),
20}
21
22#[derive(Debug, Clone)]
23pub enum SubStmtDef {
24    // stmt
25    HasOne(SubStmtWith),
26    // [stmt]
27    Optional(SubStmtWith),
28    // *stmt
29    ZeroOrMore(SubStmtWith),
30    // 1*stmt
31    OneOrMore(SubStmtWith),
32}
33
34#[derive(Debug, Clone)]
35pub struct RepeatCount {
36    pub count: usize,
37    pub min: usize,
38    pub max: usize,
39}
40
41///
42/// Substatements Utilities.
43///
44pub struct SubStmtUtil;
45
46impl SubStmtUtil {
47    // Parse a single statement.
48    pub fn call_stmt_parser(parser: &mut Parser, keyword: &str) -> Result<YangStmt, YangError> {
49        let f = STMT_PARSER.get(keyword).unwrap();
50        f(parser)
51    }
52
53    pub fn parse_substmts(
54        parser: &mut Parser,
55        def: Vec<SubStmtDef>,
56    ) -> Result<StmtCollection, YangError> {
57        // TBD: want to cache this definition somewhere.
58        // Keyword to index.
59        let mut k2i = HashMap::new();
60        // Index to Repeat.
61        let mut i2rep = HashMap::new();
62
63        let mut i = 0;
64        for s in def {
65            let (rep, ssw) = match s {
66                SubStmtDef::HasOne(ssw) => (
67                    RepeatCount {
68                        count: 0,
69                        min: 1,
70                        max: 1,
71                    },
72                    ssw,
73                ),
74                SubStmtDef::Optional(ssw) => (
75                    RepeatCount {
76                        count: 0,
77                        min: 0,
78                        max: 1,
79                    },
80                    ssw,
81                ),
82                SubStmtDef::ZeroOrMore(ssw) => (
83                    RepeatCount {
84                        count: 0,
85                        min: 0,
86                        max: usize::MAX,
87                    },
88                    ssw,
89                ),
90                SubStmtDef::OneOrMore(ssw) => (
91                    RepeatCount {
92                        count: 0,
93                        min: 1,
94                        max: usize::MAX,
95                    },
96                    ssw,
97                ),
98            };
99            i2rep.insert(i, rep);
100
101            match ssw {
102                SubStmtWith::Stmt(func) => {
103                    k2i.insert(func(), i);
104                }
105                SubStmtWith::Selection(func) => {
106                    for k in func() {
107                        k2i.insert(k, i);
108                    }
109                }
110            }
111
112            i += 1;
113        }
114
115        let mut stmts: StmtCollection = HashMap::new();
116
117        loop {
118            let token = parser.get_token()?;
119
120            if parser.config().debug() {
121                println!("*** [DEBUG] parse_substmts_default {:?}", token);
122            }
123            match token {
124                Token::Identifier(ref keyword) => {
125                    if k2i.contains_key(keyword as &str) {
126                        if let Some(rep) = i2rep.get_mut(k2i.get(keyword as &str).unwrap()) {
127                            let stmt = Self::call_stmt_parser(parser, &keyword)?;
128                            let v = match stmts.get_mut(keyword as &str) {
129                                Some(v) => v,
130                                None => {
131                                    stmts.insert(keyword.to_string(), Vec::new());
132                                    stmts.get_mut(keyword as &str).unwrap()
133                                }
134                            };
135                            v.push(stmt);
136                            rep.count += 1;
137                            // maybe we should validate number.
138                        } else {
139                            break;
140                        }
141                    } else if !STMT_PARSER.contains_key(keyword as &str) {
142                        // This could be "unknown" statement.
143                        let _stmt = UnknownStmt::parse(parser, keyword)?;
144                        // TBD: just parse and ignore it for now.
145                    } else {
146                        parser.save_token(token);
147                        break;
148                    }
149                }
150                _ => {
151                    parser.save_token(token);
152                    break;
153                }
154            }
155        }
156
157        // Validation.
158        for k in stmts.keys() {
159            match k2i.get(k as &str) {
160                Some(i) => {
161                    let rep = i2rep.get(i).unwrap();
162                    if rep.count < rep.min {
163                        return Err(YangError::TooFewStatement(k.clone()));
164                    }
165                    if rep.max < rep.count {
166                        return Err(YangError::TooManyStatements(k.clone()));
167                    }
168                }
169                None => return Err(YangError::UnexpectedStatement(k.clone())),
170            }
171        }
172
173        if parser.config().debug() {
174            println!("*** [DEBUG] end");
175        }
176
177        Ok(stmts)
178    }
179}