yang_rs/
core.rs

1//
2// YANG - YANG core rules and enums.
3//   Copyright (C) 2021 Toshiaki Takada
4//
5
6use std::collections::HashMap;
7use std::fmt;
8
9use super::error::*;
10use super::parser::*;
11use super::stmt::*;
12
13// Statement Parser initialization.
14lazy_static! {
15    pub static ref STMT_PARSER: HashMap<Keyword, StmtParserFn> = {
16        let mut m = HashMap::new();
17
18        m.insert("module", ModuleStmt::parse as StmtParserFn);
19        m.insert("submodule", SubmoduleStmt::parse as StmtParserFn);
20        m.insert("yang-version", YangVersionStmt::parse as StmtParserFn);
21        m.insert("import", ImportStmt::parse as StmtParserFn);
22        m.insert("include", IncludeStmt::parse as StmtParserFn);
23        m.insert("namespace", NamespaceStmt::parse as StmtParserFn);
24        m.insert("belongs-to", BelongsToStmt::parse as StmtParserFn);
25        m.insert("prefix", PrefixStmt::parse as StmtParserFn);
26        m.insert("organization", OrganizationStmt::parse as StmtParserFn);
27        m.insert("contact", ContactStmt::parse as StmtParserFn);
28        m.insert("description", DescriptionStmt::parse as StmtParserFn);
29        m.insert("reference", ReferenceStmt::parse as StmtParserFn);
30        m.insert("units", UnitsStmt::parse as StmtParserFn);
31        m.insert("revision", RevisionStmt::parse as StmtParserFn);
32        m.insert("revision-date", RevisionDateStmt::parse as StmtParserFn);
33        m.insert("extension", ExtensionStmt::parse as StmtParserFn);
34        m.insert("argument", ArgumentStmt::parse as StmtParserFn);
35        m.insert("yin-element", YinElementStmt::parse as StmtParserFn);
36        m.insert("identity", IdentityStmt::parse as StmtParserFn);
37        m.insert("base", BaseStmt::parse as StmtParserFn);
38        m.insert("feature", FeatureStmt::parse as StmtParserFn);
39        m.insert("if-feature", IfFeatureStmt::parse as StmtParserFn);
40        m.insert("typedef", TypedefStmt::parse as StmtParserFn);
41        m.insert("type", TypeStmt::parse as StmtParserFn);
42        m.insert("range", RangeStmt::parse as StmtParserFn);
43        m.insert("fraction-digits", FractionDigitsStmt::parse as StmtParserFn);
44        m.insert("length", LengthStmt::parse as StmtParserFn);
45        m.insert("pattern", PatternStmt::parse as StmtParserFn);
46        m.insert("modifier", ModifierStmt::parse as StmtParserFn);
47        m.insert("default", DefaultStmt::parse as StmtParserFn);
48        m.insert("enum", EnumStmt::parse as StmtParserFn);
49        m.insert("path", PathStmt::parse as StmtParserFn);
50        m.insert(
51            "require-instance",
52            RequireInstanceStmt::parse as StmtParserFn,
53        );
54        m.insert("bit", BitStmt::parse as StmtParserFn);
55        m.insert("position", PositionStmt::parse as StmtParserFn);
56        m.insert("status", StatusStmt::parse as StmtParserFn);
57        m.insert("config", ConfigStmt::parse as StmtParserFn);
58        m.insert("mandatory", MandatoryStmt::parse as StmtParserFn);
59        m.insert("presence", PresenceStmt::parse as StmtParserFn);
60        m.insert("ordered-by", OrderedByStmt::parse as StmtParserFn);
61        m.insert("must", MustStmt::parse as StmtParserFn);
62        m.insert("error-message", ErrorMessageStmt::parse as StmtParserFn);
63        m.insert("error-app-tag", ErrorAppTagStmt::parse as StmtParserFn);
64        m.insert("min-elements", MinElementsStmt::parse as StmtParserFn);
65        m.insert("max-elements", MaxElementsStmt::parse as StmtParserFn);
66        m.insert("value", ValueStmt::parse as StmtParserFn);
67        m.insert("grouping", GroupingStmt::parse as StmtParserFn);
68        m.insert("container", ContainerStmt::parse as StmtParserFn);
69        m.insert("leaf", LeafStmt::parse as StmtParserFn);
70        m.insert("leaf-list", LeafListStmt::parse as StmtParserFn);
71        m.insert("list", ListStmt::parse as StmtParserFn);
72        m.insert("key", KeyStmt::parse as StmtParserFn);
73        m.insert("unique", UniqueStmt::parse as StmtParserFn);
74        m.insert("choice", ChoiceStmt::parse as StmtParserFn);
75        m.insert("case", CaseStmt::parse as StmtParserFn);
76        m.insert("anydata", AnydataStmt::parse as StmtParserFn);
77        m.insert("anyxml", AnyxmlStmt::parse as StmtParserFn);
78        m.insert("uses", UsesStmt::parse as StmtParserFn);
79        m.insert("refine", RefineStmt::parse as StmtParserFn);
80        m.insert("augment", AugmentStmt::parse as StmtParserFn);
81        m.insert("when", WhenStmt::parse as StmtParserFn);
82        m.insert("rpc", RpcStmt::parse as StmtParserFn);
83        m.insert("action", ActionStmt::parse as StmtParserFn);
84        m.insert("input", InputStmt::parse as StmtParserFn);
85        m.insert("output", OutputStmt::parse as StmtParserFn);
86        m.insert("notification", NotificationStmt::parse as StmtParserFn);
87        m.insert("deviation", DeviationStmt::parse as StmtParserFn);
88        m.insert("deviate", DeviateStmt::parse as StmtParserFn);
89        m
90    };
91}
92
93// Keyword.
94pub type Keyword = &'static str;
95
96// Statement collection.
97pub type StmtCollection = HashMap<String, Vec<YangStmt>>;
98
99// Statement Parser callback type.
100type StmtParserFn = fn(&mut Parser) -> Result<YangStmt, YangError>;
101
102// Yang Statement
103#[derive(Clone, PartialEq)]
104pub enum YangStmt {
105    ModuleStmt(ModuleStmt),
106    SubmoduleStmt(SubmoduleStmt),
107    YangVersionStmt(YangVersionStmt),
108    ImportStmt(ImportStmt),
109    IncludeStmt(IncludeStmt),
110    NamespaceStmt(NamespaceStmt),
111    PrefixStmt(PrefixStmt),
112    BelongsToStmt(BelongsToStmt),
113    OrganizationStmt(OrganizationStmt),
114    ContactStmt(ContactStmt),
115    DescriptionStmt(DescriptionStmt),
116    ReferenceStmt(ReferenceStmt),
117    UnitsStmt(UnitsStmt),
118    RevisionStmt(RevisionStmt),
119    RevisionDateStmt(RevisionDateStmt),
120    ExtensionStmt(ExtensionStmt),
121    ArgumentStmt(ArgumentStmt),
122    YinElementStmt(YinElementStmt),
123    IdentityStmt(IdentityStmt),
124    BaseStmt(BaseStmt),
125    FeatureStmt(FeatureStmt),
126    IfFeatureStmt(IfFeatureStmt),
127    TypedefStmt(TypedefStmt),
128    TypeStmt(TypeStmt),
129    RangeStmt(RangeStmt),
130    FractionDigitsStmt(FractionDigitsStmt),
131    LengthStmt(LengthStmt),
132    PatternStmt(PatternStmt),
133    ModifierStmt(ModifierStmt),
134    DefaultStmt(DefaultStmt),
135    EnumStmt(EnumStmt),
136    PathStmt(PathStmt),
137    RequireInstanceStmt(RequireInstanceStmt),
138    BitStmt(BitStmt),
139    PositionStmt(PositionStmt),
140    StatusStmt(StatusStmt),
141    ConfigStmt(ConfigStmt),
142    MandatoryStmt(MandatoryStmt),
143    PresenceStmt(PresenceStmt),
144    OrderedByStmt(OrderedByStmt),
145    MustStmt(MustStmt),
146    ErrorMessageStmt(ErrorMessageStmt),
147    ErrorAppTagStmt(ErrorAppTagStmt),
148    MinElementsStmt(MinElementsStmt),
149    MaxElementsStmt(MaxElementsStmt),
150    ValueStmt(ValueStmt),
151    GroupingStmt(GroupingStmt),
152    ContainerStmt(ContainerStmt),
153    LeafStmt(LeafStmt),
154    LeafListStmt(LeafListStmt),
155    ListStmt(ListStmt),
156    KeyStmt(KeyStmt),
157    UniqueStmt(UniqueStmt),
158    ChoiceStmt(ChoiceStmt),
159    CaseStmt(CaseStmt),
160    AnydataStmt(AnydataStmt),
161    AnyxmlStmt(AnyxmlStmt),
162    UsesStmt(UsesStmt),
163    RefineStmt(RefineStmt),
164    AugmentStmt(AugmentStmt),
165    WhenStmt(WhenStmt),
166    RpcStmt(RpcStmt),
167    ActionStmt(ActionStmt),
168    InputStmt(InputStmt),
169    OutputStmt(OutputStmt),
170    NotificationStmt(NotificationStmt),
171    DeviationStmt(DeviationStmt),
172    DeviateStmt(DeviateStmt),
173    UnknownStmt(UnknownStmt),
174}
175
176impl fmt::Debug for YangStmt {
177    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178        match &*self {
179            YangStmt::ModuleStmt(stmt) => write!(f, "{:?}", stmt),
180            YangStmt::SubmoduleStmt(stmt) => write!(f, "{:?}", stmt),
181            YangStmt::YangVersionStmt(stmt) => write!(f, "{:?}", stmt),
182            YangStmt::ImportStmt(stmt) => write!(f, "{:?}", stmt),
183            YangStmt::IncludeStmt(stmt) => write!(f, "{:?}", stmt),
184            YangStmt::NamespaceStmt(stmt) => write!(f, "{:?}", stmt),
185            YangStmt::PrefixStmt(stmt) => write!(f, "{:?}", stmt),
186            YangStmt::BelongsToStmt(stmt) => write!(f, "{:?}", stmt),
187            YangStmt::OrganizationStmt(stmt) => write!(f, "{:?}", stmt),
188            YangStmt::ContactStmt(stmt) => write!(f, "{:?}", stmt),
189            YangStmt::DescriptionStmt(stmt) => write!(f, "{:?}", stmt),
190            YangStmt::ReferenceStmt(stmt) => write!(f, "{:?}", stmt),
191            YangStmt::UnitsStmt(stmt) => write!(f, "{:?}", stmt),
192            YangStmt::RevisionStmt(stmt) => write!(f, "{:?}", stmt),
193            YangStmt::RevisionDateStmt(stmt) => write!(f, "{:?}", stmt),
194            YangStmt::ExtensionStmt(stmt) => write!(f, "{:?}", stmt),
195            YangStmt::ArgumentStmt(stmt) => write!(f, "{:?}", stmt),
196            YangStmt::YinElementStmt(stmt) => write!(f, "{:?}", stmt),
197            YangStmt::IdentityStmt(stmt) => write!(f, "{:?}", stmt),
198            YangStmt::BaseStmt(stmt) => write!(f, "{:?}", stmt),
199            YangStmt::FeatureStmt(stmt) => write!(f, "{:?}", stmt),
200            YangStmt::IfFeatureStmt(stmt) => write!(f, "{:?}", stmt),
201            YangStmt::TypedefStmt(stmt) => write!(f, "{:?}", stmt),
202            YangStmt::TypeStmt(stmt) => write!(f, "{:?}", stmt),
203            YangStmt::RangeStmt(stmt) => write!(f, "{:?}", stmt),
204            YangStmt::FractionDigitsStmt(stmt) => write!(f, "{:?}", stmt),
205            YangStmt::LengthStmt(stmt) => write!(f, "{:?}", stmt),
206            YangStmt::PatternStmt(stmt) => write!(f, "{:?}", stmt),
207            YangStmt::ModifierStmt(stmt) => write!(f, "{:?}", stmt),
208            YangStmt::DefaultStmt(stmt) => write!(f, "{:?}", stmt),
209            YangStmt::EnumStmt(stmt) => write!(f, "{:?}", stmt),
210            YangStmt::PathStmt(stmt) => write!(f, "{:?}", stmt),
211            YangStmt::RequireInstanceStmt(stmt) => write!(f, "{:?}", stmt),
212            YangStmt::BitStmt(stmt) => write!(f, "{:?}", stmt),
213            YangStmt::PositionStmt(stmt) => write!(f, "{:?}", stmt),
214            YangStmt::StatusStmt(stmt) => write!(f, "{:?}", stmt),
215            YangStmt::ConfigStmt(stmt) => write!(f, "{:?}", stmt),
216            YangStmt::MandatoryStmt(stmt) => write!(f, "{:?}", stmt),
217            YangStmt::PresenceStmt(stmt) => write!(f, "{:?}", stmt),
218            YangStmt::OrderedByStmt(stmt) => write!(f, "{:?}", stmt),
219            YangStmt::MustStmt(stmt) => write!(f, "{:?}", stmt),
220            YangStmt::ErrorMessageStmt(stmt) => write!(f, "{:?}", stmt),
221            YangStmt::ErrorAppTagStmt(stmt) => write!(f, "{:?}", stmt),
222            YangStmt::MinElementsStmt(stmt) => write!(f, "{:?}", stmt),
223            YangStmt::MaxElementsStmt(stmt) => write!(f, "{:?}", stmt),
224            YangStmt::ValueStmt(stmt) => write!(f, "{:?}", stmt),
225            YangStmt::GroupingStmt(stmt) => write!(f, "{:?}", stmt),
226            YangStmt::ContainerStmt(stmt) => write!(f, "{:?}", stmt),
227            YangStmt::LeafStmt(stmt) => write!(f, "{:?}", stmt),
228            YangStmt::LeafListStmt(stmt) => write!(f, "{:?}", stmt),
229            YangStmt::ListStmt(stmt) => write!(f, "{:?}", stmt),
230            YangStmt::KeyStmt(stmt) => write!(f, "{:?}", stmt),
231            YangStmt::UniqueStmt(stmt) => write!(f, "{:?}", stmt),
232            YangStmt::ChoiceStmt(stmt) => write!(f, "{:?}", stmt),
233            YangStmt::CaseStmt(stmt) => write!(f, "{:?}", stmt),
234            YangStmt::AnydataStmt(stmt) => write!(f, "{:?}", stmt),
235            YangStmt::AnyxmlStmt(stmt) => write!(f, "{:?}", stmt),
236            YangStmt::UsesStmt(stmt) => write!(f, "{:?}", stmt),
237            YangStmt::RefineStmt(stmt) => write!(f, "{:?}", stmt),
238            YangStmt::AugmentStmt(stmt) => write!(f, "{:?}", stmt),
239            YangStmt::WhenStmt(stmt) => write!(f, "{:?}", stmt),
240            YangStmt::RpcStmt(stmt) => write!(f, "{:?}", stmt),
241            YangStmt::ActionStmt(stmt) => write!(f, "{:?}", stmt),
242            YangStmt::InputStmt(stmt) => write!(f, "{:?}", stmt),
243            YangStmt::OutputStmt(stmt) => write!(f, "{:?}", stmt),
244            YangStmt::NotificationStmt(stmt) => write!(f, "{:?}", stmt),
245            YangStmt::DeviationStmt(stmt) => write!(f, "{:?}", stmt),
246            YangStmt::DeviateStmt(stmt) => write!(f, "{:?}", stmt),
247            YangStmt::UnknownStmt(stmt) => write!(f, "{:?}", stmt),
248        }
249    }
250}
251
252// String helper functions for Basic rules.
253pub fn is_node_identifier(s: &str) -> bool {
254    let parts: Vec<_> = s.split(":").collect();
255
256    if parts.len() == 1 {
257        is_identifier(parts[0])
258    } else if parts.len() == 2 {
259        is_identifier(parts[0]) && is_identifier(parts[1])
260    } else {
261        false
262    }
263}
264
265pub fn is_current_function_invocation(s: &str) -> bool {
266    let s = s.trim();
267
268    if !s.starts_with("current") {
269        false
270    } else {
271        let s = &s[7..].trim_start();
272
273        if !s.starts_with("(") {
274            false
275        } else {
276            let s = &s[1..].trim();
277
278            if s != &")" {
279                false
280            } else {
281                true
282            }
283        }
284    }
285}
286
287pub fn is_identifier(s: &str) -> bool {
288    if !s.starts_with(|c: char| c.is_alphabetic() || c == '_') {
289        false
290    } else if s.len() > 1 {
291        if let Some(_) = &s[1..].find(|c: char| {
292            !c.is_alphabetic() && !c.is_ascii_digit() && c != '_' && c != '-' && c != '.'
293        }) {
294            false
295        } else {
296            true
297        }
298    } else {
299        true
300    }
301}
302
303pub fn is_integer_value(s: &str) -> bool {
304    if s.starts_with("-") {
305        is_non_negative_integer_value(&s[1..])
306    } else {
307        is_non_negative_integer_value(s)
308    }
309}
310
311pub fn is_non_negative_integer_value(s: &str) -> bool {
312    s == "0" || is_positive_integer_value(s)
313}
314
315pub fn is_positive_integer_value(s: &str) -> bool {
316    let mut chars = s.chars();
317    let c = chars.next().unwrap();
318
319    if c != '0' && c.is_ascii_digit() {
320        chars.all(|c: char| c.is_ascii_digit())
321    } else {
322        false
323    }
324}
325
326fn is_zero_integer_value(s: &str) -> bool {
327    s.chars().all(|c: char| c.is_ascii_digit())
328}
329
330pub fn is_decimal_value(s: &str) -> bool {
331    if let Some(p) = s.find('.') {
332        let is = &s[..p];
333        let fs = &s[p + 1..];
334
335        if is_integer_value(is) && fs.len() > 0 {
336            is_zero_integer_value(fs)
337        } else {
338            false
339        }
340    } else {
341        false
342    }
343}
344
345#[cfg(test)]
346mod tests {
347    use super::*;
348
349    #[test]
350    pub fn test_current_function_invocation() {
351        let s = "current()";
352        assert_eq!(is_current_function_invocation(&s), true);
353
354        let s = "  current () ";
355        assert_eq!(is_current_function_invocation(&s), true);
356
357        let s = "current ( )";
358        assert_eq!(is_current_function_invocation(&s), true);
359
360        let s = "current (   ) ";
361        assert_eq!(is_current_function_invocation(&s), true);
362
363        let s = "current (   ) ";
364        assert_eq!(is_current_function_invocation(&s), true);
365
366        let s = "current ( 0 ) ";
367        assert_eq!(is_current_function_invocation(&s), false);
368    }
369
370    #[test]
371    pub fn test_identifier() {
372        let s = "identifier";
373        assert_eq!(is_identifier(&s), true);
374
375        let s = "_0123456789-abcdefghijklmnokprstuvwxyz_";
376        assert_eq!(is_identifier(&s), true);
377
378        let s = "_ABCDEFGHIJKLMNOKPRSTUVWXYZ-0123456789_";
379        assert_eq!(is_identifier(&s), true);
380
381        let s = "1a";
382        assert_eq!(is_identifier(&s), false);
383
384        let s = "_";
385        assert_eq!(is_identifier(&s), true);
386
387        let s = "_3.14159265";
388        assert_eq!(is_identifier(&s), true);
389
390        let s = "_127.0.0.1";
391        assert_eq!(is_identifier(&s), true);
392
393        let s = "_ff02::1";
394        assert_eq!(is_identifier(&s), false);
395    }
396
397    #[test]
398    pub fn test_integer_value() {
399        let s = "0123456789";
400        assert_eq!(is_integer_value(&s), false);
401
402        let s = "0";
403        assert_eq!(is_integer_value(&s), true);
404
405        let s = "1234567890";
406        assert_eq!(is_integer_value(&s), true);
407
408        let s = "abc";
409        assert_eq!(is_integer_value(&s), false);
410
411        let s = "-1";
412        assert_eq!(is_integer_value(&s), true);
413
414        let s = "3.14159265";
415        assert_eq!(is_integer_value(&s), false);
416    }
417
418    #[test]
419    pub fn test_non_negative_integer_value() {
420        let s = "0123456789";
421        assert_eq!(is_non_negative_integer_value(&s), false);
422
423        let s = "0";
424        assert_eq!(is_non_negative_integer_value(&s), true);
425
426        let s = "1234567890";
427        assert_eq!(is_non_negative_integer_value(&s), true);
428
429        let s = "abc";
430        assert_eq!(is_non_negative_integer_value(&s), false);
431
432        let s = "-1";
433        assert_eq!(is_non_negative_integer_value(&s), false);
434
435        let s = "3.14159265";
436        assert_eq!(is_non_negative_integer_value(&s), false);
437    }
438
439    #[test]
440    pub fn test_positive_integer_value() {
441        let s = "0123456789";
442        assert_eq!(is_positive_integer_value(&s), false);
443
444        let s = "0";
445        assert_eq!(is_positive_integer_value(&s), false);
446
447        let s = "1234567890";
448        assert_eq!(is_positive_integer_value(&s), true);
449
450        let s = "abc";
451        assert_eq!(is_positive_integer_value(&s), false);
452
453        let s = "-1";
454        assert_eq!(is_positive_integer_value(&s), false);
455
456        let s = "3.14159265";
457        assert_eq!(is_positive_integer_value(&s), false);
458    }
459
460    #[test]
461    pub fn test_zero_integer_value() {
462        let s = "0123456789";
463        assert_eq!(is_zero_integer_value(&s), true);
464
465        let s = "0";
466        assert_eq!(is_zero_integer_value(&s), true);
467
468        let s = "1234567890";
469        assert_eq!(is_zero_integer_value(&s), true);
470
471        let s = "abc";
472        assert_eq!(is_zero_integer_value(&s), false);
473
474        let s = "-1";
475        assert_eq!(is_zero_integer_value(&s), false);
476
477        let s = "3.14159265";
478        assert_eq!(is_zero_integer_value(&s), false);
479    }
480
481    #[test]
482    pub fn test_decimal_value() {
483        let s = "0123456789";
484        assert_eq!(is_decimal_value(&s), false);
485
486        let s = "0";
487        assert_eq!(is_decimal_value(&s), false);
488
489        let s = "1234567890";
490        assert_eq!(is_decimal_value(&s), false);
491
492        let s = "abc";
493        assert_eq!(is_decimal_value(&s), false);
494
495        let s = "-1.0";
496        assert_eq!(is_decimal_value(&s), true);
497
498        let s = "3.14159265";
499        assert_eq!(is_decimal_value(&s), true);
500    }
501}