cfg_lib/
config.rs

1//
2//  Copyright (C) 2018-2021 Red Dove Consultants Limited
3//
4/*!
5  This module implements code to tokenize and parse CFG source text, and query configurations.
6*/
7use std::cell::RefCell;
8use std::cmp::{Ord, Ordering};
9use std::collections::{HashMap, HashSet};
10use std::convert::{From, TryInto};
11use std::env;
12use std::fmt::{self, Write};
13use std::fs::{canonicalize, File};
14use std::io::{self, BufRead, BufReader, Cursor, Error, ErrorKind, Read, Result};
15use std::path::{Path, PathBuf};
16use std::rc::Rc;
17use std::result::Result as StdResult;
18
19use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime};
20use lazy_static::lazy_static;
21use num_complex::Complex64;
22use regex::{Captures, Regex};
23
24//
25// Low level I/O stuff
26//
27
28const UTF8_ACCEPT: u32 = 0;
29const UTF8_REJECT: u32 = 12;
30
31lazy_static! {
32    // see http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
33    /*
34      // The first part of the table maps bytes to character classes that
35      // to reduce the size of the transition table and create bit-masks.
36       0   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
37      32   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
38      64   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
39      96   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
40     128   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
41     160   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
42     192   8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
43     224  10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
44
45          // The second part is a transition table that maps a combination
46          // of a state of the automaton and a character class to a state.
47     256   0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
48     280  12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
49     304  12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
50     328  12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
51     352  12,36,12,12,12,12,12,12,12,12,12,12,
52
53    uint32_t inline
54    decode(uint32_t* state, uint32_t* code_point, uint32_t byte) {
55      uint32_t type = utf8d[byte];
56
57      *code_point = (*state != UTF8_ACCEPT) ?
58        (byte & 0x3fu) | (*code_point << 6) :
59        (0xff >> type) & (byte);
60
61      *state = utf8d[256 + *state + type];
62      return *state;
63    }
64
65     */
66
67    static ref UTF8_LOOKUP: [u8; 364] = {
68        let mut map = [0u8; 364];
69        for i in 128..144 {
70            map[i] = 1;
71        }
72        for i in 144..160 {
73            map[i] = 9;
74        }
75        for i in 160..192 {
76            map[i] = 7;
77        }
78        map[192] = 8;
79        map[193] = 8;
80        for i in 194..224 {
81            map[i] = 2;
82        }
83        map[224] = 10;
84        for i in 225..240 {
85            map[i] = 3;
86        }
87        map[237] = 4;
88        map[240] = 11;
89        for i in 241..244 {
90            map[i] = 6;
91        }
92        map[244] = 5;
93        for i in 245..256 {
94            map[i] = 8;
95        }
96        for i in 256..260 {
97            map[i] = ((i - 256) * 12) as u8;
98        }
99        map[260] = 60;
100        map[261] = 96;
101        map[262] = 84;
102        for i in 263..364 {
103            map[i] = 12;
104        }
105        map[266] = 48;
106        map[267] = 72;
107        map[281] = 0;
108        map[287] = 0;
109        map[289] = 0;
110        map[293] = 24;
111        map[299] = 24;
112        map[301] = 24;
113        map[311] = 24;
114        map[317] = 24;
115        map[325] = 24;
116        map[335] = 36;
117        map[337] = 36;
118        map[341] = 36;
119        map[347] = 36;
120        map[349] = 36;
121        map[353] = 36;
122        map
123    };
124
125    static ref PUNCTUATION: HashMap<char, TokenKind> = {
126        let mut map = HashMap::new();
127
128        map.insert(':', TokenKind::Colon);
129        map.insert('-', TokenKind::Minus);
130        map.insert('+', TokenKind::Plus);
131        map.insert('*', TokenKind::Star);
132        map.insert('/', TokenKind::Slash);
133        map.insert('%', TokenKind::Modulo);
134        map.insert(',', TokenKind::Comma);
135        map.insert('{', TokenKind::LeftCurly);
136        map.insert('}', TokenKind::RightCurly);
137        map.insert('[', TokenKind::LeftBracket);
138        map.insert(']', TokenKind::RightBracket);
139        map.insert('(', TokenKind::LeftParenthesis);
140        map.insert(')', TokenKind::RightParenthesis);
141        map.insert('@', TokenKind::At);
142        map.insert('$', TokenKind::Dollar);
143        map.insert('<', TokenKind::LessThan);
144        map.insert('>', TokenKind::GreaterThan);
145        map.insert('!', TokenKind::Not);
146        map.insert('~', TokenKind::BitwiseComplement);
147        map.insert('&', TokenKind::BitwiseAnd);
148        map.insert('|', TokenKind::BitwiseOr);
149        map.insert('^', TokenKind::BitwiseXor);
150        map.insert('.', TokenKind::Dot);
151        map
152    };
153
154    static ref KEYWORDS: HashMap<String, TokenKind> = {
155        let mut map = HashMap::new();
156
157        map.insert("true".to_string(), TokenKind::True);
158        map.insert("false".to_string(), TokenKind::False);
159        map.insert("null".to_string(), TokenKind::None);
160        map.insert("is".to_string(), TokenKind::Is);
161        map.insert("in".to_string(), TokenKind::In);
162        map.insert("not".to_string(), TokenKind::Not);
163        map.insert("and".to_string(), TokenKind::And);
164        map.insert("or".to_string(), TokenKind::Or);
165        map
166    };
167
168    static ref KEYWORD_VALUES: HashMap<String, ScalarValue> = {
169        let mut map = HashMap::new();
170
171        map.insert("true".to_string(), ScalarValue::Bool(true));
172        map.insert("false".to_string(), ScalarValue::Bool(false));
173        map.insert("null".to_string(), ScalarValue::Null);
174        map
175    };
176
177    static ref EXPRESSION_STARTERS: HashSet<TokenKind> = {
178        let mut set = HashSet::new();
179
180        set.insert(TokenKind::LeftCurly);
181        set.insert(TokenKind::LeftCurly);
182        set.insert(TokenKind::LeftBracket);
183        set.insert(TokenKind::LeftParenthesis);
184        set.insert(TokenKind::At);
185        set.insert(TokenKind::Dollar);
186        set.insert(TokenKind::BackTick);
187        set.insert(TokenKind::Plus);
188        set.insert(TokenKind::Minus);
189        set.insert(TokenKind::BitwiseComplement);
190        set.insert(TokenKind::Number);
191        set.insert(TokenKind::Complex);
192        set.insert(TokenKind::True);
193        set.insert(TokenKind::False);
194        set.insert(TokenKind::None);
195        set.insert(TokenKind::Not);
196        set.insert(TokenKind::String);
197        set.insert(TokenKind::Word);
198        set
199    };
200
201    static ref VALUE_STARTERS: HashSet<TokenKind> = {
202        let mut set = HashSet::new();
203
204        set.insert(TokenKind::Word);
205        set.insert(TokenKind::Number);
206        set.insert(TokenKind::Complex);
207        set.insert(TokenKind::String);
208        set.insert(TokenKind::BackTick);
209        set.insert(TokenKind::None);
210        set.insert(TokenKind::True);
211        set.insert(TokenKind::False);
212        set
213    };
214
215    static ref COMPARISON_OPERATORS: HashSet<TokenKind> = {
216        let mut set = HashSet::new();
217
218        set.insert(TokenKind::LessThan);
219        set.insert(TokenKind::LessThanOrEqual);
220        set.insert(TokenKind::GreaterThan);
221        set.insert(TokenKind::GreaterThanOrEqual);
222        set.insert(TokenKind::Equal);
223        set.insert(TokenKind::Unequal);
224        set.insert(TokenKind::AltUnequal);
225        set.insert(TokenKind::Is);
226        set.insert(TokenKind::In);
227        set.insert(TokenKind::Not);
228        set
229    };
230
231    static ref ESCAPES: HashMap<char, char> = {
232        let mut map = HashMap::new();
233
234        map.insert('a', '\u{0007}');
235        map.insert('b', '\u{0008}');
236        map.insert('f', '\u{000C}');
237        map.insert('n', '\n');
238        map.insert('r', '\r');
239        map.insert('t', '\t');
240        map.insert('v', '\u{000B}');
241        map.insert('\\', '\\');
242        map.insert('\'', '\'');
243        map.insert('"', '"');
244        map
245    };
246
247    static ref TOKEN_TEXT: HashMap<TokenKind, String> = {
248        let mut map = HashMap::new();
249
250        map.insert(TokenKind::EOF, "EOF".to_string());
251        map.insert(TokenKind::Word, "<an identifier>".to_string());
252        map.insert(TokenKind::Number, "<a number>".to_string());
253        map.insert(TokenKind::String, "<a literal string>".to_string());
254        map.insert(TokenKind::Newline, "<a newline>".to_string());
255        map.insert(TokenKind::LeftCurly, "'{'".to_string());
256        map.insert(TokenKind::RightCurly, "'}'".to_string());
257        map.insert(TokenKind::LeftBracket, "'['".to_string());
258        map.insert(TokenKind::RightBracket, "']'".to_string());
259        map.insert(TokenKind::LeftParenthesis, "'('".to_string());
260        map.insert(TokenKind::RightParenthesis, "')'".to_string());
261        map.insert(TokenKind::LessThan, "'<'".to_string());
262        map.insert(TokenKind::GreaterThan, "'>'".to_string());
263        map.insert(TokenKind::LessThanOrEqual, "'<='".to_string());
264        map.insert(TokenKind::GreaterThanOrEqual, "'>='".to_string());
265        map.insert(TokenKind::Assign, "'='".to_string());
266        map.insert(TokenKind::Equal, "'=='".to_string());
267        map.insert(TokenKind::Unequal, "'!='".to_string());
268        map.insert(TokenKind::AltUnequal, "'<>'".to_string());
269        map.insert(TokenKind::LeftShift, "'<<'".to_string());
270        map.insert(TokenKind::RightShift, "'>>'".to_string());
271        map.insert(TokenKind::Dot, "'.'".to_string());
272        map.insert(TokenKind::Comma, "','".to_string());
273        map.insert(TokenKind::Colon, "':'".to_string());
274        map.insert(TokenKind::At, "'@'".to_string());
275        map.insert(TokenKind::Plus, "'+'".to_string());
276        map.insert(TokenKind::Minus, "'-'".to_string());
277        map.insert(TokenKind::Star, "'*'".to_string());
278        map.insert(TokenKind::Power, "'**'".to_string());
279        map.insert(TokenKind::Slash, "'/'".to_string());
280        map.insert(TokenKind::SlashSlash, "'//'".to_string());
281        map.insert(TokenKind::Modulo, "'%'".to_string());
282        map.insert(TokenKind::BackTick, "'`'".to_string());
283        map.insert(TokenKind::Dollar, "'$'".to_string());
284        map.insert(TokenKind::True, "<true>".to_string());
285        map.insert(TokenKind::False, "<false>".to_string());
286        map.insert(TokenKind::None, "<none>".to_string());
287        map.insert(TokenKind::Is, "'is'".to_string());
288        map.insert(TokenKind::In, "'in'".to_string());
289        map.insert(TokenKind::Not, "'not'".to_string());
290        map.insert(TokenKind::And, "'and'".to_string());
291        map.insert(TokenKind::Or, "'or'".to_string());
292        map.insert(TokenKind::BitwiseAnd, "'&'".to_string());
293        map.insert(TokenKind::BitwiseOr, "'|'".to_string());
294        map.insert(TokenKind::BitwiseXor, "'^'".to_string());
295        map.insert(TokenKind::BitwiseComplement, "'~'".to_string());
296        map.insert(TokenKind::Complex, "<complex>".to_string());
297        map.insert(TokenKind::IsNot, "'is not'".to_string());
298        map.insert(TokenKind::NotIn, "'not in'".to_string());
299        map
300    };
301
302    static ref IDENTIFIER_PATTERN: Regex = Regex::new(r"^[\pL_](\w*)$").expect("couldn't compile regex");
303    static ref ISO_DATETIME_PATTERN: Regex = Regex::new(r"^(\d{4})-(\d{2})-(\d{2})(([ T])(((\d{2}):(\d{2}):(\d{2}))(\.\d{1,6})?(([+-])(\d{2}):(\d{2})(:(\d{2})(\.\d{1,6})?)?)?))?$").expect("couldn't compile regex");
304    static ref ENV_VALUE_PATTERN: Regex = Regex::new(r"^\$(\w+)(\|(.*))?$").expect("couldn't compile regex");
305    static ref INTERPOLATION_PATTERN: Regex = Regex::new(r"\$\{([^}]+)\}").expect("couldn't compile regex");
306
307    static ref NOT_STRING: &'static str = "configuration value is not a string";
308    static ref NOT_INTEGER: &'static str = "configuration value is not an integer";
309    static ref NOT_FLOAT: &'static str = "configuration value is not a floating-point value";
310    static ref NOT_COMPLEX: &'static str = "configuration value is not a complex number value";
311    static ref NOT_DATE: &'static str = "configuration value is not a date value";
312    static ref NOT_DATETIME: &'static str = "configuration value is not a date/time value";
313}
314
315#[derive(Debug)]
316pub(crate) enum DecoderError {
317    InvalidBytes(Vec<u8>),
318    Io(io::Error),
319}
320
321impl fmt::Display for DecoderError {
322    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
323        match self {
324            DecoderError::InvalidBytes(b) => write!(f, "invalid bytes: {:?}", b),
325            DecoderError::Io(e) => write!(f, "I/O error: {:?}", e),
326        }
327    }
328}
329
330// no actual implementations needed, as defaults are in the trait itself
331impl std::error::Error for DecoderError {}
332
333#[derive(Debug)]
334pub(crate) enum DecodeResult {
335    EOF,
336    Error(DecoderError),
337    Char(char, Vec<u8>),
338}
339
340pub(crate) struct Decoder<'a> {
341    reader: Box<dyn BufRead + 'a>,
342    pub(crate) bytes_read: usize,
343    log: bool,
344}
345
346impl<'a> Decoder<'a> {
347    pub(crate) fn new<R: Read + 'a>(r: R) -> Self {
348        let boxed = Box::new(r);
349        let br = BufReader::new(boxed);
350
351        Self {
352            reader: Box::new(br),
353            bytes_read: 0,
354            log: false,
355        }
356    }
357
358    pub(crate) fn decode(&mut self) -> DecodeResult {
359        let mut pos: usize;
360        let mut code_point: u32 = 0;
361        let mut state = UTF8_ACCEPT;
362        let mut the_bytes = vec![];
363
364        loop {
365            let reader = &mut self.reader;
366            // we create a block just to get some bytes using fill_buf() and process some byes from
367            // the buffer it gives us. Once we exit the block, we've given back the borrow and can
368            // call consume().
369            {
370                let r = reader.fill_buf();
371                let length: usize;
372                let buf: &[u8];
373
374                match r {
375                    Ok(buffer) => {
376                        buf = buffer;
377                        length = buffer.len();
378                        if self.log {
379                            println!("Buffer is {} long", length);
380                        }
381                        if length == 0 {
382                            return if state == UTF8_ACCEPT {
383                                DecodeResult::EOF
384                            } else {
385                                DecodeResult::Error(DecoderError::InvalidBytes(the_bytes))
386                            };
387                        }
388                        pos = 0;
389                    }
390                    Err(e) => {
391                        return DecodeResult::Error(DecoderError::Io(e));
392                    }
393                }
394                while pos < length {
395                    let byte = buf[pos];
396                    let kind: u32 = UTF8_LOOKUP[byte as usize] as u32;
397
398                    the_bytes.push(byte);
399                    code_point = if state != UTF8_ACCEPT {
400                        (byte & 0x3F) as u32 | (code_point << 6)
401                    } else {
402                        (0xFF >> kind) & (byte as u32)
403                    };
404                    state = UTF8_LOOKUP[(256 + state + kind) as usize] as u32;
405                    if self.log {
406                        println!("byte = {}, kind = {}, state = {}", byte, kind, state);
407                    }
408                    if state == UTF8_REJECT {
409                        break;
410                    } else {
411                        pos += 1;
412                        if state == UTF8_ACCEPT {
413                            break;
414                        }
415                    }
416                }
417            } // block which processes bytes in the buffer
418            reader.consume(pos);
419            self.bytes_read += pos;
420
421            if state == UTF8_REJECT || state == UTF8_ACCEPT {
422                break;
423            }
424        } // loop which processes until char or error
425        if self.log {
426            println!("exited loop, state = {}", state);
427        }
428        assert!(state == UTF8_REJECT || state == UTF8_ACCEPT);
429        if state == UTF8_REJECT {
430            DecodeResult::Error(DecoderError::InvalidBytes(the_bytes))
431        } else {
432            match std::char::from_u32(code_point) {
433                Some(c) => DecodeResult::Char(c, the_bytes),
434                None => DecodeResult::Error(DecoderError::InvalidBytes(the_bytes)),
435            }
436        }
437    }
438}
439
440//
441// Token and Tokenizer stuff
442//
443/// This represents a line and column location in CFG source.
444#[derive(Debug, Copy, Clone, PartialEq, Hash, Eq, PartialOrd)]
445pub struct Location {
446    /// The line number of the location.
447    pub line: u16,
448    /// The column number of the location.
449    pub column: u16,
450}
451
452impl Location {
453    pub(crate) fn next_line(&mut self) {
454        self.line += 1;
455        self.column = 1;
456    }
457
458    pub(crate) fn update(&mut self, other: &Self) {
459        *self = *other;
460    }
461}
462
463impl fmt::Display for Location {
464    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465        write!(f, "({}, {})", self.line, self.column)
466    }
467}
468
469impl Ord for Location {
470    fn cmp(&self, other: &Self) -> Ordering {
471        let result = self.line.cmp(&other.column);
472
473        if result != Ordering::Equal {
474            return result;
475        }
476        self.column.cmp(&other.column)
477    }
478}
479
480/// This represents the low-level errors which can occur when parsing CFG source. They all include
481/// the source location where the error was detected.
482#[derive(Debug, PartialEq)]
483pub enum RecognizerError {
484    /// This represents an I/O error (e.g. a network or disk read error).
485    Io(Location),
486    /// This represents an unexpected character at the start of a token.
487    UnexpectedCharacter(char, Location),
488    /// This represents a character which is invalid in the middle of a token.
489    InvalidCharacter(char, Location),
490    /// This represents an invalid number.
491    InvalidNumber(Location),
492    /// This represents an unterminated string. The start of the string is returned.
493    UnterminatedString(Location),
494    /// This represents where an invalid string was detected. An example would be a back-tick
495    /// string containing a newline character.
496    InvalidString(Location),
497    /// This represents where a particular token was expected but not found. The text of the
498    /// expected token, the text of the actual token and the location are returned.
499    UnexpectedToken(String, String, Location),
500    /// This represents where a value was expected but not found.
501    ValueExpected(String, Location),
502    /// This represents where an "atom" (identifier, number, string etc.) was expected but not found.
503    AtomExpected(String, Location),
504    /// This represents where a key (identifier or literal string) was expected but not found.
505    KeyExpected(String, Location),
506    /// This represents where a key/value separator was expected but not found.
507    KeyValueSeparatorExpected(String, Location),
508    /// This represents that a valid container (mapping or list) was expected, but not found.
509    ContainerExpected(String, Location),
510    /// This representsd an invalid escape sequence.
511    InvalidEscapeSequence(usize, Location),
512    /// This represents an unexpected list size. Currently, only one-dimensional lists are allowed.
513    UnexpectedListSize(Location),
514    /// This represents trailing text, e.g. at the end of an expression.
515    TrailingText(Location),
516}
517
518/// This represents the kind of token. A deliberate choice was made to separate this from the
519/// ScalarValue enumeration to keep the token kind as just a simple enumeration, as in other
520/// language implementations.
521#[derive(Debug, Copy, Clone, PartialEq, Hash, Eq)]
522pub enum TokenKind {
523    /// This represents the token at the end of the input stream.
524    EOF = 0,
525    /// This represents a word (identifier).
526    Word,
527    /// This represents a literal number.
528    Number,
529    /// This represents a literal string.
530    String,
531    /// This represents the "\n" punctuation character.
532    Newline,
533    /// This represents the "{" punctuation character.
534    LeftCurly,
535    /// This represents the "}" punctuation character.
536    RightCurly,
537    /// This represents the "[" punctuation character.
538    LeftBracket,
539    /// This represents the "]" punctuation character.
540    RightBracket,
541    /// This represents the "(>)" punctuation character.
542    LeftParenthesis,
543    /// This represents the ")" punctuation character.
544    RightParenthesis,
545    /// This represents the "<>>" punctuation character.
546    LessThan,
547    /// This represents the ">" punctuation character.
548    GreaterThan,
549    /// This represents the "<=>" punctuation sequence.
550    LessThanOrEqual,
551    /// This represents the ">=" punctuation sequence.
552    GreaterThanOrEqual,
553    /// This represents the "=" punctuation character.
554    Assign,
555    /// This represents the "==" punctuation sequence.
556    Equal,
557    /// This represents the "!=" punctuation sequence.
558    Unequal,
559    /// This represents the "<>>>" punctuation sequence.
560    AltUnequal,
561    /// This represents the "<<>>>>" punctuation sequence.
562    LeftShift,
563    /// This represents the ">>" punctuation sequence.
564    RightShift,
565    /// This represents the "." punctuation character.
566    Dot,
567    /// This represents the "," punctuation character.
568    Comma,
569    /// This represents the ":" punctuation character.
570    Colon,
571    /// This represents the "@" punctuation character.
572    At,
573    /// This represents the "+" punctuation character.
574    Plus,
575    /// This represents the "-" punctuation character.
576    Minus,
577    /// This represents the "*" punctuation character.
578    Star,
579    /// This represents the "**" punctuation sequence.
580    Power,
581    /// This represents the "/" punctuation character.
582    Slash,
583    /// This represents the "//" punctuation sequence.
584    SlashSlash,
585    /// This represents the "%" punctuation character.
586    Modulo,
587    /// This represents the "`" punctuation character.
588    BackTick,
589    /// This represents the "$" punctuation character.
590    Dollar,
591    /// This represents the "true" keyword.
592    True,
593    /// This represents the "false" keyword.
594    False,
595    /// This represents the "null" keyword.
596    None,
597    /// This represents an equivalence - the "is" operator.
598    Is,
599    /// This represents a containment - the "in" operator.
600    In,
601    /// This represents a logical negation - the ! or "not" operator.
602    Not,
603    /// This represents a logical and - the && or "and" operator.
604    And,
605    /// This represents a logical or - the || or "or" operator.
606    Or,
607    /// This represents a bitwise and - the & operator.
608    BitwiseAnd,
609    /// This represents a bitwise or - the | operator.
610    BitwiseOr,
611    /// This represents a bitwise exclusive or - the ^ operator.
612    BitwiseXor,
613    /// This represents a bitwise complement - the ~ operator.
614    BitwiseComplement,
615    /// This represents a complex value.
616    Complex,
617    /// This represents the "is not" operator.
618    IsNot,
619    /// This represents the "not in" operator.
620    NotIn,
621}
622
623/// This represents a scalar value corresponding to a token.
624#[derive(Debug, Clone, PartialEq)]
625pub enum ScalarValue {
626    /// This is the (absence of) value for punctuation tokens.
627    None,
628    // Above: absence of a value (e.g. punctuation tokens). Note that we could remove this and use
629    // Option<ScalarValue>, but this just leads to a lot of unwrap() and Some(xxx) all over
630    // the place, which hurts readability.
631    /// This is the value for the "null" keyword.
632    Null,
633    /// This is the value for the "true" and "false" keywords.
634    Bool(bool),
635    /// This is the value for an identifier.
636    Identifier(String),
637    /// This is the value for a string literal.
638    String(String),
639    /// This is the value for an integer.
640    Integer(i64),
641    /// This is the value for a floating-point number.
642    Float(f64),
643    /// This is the value for a complex number.
644    Complex(Complex64),
645    /// This is the value for a date.
646    Date(NaiveDate),
647    /// This is the value for a date/time.
648    DateTime(DateTime<FixedOffset>),
649}
650
651impl fmt::Display for ScalarValue {
652    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653        match self {
654            ScalarValue::None => write!(f, "<None>"),
655            ScalarValue::Bool(b) => write!(f, "{}", b),
656            ScalarValue::Null => write!(f, "null"),
657            ScalarValue::Integer(i) => write!(f, "{}", i),
658            ScalarValue::Identifier(s) => write!(f, "{}", s),
659            ScalarValue::String(s) => write!(f, "{}", s),
660            ScalarValue::Float(fv) => write!(f, "{}", fv),
661            ScalarValue::Complex(c) => {
662                if c.re != 0f64 && c.im != 0f64 {
663                    write!(f, "{} + {}j", c.re, c.im)
664                } else if c.re == 0f64 {
665                    write!(f, "{}j", c.im)
666                } else {
667                    write!(f, "{}", c.re)
668                }
669            }
670            ScalarValue::Date(d) => write!(f, "Date<{}>", d),
671            ScalarValue::DateTime(dt) => write!(f, "DateTime<{}>", dt),
672        }
673    }
674}
675
676/// This represents a lexical token in CFG source.
677#[derive(Debug, Clone, PartialEq)]
678pub struct Token {
679    /// This is the kind of token.
680    pub kind: TokenKind,
681    /// This is the text of the token.
682    pub text: String,
683    /// This is the value of the token.
684    pub value: ScalarValue,
685    /// This is the location of the start of the token.
686    pub start: Location,
687    /// This is the location of the end of the token.
688    pub end: Location,
689}
690
691impl fmt::Display for Token {
692    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
693        write!(
694            f,
695            "Token[{}, {}]({:?}:{}:{})",
696            self.start.line, self.start.column, self.kind, self.text, self.value
697        )
698    }
699}
700
701/// This represents a unary node, typically used in expressions such as -A.
702#[derive(Debug, Clone, PartialEq)]
703pub struct UnaryNode {
704    /// This is the kind of node, i.e. the operator.
705    pub(crate) kind: TokenKind,
706    /// This is the operand.
707    pub(crate) operand: Box<ASTValue>,
708    /// This is the location of the node, usually that of the operator.
709    pub start: Location,
710}
711
712impl fmt::Display for UnaryNode {
713    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
714        write!(
715            f,
716            "UnaryNode[{}, {}]({:?}, {})",
717            self.start.line, self.start.column, self.kind, self.operand
718        )
719    }
720}
721
722/// This represents a binary node, typically used in expressions such as A + B.
723#[derive(Debug, Clone, PartialEq)]
724pub struct BinaryNode {
725    /// This is the kind of node, i.e. the operator.
726    pub(crate) kind: TokenKind,
727    /// This is the left-hand side of the binary.
728    pub(crate) left: Box<ASTValue>,
729    /// This is the right-hand side of the binary.
730    pub(crate) right: Box<ASTValue>,
731    /// This is the location of the node, usually that of the operator.
732    pub start: Location,
733}
734
735impl fmt::Display for BinaryNode {
736    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
737        write!(
738            f,
739            "BinaryNode[{}, {}]({:?}, {}, {})",
740            self.start.line, self.start.column, self.kind, self.left, self.right
741        )
742    }
743}
744
745/// This represents AST nodes corresponding to fragments of CFG source.
746#[derive(Debug, Clone, PartialEq)]
747pub enum ASTValue {
748    /// This is a token in the CFG grammar.
749    TokenValue(Token),
750    /// This is a unary node.
751    Unary(UnaryNode),
752    /// This is a binary node.
753    Binary(BinaryNode),
754    /// This is a list node.
755    List(Vec<ASTValue>),
756    /// This is a mapping node.
757    Mapping(Vec<(Token, ASTValue)>),
758    /// This is a slice node. It's produced when parsing slices.
759    Slice(
760        Location,
761        Box<Option<ASTValue>>,
762        Box<Option<ASTValue>>,
763        Box<Option<ASTValue>>,
764    ),
765}
766
767impl fmt::Display for ASTValue {
768    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
769        match self {
770            ASTValue::TokenValue(t) => write!(f, "{}", t),
771            ASTValue::Unary(u) => write!(f, "{}", u),
772            ASTValue::Binary(b) => write!(f, "{}", b),
773            ASTValue::List(lv) => {
774                let mut s = "[".to_string();
775                for e in lv {
776                    write!(s, "{}", e).unwrap();
777                    write!(s, ", ").unwrap();
778                }
779                // remove last ", "
780                s.pop();
781                s.pop();
782                write!(s, "]").unwrap();
783                write!(f, "{}", s)
784            }
785            ASTValue::Mapping(mv) => {
786                let mut s = "{".to_string();
787                for e in mv {
788                    write!(s, "{}", e.0).unwrap();
789                    write!(s, ":").unwrap();
790                    write!(s, "{}", e.1).unwrap();
791                    write!(s, ", ").unwrap();
792                }
793                // remove last ", "
794                s.pop();
795                s.pop();
796                write!(s, "}}").unwrap();
797                write!(f, "{}", s)
798            }
799            ASTValue::Slice(loc, start, stop, step) => {
800                write!(f, "Slice[{}, {}](", loc.line, loc.column).unwrap();
801                match &**start {
802                    None => write!(f, "None").unwrap(),
803                    Some(v) => write!(f, "{}", v).unwrap(),
804                };
805                write!(f, ", ").unwrap();
806                match &**stop {
807                    None => write!(f, "None").unwrap(),
808                    Some(v) => write!(f, "{}", v).unwrap(),
809                };
810                write!(f, ", ").unwrap();
811                match &**step {
812                    None => write!(f, "None").unwrap(),
813                    Some(v) => write!(f, "{}", v).unwrap(),
814                };
815                write!(f, ")")
816                // write!(f, "Slice({}, {:?}, {:?}, {:?})", loc, start, stop, step)
817            }
818        }
819    }
820}
821
822struct PushBackInfo {
823    pub(crate) c: char,
824    pub(crate) location: Location,
825}
826
827pub(crate) struct Tokenizer<'a> {
828    reader: Decoder<'a>,
829    char_location: Location,
830    location: Location,
831    pushed_back: Vec<PushBackInfo>,
832    log: bool,
833}
834
835macro_rules! get_char {
836    ($self: expr) => {{
837        let r = $self.get_char();
838
839        match r {
840            Err(_) => {
841                return Err(RecognizerError::Io($self.char_location.clone()));
842            }
843            Ok(c) => c,
844        }
845    }};
846}
847
848macro_rules! append_char {
849    ($self: expr, $text: expr, $c: expr, $endloc: expr) => {{
850        $text.push($c);
851        $endloc.update(&$self.char_location);
852    }};
853}
854
855pub(crate) fn is_identifier(s: &str) -> bool {
856    IDENTIFIER_PATTERN.is_match(s)
857}
858
859fn find_in_slice(text: &[char], c: char) -> isize {
860    let mut result = -1;
861
862    for (i, ch) in text.iter().enumerate() {
863        if *ch == c {
864            result = i as isize;
865            break;
866        }
867    }
868    result
869}
870
871macro_rules! loc {
872    ($line:expr, $column:expr) => {{
873        Location {
874            line: $line,
875            column: $column,
876        }
877    }};
878}
879
880impl<'a> Tokenizer<'a> {
881    pub(crate) fn new(r: Box<dyn Read + 'a>) -> Self {
882        let br = BufReader::new(r);
883        let b = Box::new(br);
884        Self {
885            reader: Decoder::new(b),
886            char_location: loc!(1, 1),
887            location: loc!(1, 1),
888            pushed_back: vec![],
889            log: false,
890        }
891    }
892
893    pub(crate) fn push_back(&mut self, c: char) {
894        let push_back_info = PushBackInfo {
895            c,
896            location: self.char_location,
897        };
898        self.pushed_back.push(push_back_info);
899    }
900
901    pub(crate) fn get_char(&mut self) -> Result<Option<char>> {
902        let result;
903
904        if let Some(push_back_info) = self.pushed_back.pop() {
905            result = Ok(Some(push_back_info.c));
906            self.char_location.update(&push_back_info.location);
907            self.location.update(&push_back_info.location); // will be bumped later
908        } else {
909            self.char_location.update(&self.location);
910            match self.reader.decode() {
911                DecodeResult::Char(c, _) => {
912                    result = Ok(Some(c));
913                }
914                DecodeResult::EOF => {
915                    result = Ok(Option::None);
916                }
917                DecodeResult::Error(e) => match e {
918                    DecoderError::Io(e) => result = Err(e),
919                    e => {
920                        result = Err(Error::new(ErrorKind::InvalidData, e));
921                    }
922                },
923            }
924        }
925        if let Ok(v) = &result {
926            if let Some(c) = v {
927                self.location.column += 1;
928                if *c == '\n' {
929                    self.location.next_line();
930                }
931            }
932        }
933        result
934    }
935
936    fn get_number(
937        &mut self,
938        text: &mut Vec<char>,
939        start_location: Location,
940        end_location: &mut Location,
941    ) -> StdResult<(TokenKind, ScalarValue), RecognizerError> {
942        let mut kind = TokenKind::Number;
943        let mut value = ScalarValue::None;
944        let mut in_exponent = false;
945        let mut radix = 0;
946        let mut dot_seen = text.contains(&'.');
947        let mut last_was_digit = match text.last() {
948            None => false,
949            Some(c) => c.is_ascii_hexdigit(),
950        };
951        let mut fail_location: Option<Location> = Option::None;
952        let mut lastc;
953
954        fn ends_with(text: &[char], c: char) -> bool {
955            match text.last() {
956                None => false,
957                Some(ch) => *ch == c,
958            }
959        }
960
961        loop {
962            let c = get_char!(self);
963
964            lastc = c;
965            match c {
966                None => break,
967                Some(ch) => {
968                    if ch == '.' {
969                        dot_seen = true;
970                    }
971                    if ch == '_' {
972                        if last_was_digit {
973                            append_char!(self, text, ch, end_location);
974                            last_was_digit = false;
975                            continue;
976                        }
977                        fail_location = Some(self.char_location);
978                    }
979                    last_was_digit = false; // unless set in one of the clauses below
980                    if ((radix == 0) && (ch >= '0') && (ch <= '9'))
981                        || ((radix == 2) && (ch >= '0') && (ch <= '1'))
982                        || ((radix == 8) && (ch >= '0') && (ch <= '7'))
983                        || ((radix == 16) && ch.is_ascii_hexdigit())
984                    {
985                        append_char!(self, text, ch, end_location);
986                        last_was_digit = true;
987                    } else if ((ch == 'o')
988                        || (ch == 'O')
989                        || (ch == 'x')
990                        || (ch == 'X')
991                        || (ch == 'b')
992                        || (ch == 'B'))
993                        && (text.len() == 1)
994                        && (text[0] == '0')
995                    {
996                        if (ch == 'o') || (ch == 'O') {
997                            radix = 8;
998                        } else if (ch == 'x') || (ch == 'X') {
999                            radix = 16;
1000                        } else {
1001                            radix = 2;
1002                        }
1003                        append_char!(self, text, ch, end_location);
1004                    } else if (radix == 0) && (ch == '.') && !in_exponent && !text.contains(&ch) {
1005                        append_char!(self, text, ch, end_location);
1006                    } else if (radix == 0)
1007                        && (ch == '-')
1008                        && !text[1..].contains(&'-')
1009                        && in_exponent
1010                    {
1011                        append_char!(self, text, ch, end_location);
1012                    } else if (radix == 0)
1013                        && ((ch == 'e') || (ch == 'E'))
1014                        && !text.contains(&'e')
1015                        && !text.contains(&'E')
1016                    {
1017                        if ends_with(text, '_') {
1018                            fail_location = Some(self.char_location);
1019                            break;
1020                        } else {
1021                            append_char!(self, text, ch, end_location);
1022                            in_exponent = true;
1023                        }
1024                    } else {
1025                        break;
1026                    }
1027                }
1028            }
1029        }
1030        if ends_with(text, '_') {
1031            if fail_location.is_none() {
1032                let mut loc = self.char_location;
1033
1034                loc.column -= 1;
1035                fail_location = Some(loc);
1036            }
1037        } else {
1038            match lastc {
1039                None => {}
1040                Some(ch) => {
1041                    if (radix == 0) && ((ch == 'j') || (ch == 'J')) {
1042                        append_char!(self, text, ch, end_location);
1043                        kind = TokenKind::Complex;
1044                    } else {
1045                        // not allowed to have a letter or digit which wasn't accepted
1046                        if (ch != '.') && !ch.is_alphanumeric() {
1047                            self.push_back(ch);
1048                        } else {
1049                            fail_location = Some(self.char_location);
1050                        }
1051                    }
1052                }
1053            }
1054        }
1055        if fail_location.is_none() {
1056            let s = text.iter().cloned().collect::<String>().replace("_", "");
1057            if radix != 0 {
1058                match i64::from_str_radix(&s[2..], radix) {
1059                    Ok(v) => value = ScalarValue::Integer(v),
1060                    Err(_) => fail_location = Some(start_location),
1061                }
1062            } else if kind == TokenKind::Complex {
1063                match s[..s.len() - 1].parse::<f64>() {
1064                    Ok(v) => value = ScalarValue::Complex(Complex64::new(0.0, v)),
1065                    Err(_) => fail_location = Some(start_location),
1066                }
1067            } else if in_exponent || dot_seen {
1068                match s.parse::<f64>() {
1069                    Ok(v) => value = ScalarValue::Float(v),
1070                    Err(_) => fail_location = Some(start_location),
1071                }
1072            } else {
1073                radix = if text[0] == '0' { 8 } else { 10 };
1074                match i64::from_str_radix(&s, radix) {
1075                    Ok(v) => value = ScalarValue::Integer(v),
1076                    Err(_) => fail_location = Some(start_location),
1077                }
1078            }
1079        }
1080        match fail_location {
1081            Some(loc) => Err(RecognizerError::InvalidNumber(loc)),
1082            None => Ok((kind, value)),
1083        }
1084    }
1085
1086    fn parse_escapes(
1087        &self,
1088        mut text: &[char],
1089        loc: Location,
1090    ) -> StdResult<String, RecognizerError> {
1091        let result;
1092        let mut i = find_in_slice(text, '\\');
1093
1094        if i < 0 {
1095            result = text.iter().cloned().collect::<String>();
1096        } else {
1097            let mut out: Vec<char> = vec![];
1098            let mut failed = false;
1099
1100            while i >= 0 {
1101                let n = text.len();
1102                let mut u = i as usize;
1103
1104                if i > 0 {
1105                    out.extend_from_slice(&text[..u]);
1106                }
1107                let c = text[i as usize + 1];
1108                if ESCAPES.contains_key(&c) {
1109                    out.push(ESCAPES[&c]);
1110                    u += 2;
1111                } else if c == 'x' || c == 'X' || c == 'u' || c == 'U' {
1112                    let slen = if c == 'x' || c == 'X' {
1113                        4
1114                    } else if c == 'u' {
1115                        6
1116                    } else {
1117                        10
1118                    };
1119
1120                    if u + slen > n {
1121                        failed = true;
1122                        break;
1123                    }
1124                    let p = text[u + 2..u + slen].iter().cloned().collect::<String>();
1125                    match u32::from_str_radix(&p, 16) {
1126                        Ok(v) => match std::char::from_u32(v) {
1127                            Some(c) => {
1128                                out.push(c);
1129                                u += slen;
1130                            }
1131                            None => {
1132                                failed = true;
1133                                break;
1134                            }
1135                        },
1136                        Err(_) => {
1137                            failed = true;
1138                            break;
1139                        }
1140                    }
1141                } else {
1142                    failed = true;
1143                    break;
1144                }
1145                text = &text[u..];
1146                i = find_in_slice(text, '\\');
1147            }
1148            if failed {
1149                return Err(RecognizerError::InvalidEscapeSequence(i as usize, loc));
1150            }
1151            out.extend(text);
1152            result = out.iter().cloned().collect::<String>();
1153        }
1154        Ok(result)
1155    }
1156
1157    pub(crate) fn get_token(&mut self) -> StdResult<Token, RecognizerError> {
1158        let mut kind;
1159        let mut value = ScalarValue::None;
1160        let mut text: Vec<char> = vec![];
1161        let mut start_location = loc!(1, 1);
1162        let mut end_location = loc!(1, 1);
1163        let mut s = String::new();
1164
1165        loop {
1166            let mut c = get_char!(self);
1167
1168            start_location.update(&self.char_location);
1169            // This value will be overridden for Newline below, but is
1170            // generally the right value
1171            end_location.update(&self.char_location);
1172
1173            match c {
1174                None => {
1175                    kind = TokenKind::EOF;
1176                    break;
1177                }
1178                Some('#') => {
1179                    text.push('#');
1180                    kind = TokenKind::Newline;
1181                    loop {
1182                        let ch = get_char!(self);
1183                        match ch {
1184                            None => break,
1185                            Some(c) => {
1186                                text.push(c);
1187                                if c == '\n' {
1188                                    break;
1189                                }
1190                            }
1191                        }
1192                    }
1193                    //                    self.location.next_line();
1194                    end_location.update(&self.location);
1195                    break;
1196                }
1197                Some('\n') => {
1198                    append_char!(self, text, '\n', end_location);
1199                    kind = TokenKind::Newline;
1200                    end_location.update(&self.location);
1201                    end_location.column -= 1;
1202                    break;
1203                }
1204                Some('\r') => {
1205                    let nc = get_char!(self);
1206
1207                    match nc {
1208                        None => {}
1209                        Some('\n') => {}
1210                        Some(c) => self.push_back(c),
1211                    }
1212                    kind = TokenKind::Newline;
1213                    end_location.update(&self.location);
1214                    end_location.column -= 1;
1215                    break;
1216                }
1217                Some('\\') => {
1218                    let nc = get_char!(self);
1219
1220                    match nc {
1221                        None => {}
1222                        Some('\n') => {
1223                            end_location.update(&self.location);
1224                            continue;
1225                        }
1226                        Some('\r') => {
1227                            let nnc = get_char!(self);
1228
1229                            match nnc {
1230                                None => {}
1231                                Some('\n') => {
1232                                    end_location.update(&self.location);
1233                                    continue;
1234                                }
1235                                Some(c) => {
1236                                    return Err(RecognizerError::UnexpectedCharacter(
1237                                        c,
1238                                        self.char_location,
1239                                    ));
1240                                }
1241                            }
1242                        }
1243                        Some(c) => {
1244                            return Err(RecognizerError::UnexpectedCharacter(
1245                                c,
1246                                self.char_location,
1247                            ));
1248                        }
1249                    }
1250                }
1251                Some(ch) if ch.is_whitespace() => continue,
1252                Some(ch) if ch.is_alphabetic() || ch == '_' => {
1253                    kind = TokenKind::Word;
1254
1255                    append_char!(self, text, ch, end_location);
1256                    loop {
1257                        c = get_char!(self);
1258                        match c {
1259                            None => break,
1260                            Some(c) if c.is_alphanumeric() || c == '_' => {
1261                                append_char!(self, text, c, end_location)
1262                            }
1263                            Some(c) => {
1264                                self.push_back(c);
1265                                break;
1266                            }
1267                        }
1268                    }
1269                    s = text.iter().cloned().collect::<String>();
1270                    if self.log {
1271                        println!("word: {}", s);
1272                    }
1273                    if !KEYWORDS.contains_key(&s) {
1274                        value = ScalarValue::Identifier(s.clone());
1275                    } else {
1276                        kind = KEYWORDS[&s];
1277                        if KEYWORD_VALUES.contains_key(&s) {
1278                            value = KEYWORD_VALUES[&s].clone();
1279                        }
1280                    }
1281                    break;
1282                }
1283                Some('`') => {
1284                    let mut unterminated = false;
1285
1286                    kind = TokenKind::BackTick;
1287                    append_char!(self, text, '`', end_location);
1288                    loop {
1289                        let c = get_char!(self);
1290
1291                        match c {
1292                            None => {
1293                                unterminated = true;
1294                                break;
1295                            }
1296                            Some(ch) if !ch.is_control() => {
1297                                append_char!(self, text, ch, end_location);
1298                                if ch == '`' {
1299                                    break;
1300                                }
1301                            }
1302                            Some(_ch) => {
1303                                return Err(RecognizerError::InvalidString(self.char_location));
1304                            }
1305                        }
1306                    }
1307                    if self.char_location.column > 1 {
1308                        self.char_location.column -= 1;
1309                    }
1310                    if unterminated {
1311                        return Err(RecognizerError::UnterminatedString(self.char_location));
1312                    }
1313                    value = ScalarValue::String(
1314                        self.parse_escapes(&text[1..text.len() - 1], start_location)?,
1315                    );
1316                    break;
1317                }
1318                Some(ch) if ch == '\'' || ch == '"' => {
1319                    kind = TokenKind::String;
1320
1321                    let quote = ch;
1322                    let mut multi_line = false;
1323                    let mut escaped = false;
1324                    let mut unterminated = false;
1325
1326                    append_char!(self, text, ch, end_location);
1327                    let c1 = get_char!(self);
1328                    let c1_loc = self.char_location;
1329
1330                    match c1 {
1331                        None => unterminated = true,
1332                        Some(ch1) => {
1333                            if ch1 != quote {
1334                                self.push_back(ch1);
1335                            } else {
1336                                let c2 = get_char!(self);
1337
1338                                match c2 {
1339                                    Some(ch2) => {
1340                                        if ch2 != quote {
1341                                            self.push_back(ch2);
1342                                            self.push_back(ch1);
1343                                        } else {
1344                                            multi_line = true;
1345                                            text.push(quote);
1346                                            append_char!(self, text, quote, end_location);
1347                                        }
1348                                    }
1349                                    None => {
1350                                        self.char_location.update(&c1_loc);
1351                                        self.push_back(ch1);
1352                                    }
1353                                }
1354                            }
1355                        }
1356                    }
1357                    if self.char_location.column > 1 {
1358                        self.char_location.column -= 1;
1359                    }
1360                    if unterminated {
1361                        return Err(RecognizerError::UnterminatedString(self.char_location));
1362                    }
1363                    let quoter_len = text.len();
1364                    loop {
1365                        let c = get_char!(self);
1366
1367                        match c {
1368                            None => {
1369                                unterminated = true;
1370                                break;
1371                            }
1372                            Some(ch) => {
1373                                append_char!(self, text, ch, end_location);
1374                                if ch == quote && !escaped {
1375                                    let n = text.len();
1376                                    if !multi_line
1377                                        || (n >= 6)
1378                                            && (text[n - 3..n] == text[..3])
1379                                            && text[n - 4] != '\\'
1380                                    {
1381                                        break;
1382                                    }
1383                                }
1384                                escaped = if ch == '\\' { !escaped } else { false };
1385                            }
1386                        }
1387                    }
1388                    if self.char_location.column > 1 {
1389                        self.char_location.column -= 1;
1390                    }
1391                    if unterminated {
1392                        return Err(RecognizerError::UnterminatedString(self.char_location));
1393                    }
1394                    value = ScalarValue::String(self.parse_escapes(
1395                        &text[quoter_len..text.len() - quoter_len],
1396                        start_location,
1397                    )?);
1398                    break;
1399                }
1400                Some(ch) if ch.is_numeric() => {
1401                    append_char!(self, text, ch, end_location);
1402                    // sadly, can't use direct destructuring (kind, value) = ...
1403                    let (k, v) = self.get_number(&mut text, start_location, &mut end_location)?;
1404                    kind = k;
1405                    value = v;
1406                    break;
1407                }
1408                Some('=') => {
1409                    let nc = get_char!(self);
1410
1411                    match nc {
1412                        Some('=') => {
1413                            kind = TokenKind::Equal;
1414                            text.push('=');
1415                            append_char!(self, text, '=', end_location);
1416                            break;
1417                        }
1418                        Some(nch) => {
1419                            kind = TokenKind::Assign;
1420                            append_char!(self, text, '=', end_location);
1421                            self.push_back(nch);
1422                            break;
1423                        }
1424                        None => {
1425                            kind = TokenKind::Assign;
1426                            append_char!(self, text, '=', end_location);
1427                            break;
1428                        }
1429                    }
1430                }
1431                Some(ch) if PUNCTUATION.contains_key(&ch) => {
1432                    kind = PUNCTUATION[&ch];
1433                    append_char!(self, text, ch, end_location);
1434                    match ch {
1435                        '-' => {
1436                            let nc = get_char!(self);
1437                            match nc {
1438                                None => break,
1439                                Some(nch) if nch.is_numeric() || (nch == '.') => {
1440                                    append_char!(self, text, nch, end_location);
1441                                    // sadly, can't use direct destructuring (kind, value) = ...
1442                                    let (k, v) = self.get_number(
1443                                        &mut text,
1444                                        start_location,
1445                                        &mut end_location,
1446                                    )?;
1447                                    kind = k;
1448                                    value = v;
1449                                }
1450                                Some(nch) => self.push_back(nch),
1451                            }
1452                        }
1453                        '.' => {
1454                            let nc = get_char!(self);
1455
1456                            match nc {
1457                                None => break,
1458                                Some(nch) if nch.is_numeric() => {
1459                                    append_char!(self, text, nch, end_location);
1460                                    // sadly, can't use direct destructuring (kind, value) = ...
1461                                    let (k, v) = self.get_number(
1462                                        &mut text,
1463                                        start_location,
1464                                        &mut end_location,
1465                                    )?;
1466                                    kind = k;
1467                                    value = v;
1468                                }
1469                                Some(nch) => self.push_back(nch),
1470                            }
1471                        }
1472                        '<' => {
1473                            let nc = get_char!(self);
1474
1475                            match nc {
1476                                None => {}
1477                                Some(nch) => {
1478                                    if "=<>".contains(nch) {
1479                                        append_char!(self, text, nch, end_location);
1480                                    }
1481                                    match nch {
1482                                        '=' => kind = TokenKind::LessThanOrEqual,
1483                                        '<' => kind = TokenKind::LeftShift,
1484                                        '>' => kind = TokenKind::AltUnequal,
1485                                        _ => self.push_back(nch),
1486                                    }
1487                                }
1488                            }
1489                            break;
1490                        }
1491                        '>' => {
1492                            let nc = get_char!(self);
1493
1494                            match nc {
1495                                None => {}
1496                                Some(nch) => {
1497                                    if "=>".contains(nch) {
1498                                        append_char!(self, text, nch, end_location);
1499                                    }
1500                                    match nch {
1501                                        '=' => kind = TokenKind::GreaterThanOrEqual,
1502                                        '>' => kind = TokenKind::RightShift,
1503                                        _ => self.push_back(nch),
1504                                    }
1505                                }
1506                            }
1507                            break;
1508                        }
1509                        '!' => {
1510                            let nc = get_char!(self);
1511
1512                            match nc {
1513                                None => {}
1514                                Some(nch) => match nch {
1515                                    '=' => {
1516                                        append_char!(self, text, nch, end_location);
1517                                        kind = TokenKind::Unequal;
1518                                    }
1519                                    _ => self.push_back(nch),
1520                                },
1521                            }
1522                            break;
1523                        }
1524                        '*' => {
1525                            let nc = get_char!(self);
1526
1527                            match nc {
1528                                None => {}
1529                                Some(nch) => match nch {
1530                                    '*' => {
1531                                        append_char!(self, text, nch, end_location);
1532                                        kind = TokenKind::Power;
1533                                    }
1534                                    _ => self.push_back(nch),
1535                                },
1536                            }
1537                            break;
1538                        }
1539                        '/' => {
1540                            let nc = get_char!(self);
1541
1542                            match nc {
1543                                None => {}
1544                                Some(nch) => match nch {
1545                                    '/' => {
1546                                        append_char!(self, text, nch, end_location);
1547                                        kind = TokenKind::SlashSlash;
1548                                    }
1549                                    _ => self.push_back(nch),
1550                                },
1551                            }
1552                            break;
1553                        }
1554                        '&' | '|' => {
1555                            let nc = get_char!(self);
1556
1557                            match nc {
1558                                None => {}
1559                                Some(nch) => {
1560                                    if nch == ch {
1561                                        append_char!(self, text, nch, end_location);
1562                                        kind = if ch == '&' {
1563                                            TokenKind::And
1564                                        } else {
1565                                            TokenKind::Or
1566                                        }
1567                                    }
1568                                }
1569                            }
1570                            break;
1571                        }
1572                        _ => {}
1573                    }
1574                    break;
1575                }
1576                Some(ch) => {
1577                    return Err(RecognizerError::UnexpectedCharacter(ch, self.char_location));
1578                }
1579            }
1580        }
1581        if self.log {
1582            println!("{}, {}, {:?}", kind as i32, s, value);
1583        }
1584        if s.is_empty() {
1585            s = text.iter().cloned().collect::<String>();
1586        }
1587        Ok(Token {
1588            kind,
1589            text: s,
1590            value,
1591            start: start_location,
1592            end: end_location,
1593        })
1594    }
1595}
1596
1597/// This implements the low-level parser of CFG source text.
1598pub struct Parser<'a> {
1599    tokenizer: Tokenizer<'a>,
1600    next_token: Token,
1601}
1602
1603pub(crate) fn token_text(k: TokenKind) -> String {
1604    TOKEN_TEXT[&k].clone()
1605}
1606
1607impl<'a> Parser<'a> {
1608    /// Return a new instance of the parser using the provided reader for the source text. The
1609    /// first token is read.
1610    pub fn new(r: Box<dyn Read + 'a>) -> StdResult<Self, RecognizerError> {
1611        let mut tokenizer = Tokenizer::new(r);
1612        let t = tokenizer.get_token();
1613        match t {
1614            Err(e) => Err(e),
1615            Ok(token) => Ok(Self {
1616                tokenizer,
1617                next_token: token,
1618            }),
1619        }
1620    }
1621
1622    /// Return `true` if the parser has reached the end of the source, else `false`.
1623    pub fn at_end(&self) -> bool {
1624        self.next_token.kind == TokenKind::EOF
1625    }
1626
1627    /// Return the current location of the parser in the source.
1628    pub fn location(&self) -> Location {
1629        self.next_token.start
1630    }
1631
1632    fn advance(&mut self) -> StdResult<TokenKind, RecognizerError> {
1633        let r = self.tokenizer.get_token();
1634
1635        match r {
1636            Err(e) => Err(e),
1637            Ok(token) => {
1638                let k = token.kind;
1639
1640                self.next_token = token;
1641                Ok(k)
1642            }
1643        }
1644    }
1645
1646    fn expect(&mut self, kind: TokenKind) -> StdResult<Token, RecognizerError> {
1647        if self.next_token.kind != kind {
1648            Err(RecognizerError::UnexpectedToken(
1649                token_text(kind),
1650                token_text(self.next_token.kind),
1651                self.next_token.start,
1652            ))
1653        } else {
1654            let curr = self.next_token.clone();
1655            let r = self.advance();
1656
1657            match r {
1658                Err(e) => Err(e),
1659                Ok(_) => Ok(curr),
1660            }
1661        }
1662    }
1663
1664    pub(crate) fn consume_new_lines(&mut self) -> StdResult<TokenKind, RecognizerError> {
1665        let mut result = self.next_token.kind;
1666
1667        while result == TokenKind::Newline {
1668            result = self.advance()?;
1669        }
1670        Ok(result)
1671    }
1672
1673    pub(crate) fn strings(&mut self) -> StdResult<Token, RecognizerError> {
1674        let mut result = self.next_token.clone();
1675        let k = self.advance()?;
1676
1677        if k == TokenKind::String {
1678            let mut all_text: Vec<char> = vec![];
1679            let start = result.start;
1680            let mut end = self.next_token.end;
1681
1682            match &result.value {
1683                ScalarValue::String(s) => all_text.extend(s.chars()),
1684                e => panic!("string value expected, but found {:?}", e),
1685            }
1686            loop {
1687                match &self.next_token.value {
1688                    ScalarValue::String(s) => all_text.extend(s.chars()),
1689                    e => panic!("string value expected, but found {:?}", e),
1690                }
1691                let k = self.advance()?;
1692                if k == TokenKind::String {
1693                    end = self.next_token.end;
1694                } else {
1695                    break;
1696                }
1697            }
1698            // now construct the result
1699            let s = all_text.iter().collect::<String>();
1700            result = Token {
1701                kind: result.kind,
1702                text: s.clone(),
1703                value: ScalarValue::String(s),
1704                start,
1705                end,
1706            }
1707        }
1708        Ok(result)
1709    }
1710
1711    pub(crate) fn value(&mut self) -> StdResult<Token, RecognizerError> {
1712        let kind = self.next_token.kind;
1713
1714        if !VALUE_STARTERS.contains(&kind) {
1715            Err(RecognizerError::ValueExpected(
1716                token_text(kind),
1717                self.next_token.start,
1718            ))
1719        } else {
1720            let t;
1721
1722            if kind == TokenKind::String {
1723                t = self.strings();
1724            } else {
1725                t = Ok(self.next_token.clone());
1726                self.advance()?;
1727            }
1728            t
1729        }
1730    }
1731
1732    pub(crate) fn atom(&mut self) -> StdResult<ASTValue, RecognizerError> {
1733        let kind = self.next_token.kind;
1734
1735        match kind {
1736            TokenKind::LeftCurly => self.mapping(),
1737            TokenKind::LeftBracket => self.list(),
1738            TokenKind::LeftParenthesis => match self.expect(TokenKind::LeftParenthesis) {
1739                Err(e) => Err(e),
1740                Ok(_) => {
1741                    let result = self.expr();
1742
1743                    match self.expect(TokenKind::RightParenthesis) {
1744                        Err(e) => Err(e),
1745                        _ => result,
1746                    }
1747                }
1748            },
1749            TokenKind::Dollar => {
1750                let spos = self.next_token.start;
1751                match self.advance() {
1752                    Err(e) => Err(e),
1753                    Ok(_) => match self.expect(TokenKind::LeftCurly) {
1754                        Err(e) => Err(e),
1755                        Ok(_) => match self.primary() {
1756                            Err(e) => Err(e),
1757                            Ok(v) => match self.expect(TokenKind::RightCurly) {
1758                                Err(e) => Err(e),
1759                                _ => Ok(ASTValue::Unary(UnaryNode {
1760                                    kind,
1761                                    operand: Box::new(v),
1762                                    start: spos,
1763                                })),
1764                            },
1765                        },
1766                    },
1767                }
1768            }
1769            v => {
1770                if VALUE_STARTERS.contains(&v) {
1771                    match self.value() {
1772                        Err(e) => Err(e),
1773                        Ok(v) => Ok(ASTValue::TokenValue(v)),
1774                    }
1775                } else {
1776                    Err(RecognizerError::AtomExpected(
1777                        token_text(v),
1778                        self.next_token.start,
1779                    ))
1780                }
1781            }
1782        }
1783    }
1784
1785    fn list_element(&mut self) -> StdResult<ASTValue, RecognizerError> {
1786        let loc = self.next_token.start;
1787        let result;
1788        let v = self.list_body()?;
1789
1790        match v {
1791            ASTValue::List(lv) => {
1792                let n = lv.len();
1793
1794                if n != 1 {
1795                    return Err(RecognizerError::UnexpectedListSize(loc));
1796                }
1797                result = lv[0].clone();
1798            }
1799            _ => {
1800                panic!("unexpected when parsing list: {:?}", v);
1801            }
1802        }
1803        Ok(result)
1804    }
1805
1806    pub(crate) fn trailer(&mut self) -> StdResult<(TokenKind, ASTValue), RecognizerError> {
1807        let mut kind = self.next_token.kind;
1808        let result;
1809
1810        if kind != TokenKind::LeftBracket {
1811            self.expect(TokenKind::Dot)?;
1812            result = ASTValue::TokenValue(self.expect(TokenKind::Word)?);
1813        } else {
1814            kind = self.advance()?;
1815
1816            let spos = self.next_token.start;
1817            let is_slice;
1818            let mut start: Option<ASTValue> = None;
1819
1820            if kind == TokenKind::Colon {
1821                // it's a slice like [:xyz:abc]
1822                is_slice = true;
1823            } else {
1824                start = Some(self.list_element()?);
1825                is_slice = self.next_token.kind == TokenKind::Colon;
1826            }
1827            if !is_slice {
1828                kind = TokenKind::LeftBracket;
1829                result = start.unwrap();
1830            } else {
1831                let mut stop: Option<ASTValue> = None;
1832                let mut step: Option<ASTValue> = None;
1833                let mut tk = self.advance()?;
1834
1835                if tk == TokenKind::Colon {
1836                    // no stop, but there might be a step
1837                    tk = self.advance()?;
1838                    if tk != TokenKind::RightBracket {
1839                        step = Some(self.list_element()?);
1840                    }
1841                } else if tk != TokenKind::RightBracket {
1842                    stop = Some(self.list_element()?);
1843                    if self.next_token.kind == TokenKind::Colon {
1844                        let tk = self.advance()?;
1845
1846                        if tk != TokenKind::RightBracket {
1847                            step = Some(self.list_element()?);
1848                        }
1849                    }
1850                }
1851                kind = TokenKind::Colon;
1852                result = ASTValue::Slice(spos, Box::new(start), Box::new(stop), Box::new(step));
1853            }
1854            self.expect(TokenKind::RightBracket)?;
1855        }
1856        Ok((kind, result))
1857    }
1858
1859    pub(crate) fn primary(&mut self) -> StdResult<ASTValue, RecognizerError> {
1860        let mut result = self.atom();
1861
1862        if result.is_err() {
1863            return result;
1864        }
1865        let mut kind = self.next_token.kind;
1866
1867        while kind == TokenKind::Dot || kind == TokenKind::LeftBracket {
1868            let rhs;
1869            let spos = self.next_token.start;
1870            let (k, r) = self.trailer()?;
1871
1872            kind = k;
1873            rhs = r;
1874            result = Ok(ASTValue::Binary(BinaryNode {
1875                kind,
1876                left: Box::new(result.expect("a valid LHS was expected")),
1877                right: Box::new(rhs),
1878                start: spos,
1879            }));
1880            kind = self.next_token.kind;
1881        }
1882        result
1883    }
1884
1885    pub(crate) fn list_body(&mut self) -> StdResult<ASTValue, RecognizerError> {
1886        match self.consume_new_lines() {
1887            Err(e) => Err(e),
1888            Ok(mut k) => {
1889                let mut result = vec![];
1890
1891                while EXPRESSION_STARTERS.contains(&k) {
1892                    result.push(self.expr()?);
1893                    k = self.next_token.kind;
1894                    if k != TokenKind::Newline && k != TokenKind::Comma {
1895                        break;
1896                    }
1897                    self.advance()?;
1898                    k = self.consume_new_lines()?;
1899                }
1900                Ok(ASTValue::List(result))
1901            }
1902        }
1903    }
1904
1905    pub(crate) fn list(&mut self) -> StdResult<ASTValue, RecognizerError> {
1906        match self.expect(TokenKind::LeftBracket) {
1907            Err(e) => Err(e),
1908            Ok(_) => match self.list_body() {
1909                Err(e) => Err(e),
1910                Ok(lb) => match self.expect(TokenKind::RightBracket) {
1911                    Err(e) => Err(e),
1912                    Ok(_) => Ok(lb),
1913                },
1914            },
1915        }
1916    }
1917
1918    pub(crate) fn object_key(&mut self) -> StdResult<Token, RecognizerError> {
1919        let result;
1920
1921        if self.next_token.kind == TokenKind::String {
1922            self.strings()
1923        } else {
1924            result = Ok(self.next_token.clone());
1925            match self.advance() {
1926                Err(e) => Err(e),
1927                Ok(_) => result,
1928            }
1929        }
1930    }
1931
1932    pub(crate) fn mapping_body(&mut self) -> StdResult<ASTValue, RecognizerError> {
1933        match self.consume_new_lines() {
1934            Err(e) => Err(e),
1935            Ok(mut k) => {
1936                if k == TokenKind::RightCurly || k == TokenKind::EOF {
1937                    // for example, an empty {} or an empty file.
1938                    Ok(ASTValue::Mapping(vec![]))
1939                } else if k != TokenKind::Word && k != TokenKind::String {
1940                    Err(RecognizerError::KeyExpected(
1941                        token_text(k),
1942                        self.next_token.start,
1943                    ))
1944                } else {
1945                    let mut result = vec![];
1946
1947                    while k == TokenKind::Word || k == TokenKind::String {
1948                        let key = self.object_key()?;
1949
1950                        k = self.next_token.kind;
1951                        if k != TokenKind::Colon && k != TokenKind::Assign {
1952                            return Err(RecognizerError::KeyValueSeparatorExpected(
1953                                token_text(k),
1954                                self.next_token.start,
1955                            ));
1956                        } else {
1957                            self.advance()?;
1958                            self.consume_new_lines()?;
1959                        }
1960                        result.push((key, self.expr()?));
1961                        k = self.next_token.kind;
1962                        if k == TokenKind::Newline || k == TokenKind::Comma {
1963                            self.advance()?;
1964                            k = self.consume_new_lines()?;
1965                        } else if k != TokenKind::RightCurly && k != TokenKind::EOF {
1966                            let s = format!(
1967                                "{} or {}",
1968                                token_text(TokenKind::RightCurly),
1969                                token_text(TokenKind::EOF)
1970                            );
1971                            return Err(RecognizerError::UnexpectedToken(
1972                                s,
1973                                token_text(self.next_token.kind),
1974                                self.next_token.start,
1975                            ));
1976                        }
1977                    }
1978                    Ok(ASTValue::Mapping(result))
1979                }
1980            }
1981        }
1982    }
1983
1984    pub(crate) fn mapping(&mut self) -> StdResult<ASTValue, RecognizerError> {
1985        match self.expect(TokenKind::LeftCurly) {
1986            Err(e) => Err(e),
1987            Ok(_) => match self.mapping_body() {
1988                Err(e) => Err(e),
1989                Ok(mb) => match self.expect(TokenKind::RightCurly) {
1990                    Err(e) => Err(e),
1991                    Ok(_) => Ok(mb),
1992                },
1993            },
1994        }
1995    }
1996
1997    /// Parse the contents of a configuration, which should be a mapping or a list, and return
1998    /// the parsed value or a syntax error.
1999    pub fn container(&mut self) -> StdResult<ASTValue, RecognizerError> {
2000        match self.consume_new_lines() {
2001            Err(e) => Err(e),
2002            Ok(k) => {
2003                if k == TokenKind::LeftCurly {
2004                    match self.mapping() {
2005                        Err(e) => Err(e),
2006                        Ok(mv) => match self.consume_new_lines() {
2007                            Err(e) => Err(e),
2008                            Ok(_) => Ok(mv),
2009                        },
2010                    }
2011                } else if k == TokenKind::LeftBracket {
2012                    match self.list() {
2013                        Err(e) => Err(e),
2014                        Ok(lv) => match self.consume_new_lines() {
2015                            Err(e) => Err(e),
2016                            Ok(_) => Ok(lv),
2017                        },
2018                    }
2019                } else if k == TokenKind::Word || k == TokenKind::String {
2020                    match self.mapping_body() {
2021                        Err(e) => Err(e),
2022                        Ok(lv) => match self.consume_new_lines() {
2023                            Err(e) => Err(e),
2024                            Ok(_) => Ok(lv),
2025                        },
2026                    }
2027                } else {
2028                    Err(RecognizerError::ContainerExpected(
2029                        token_text(k),
2030                        self.next_token.start,
2031                    ))
2032                }
2033            }
2034        }
2035    }
2036
2037    pub(crate) fn power(&mut self) -> StdResult<ASTValue, RecognizerError> {
2038        match self.primary() {
2039            Err(e) => Err(e),
2040            Ok(mut lhs) => {
2041                while self.next_token.kind == TokenKind::Power {
2042                    let spos = self.next_token.start;
2043
2044                    self.advance()?;
2045
2046                    let ue = self.unary_expr()?;
2047
2048                    lhs = ASTValue::Binary(BinaryNode {
2049                        kind: TokenKind::Power,
2050                        left: Box::new(lhs),
2051                        right: Box::new(ue),
2052                        start: spos,
2053                    })
2054                }
2055                Ok(lhs)
2056            }
2057        }
2058    }
2059
2060    pub(crate) fn unary_expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2061        let kind = self.next_token.kind;
2062        let spos = self.next_token.start;
2063
2064        if kind != TokenKind::Plus
2065            && kind != TokenKind::Minus
2066            && kind != TokenKind::BitwiseComplement
2067            && kind != TokenKind::At
2068        {
2069            self.power()
2070        } else {
2071            match self.advance() {
2072                Err(e) => Err(e),
2073                Ok(_) => match self.not_expr() {
2074                    Err(e) => Err(e),
2075                    Ok(v) => Ok(ASTValue::Unary(UnaryNode {
2076                        kind,
2077                        operand: Box::new(v),
2078                        start: spos,
2079                    })),
2080                },
2081            }
2082        }
2083    }
2084
2085    pub(crate) fn mul_expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2086        match self.unary_expr() {
2087            Err(e) => Err(e),
2088            Ok(mut lhs) => {
2089                let mut kind = self.next_token.kind;
2090
2091                while kind == TokenKind::Star
2092                    || kind == TokenKind::Slash
2093                    || kind == TokenKind::SlashSlash
2094                    || kind == TokenKind::Modulo
2095                {
2096                    let spos = self.next_token.start;
2097
2098                    self.advance()?;
2099
2100                    let ue = self.unary_expr()?;
2101
2102                    lhs = ASTValue::Binary(BinaryNode {
2103                        kind,
2104                        left: Box::new(lhs),
2105                        right: Box::new(ue),
2106                        start: spos,
2107                    });
2108                    kind = self.next_token.kind;
2109                }
2110                Ok(lhs)
2111            }
2112        }
2113    }
2114
2115    pub(crate) fn add_expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2116        match self.mul_expr() {
2117            Err(e) => Err(e),
2118            Ok(mut lhs) => {
2119                let mut kind = self.next_token.kind;
2120
2121                while kind == TokenKind::Plus || kind == TokenKind::Minus {
2122                    let spos = self.next_token.start;
2123
2124                    self.advance()?;
2125
2126                    let me = self.mul_expr()?;
2127
2128                    lhs = ASTValue::Binary(BinaryNode {
2129                        kind,
2130                        left: Box::new(lhs),
2131                        right: Box::new(me),
2132                        start: spos,
2133                    });
2134                    kind = self.next_token.kind;
2135                }
2136                Ok(lhs)
2137            }
2138        }
2139    }
2140
2141    pub(crate) fn shift_expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2142        match self.add_expr() {
2143            Err(e) => Err(e),
2144            Ok(mut lhs) => {
2145                let mut kind = self.next_token.kind;
2146
2147                while kind == TokenKind::LeftShift || kind == TokenKind::RightShift {
2148                    let spos = self.next_token.start;
2149
2150                    self.advance()?;
2151
2152                    let ae = self.add_expr()?;
2153
2154                    lhs = ASTValue::Binary(BinaryNode {
2155                        kind,
2156                        left: Box::new(lhs),
2157                        right: Box::new(ae),
2158                        start: spos,
2159                    });
2160                    kind = self.next_token.kind;
2161                }
2162                Ok(lhs)
2163            }
2164        }
2165    }
2166
2167    pub(crate) fn bitand_expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2168        match self.shift_expr() {
2169            Err(e) => Err(e),
2170            Ok(mut lhs) => {
2171                while self.next_token.kind == TokenKind::BitwiseAnd {
2172                    let spos = self.next_token.start;
2173
2174                    self.advance()?;
2175
2176                    let se = self.shift_expr()?;
2177
2178                    lhs = ASTValue::Binary(BinaryNode {
2179                        kind: TokenKind::BitwiseAnd,
2180                        left: Box::new(lhs),
2181                        right: Box::new(se),
2182                        start: spos,
2183                    })
2184                }
2185                Ok(lhs)
2186            }
2187        }
2188    }
2189
2190    pub(crate) fn bitxor_expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2191        match self.bitand_expr() {
2192            Err(e) => Err(e),
2193            Ok(mut lhs) => {
2194                while self.next_token.kind == TokenKind::BitwiseXor {
2195                    let spos = self.next_token.start;
2196
2197                    self.advance()?;
2198
2199                    let bae = self.bitand_expr()?;
2200
2201                    lhs = ASTValue::Binary(BinaryNode {
2202                        kind: TokenKind::BitwiseXor,
2203                        left: Box::new(lhs),
2204                        right: Box::new(bae),
2205                        start: spos,
2206                    })
2207                }
2208                Ok(lhs)
2209            }
2210        }
2211    }
2212
2213    pub(crate) fn bitor_expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2214        match self.bitxor_expr() {
2215            Err(e) => Err(e),
2216            Ok(mut lhs) => {
2217                while self.next_token.kind == TokenKind::BitwiseOr {
2218                    let spos = self.next_token.start;
2219
2220                    self.advance()?;
2221
2222                    let bxe = self.bitxor_expr()?;
2223
2224                    lhs = ASTValue::Binary(BinaryNode {
2225                        kind: TokenKind::BitwiseOr,
2226                        left: Box::new(lhs),
2227                        right: Box::new(bxe),
2228                        start: spos,
2229                    })
2230                }
2231                Ok(lhs)
2232            }
2233        }
2234    }
2235
2236    pub(crate) fn comparison_operator(&mut self) -> StdResult<TokenKind, RecognizerError> {
2237        let mut should_advance = false;
2238        let mut result = self.next_token.kind;
2239
2240        match self.advance() {
2241            Err(e) => Err(e),
2242            Ok(k) => {
2243                if result == TokenKind::Is && k == TokenKind::Not {
2244                    result = TokenKind::IsNot;
2245                    should_advance = true;
2246                } else if result == TokenKind::Not && k == TokenKind::In {
2247                    result = TokenKind::NotIn;
2248                    should_advance = true;
2249                }
2250                if !should_advance {
2251                    Ok(result)
2252                } else {
2253                    match self.advance() {
2254                        Err(e) => Err(e),
2255                        Ok(_) => Ok(result),
2256                    }
2257                }
2258            }
2259        }
2260    }
2261
2262    pub(crate) fn comparison(&mut self) -> StdResult<ASTValue, RecognizerError> {
2263        match self.bitor_expr() {
2264            Err(e) => Err(e),
2265            Ok(mut lhs) => {
2266                while COMPARISON_OPERATORS.contains(&self.next_token.kind) {
2267                    let spos = self.next_token.start;
2268                    let k = self.comparison_operator()?;
2269                    let boe = self.bitor_expr()?;
2270
2271                    lhs = ASTValue::Binary(BinaryNode {
2272                        kind: k,
2273                        left: Box::new(lhs),
2274                        right: Box::new(boe),
2275                        start: spos,
2276                    })
2277                }
2278                Ok(lhs)
2279            }
2280        }
2281    }
2282
2283    pub(crate) fn not_expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2284        if self.next_token.kind != TokenKind::Not {
2285            self.comparison()
2286        } else {
2287            let spos = self.next_token.start;
2288
2289            match self.advance() {
2290                Err(e) => Err(e),
2291                Ok(_) => match self.not_expr() {
2292                    Err(e) => Err(e),
2293                    Ok(v) => Ok(ASTValue::Unary(UnaryNode {
2294                        kind: TokenKind::Not,
2295                        operand: Box::new(v),
2296                        start: spos,
2297                    })),
2298                },
2299            }
2300        }
2301    }
2302
2303    pub(crate) fn and_expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2304        match self.not_expr() {
2305            Err(e) => Err(e),
2306            Ok(mut lhs) => {
2307                while self.next_token.kind == TokenKind::And {
2308                    let spos = self.next_token.start;
2309
2310                    self.advance()?;
2311
2312                    let ne = self.not_expr()?;
2313
2314                    lhs = ASTValue::Binary(BinaryNode {
2315                        kind: TokenKind::And,
2316                        left: Box::new(lhs),
2317                        right: Box::new(ne),
2318                        start: spos,
2319                    })
2320                }
2321                Ok(lhs)
2322            }
2323        }
2324    }
2325
2326    /// Parse an expression and return an AST node representing it, or a syntax error.
2327    pub fn expr(&mut self) -> StdResult<ASTValue, RecognizerError> {
2328        match self.and_expr() {
2329            Err(e) => Err(e),
2330            Ok(mut lhs) => {
2331                while self.next_token.kind == TokenKind::Or {
2332                    let spos = self.next_token.start;
2333
2334                    self.advance()?;
2335
2336                    let ae = self.and_expr()?;
2337
2338                    lhs = ASTValue::Binary(BinaryNode {
2339                        kind: TokenKind::Or,
2340                        left: Box::new(lhs),
2341                        right: Box::new(ae),
2342                        start: spos,
2343                    })
2344                }
2345                Ok(lhs)
2346            }
2347        }
2348    }
2349}
2350
2351// Use a tuple struct so that we can implement PartialEq for it. This allows PartialEq to be
2352// derived for containing structs.
2353
2354struct StringConverter(fn(&str, &Config) -> Option<Value>);
2355
2356impl PartialEq for StringConverter {
2357    fn eq(&self, other: &Self) -> bool {
2358        self.0 as usize == other.0 as usize
2359    }
2360}
2361
2362impl Clone for StringConverter {
2363    fn clone(&self) -> Self {
2364        Self(self.0)
2365    }
2366}
2367
2368impl fmt::Debug for StringConverter {
2369    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2370        write!(f, "StringConverter({:x})", self.0 as usize)
2371    }
2372}
2373
2374/// This represents a value in a configuration.
2375#[derive(Debug, Clone, PartialEq)]
2376pub enum Value {
2377    /// These are the scalar values.
2378    Base(ScalarValue),
2379    /// This is a list of values.
2380    List(Vec<Value>),
2381    /// This is a mapping of strings to values.
2382    Mapping(HashMap<String, Value>),
2383    /// This is a nested (sub-) configuration.
2384    Config(Config),
2385}
2386
2387impl From<bool> for Value {
2388    fn from(value: bool) -> Self {
2389        Value::Base(ScalarValue::Bool(value))
2390    }
2391}
2392
2393impl From<i64> for Value {
2394    fn from(value: i64) -> Self {
2395        Value::Base(ScalarValue::Integer(value))
2396    }
2397}
2398
2399impl From<f64> for Value {
2400    fn from(value: f64) -> Self {
2401        Value::Base(ScalarValue::Float(value))
2402    }
2403}
2404
2405impl From<String> for Value {
2406    fn from(value: String) -> Self {
2407        Value::Base(ScalarValue::String(value))
2408    }
2409}
2410
2411impl From<&str> for Value {
2412    fn from(value: &str) -> Self {
2413        Value::Base(ScalarValue::String(value.to_string()))
2414    }
2415}
2416
2417impl From<Complex64> for Value {
2418    fn from(value: Complex64) -> Self {
2419        Value::Base(ScalarValue::Complex(value))
2420    }
2421}
2422
2423impl From<NaiveDate> for Value {
2424    fn from(value: NaiveDate) -> Self {
2425        Value::Base(ScalarValue::Date(value))
2426    }
2427}
2428
2429impl From<DateTime<FixedOffset>> for Value {
2430    fn from(value: DateTime<FixedOffset>) -> Self {
2431        Value::Base(ScalarValue::DateTime(value))
2432    }
2433}
2434
2435impl TryInto<i64> for Value {
2436    type Error = &'static str;
2437
2438    fn try_into(self) -> StdResult<i64, Self::Error> {
2439        match self {
2440            Value::Base(b) => match b {
2441                ScalarValue::Integer(i) => Ok(i),
2442                _ => Err(&NOT_INTEGER),
2443            },
2444            _ => Err(&NOT_INTEGER),
2445        }
2446    }
2447}
2448
2449impl TryInto<String> for Value {
2450    type Error = &'static str;
2451
2452    fn try_into(self) -> StdResult<String, Self::Error> {
2453        match self {
2454            Value::Base(b) => match b {
2455                ScalarValue::String(s) => Ok(s),
2456                _ => Err(&NOT_STRING),
2457            },
2458            _ => Err(&NOT_STRING),
2459        }
2460    }
2461}
2462
2463impl TryInto<f64> for Value {
2464    type Error = &'static str;
2465
2466    fn try_into(self) -> StdResult<f64, Self::Error> {
2467        match self {
2468            Value::Base(b) => match b {
2469                ScalarValue::Float(f) => Ok(f),
2470                _ => Err(&NOT_FLOAT),
2471            },
2472            _ => Err(&NOT_FLOAT),
2473        }
2474    }
2475}
2476
2477impl TryInto<Complex64> for Value {
2478    type Error = &'static str;
2479
2480    fn try_into(self) -> StdResult<Complex64, Self::Error> {
2481        match self {
2482            Value::Base(b) => match b {
2483                ScalarValue::Complex(c) => Ok(c),
2484                _ => Err(&NOT_COMPLEX),
2485            },
2486            _ => Err(&NOT_COMPLEX),
2487        }
2488    }
2489}
2490
2491impl TryInto<NaiveDate> for Value {
2492    type Error = &'static str;
2493
2494    fn try_into(self) -> StdResult<NaiveDate, Self::Error> {
2495        match self {
2496            Value::Base(b) => match b {
2497                ScalarValue::Date(nd) => Ok(nd),
2498                _ => Err(&NOT_DATE),
2499            },
2500            _ => Err(&NOT_DATE),
2501        }
2502    }
2503}
2504
2505impl TryInto<DateTime<FixedOffset>> for Value {
2506    type Error = &'static str;
2507
2508    fn try_into(self) -> StdResult<DateTime<FixedOffset>, Self::Error> {
2509        match self {
2510            Value::Base(b) => match b {
2511                ScalarValue::DateTime(dt) => Ok(dt),
2512                _ => Err(&NOT_DATETIME),
2513            },
2514            _ => Err(&NOT_DATETIME),
2515        }
2516    }
2517}
2518
2519impl fmt::Display for Value {
2520    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2521        match self {
2522            Value::Base(b) => write!(f, "{}", b),
2523            Value::List(lv) => {
2524                let mut parts = vec![];
2525
2526                for item in lv {
2527                    parts.push(format!("{}", item));
2528                }
2529                let s = parts.join(", ");
2530                write!(f, "[{}]", s)
2531            }
2532            Value::Mapping(mv) => {
2533                let mut parts = vec![];
2534
2535                for (k, v) in mv.iter() {
2536                    parts.push(format!("{}: {}", k, v));
2537                }
2538                let s = parts.join(", ");
2539                write!(f, "{{{}}}", s)
2540            }
2541            Value::Config(cv) => write!(f, "{}", cv),
2542        }
2543    }
2544}
2545
2546impl Value {
2547    /*
2548     * The following are useful if you just want to panic on something unexpected, e.g. in tests
2549     */
2550    /// Expect a value to be a string and return it. Panic if it's not the expected type.
2551    pub fn as_string(&self) -> String {
2552        let mut result: Option<String> = None;
2553
2554        if let Value::Base(sv) = self {
2555            if let ScalarValue::String(s) = sv {
2556                result = Some(s.clone());
2557            }
2558        }
2559        match result {
2560            None => panic!("expected string value but got {:?}", self),
2561            Some(v) => v,
2562        }
2563    }
2564
2565    /// Expect a value to be an integer and return it. Panic if it's not the expected type.
2566    pub fn as_i64(&self) -> i64 {
2567        let mut result: Option<i64> = None;
2568
2569        if let Value::Base(sv) = self {
2570            if let ScalarValue::Integer(i) = sv {
2571                result = Some(*i);
2572            }
2573        }
2574        match result {
2575            None => panic!("expected integer value but got {:?}", self),
2576            Some(v) => v,
2577        }
2578    }
2579
2580    /// Expect a value to be a floating-point value and return it. Panic if it's not the expected type.
2581    pub fn as_f64(&self) -> f64 {
2582        let mut result: Option<f64> = None;
2583
2584        if let Value::Base(sv) = self {
2585            if let ScalarValue::Float(f) = sv {
2586                result = Some(*f);
2587            }
2588        }
2589        match result {
2590            None => panic!("expected floating-point value but got {:?}", self),
2591            Some(v) => v,
2592        }
2593    }
2594
2595    /// Expect a value to be a complex number and return it. Panic if it's not the expected type.
2596    pub fn as_c64(&self) -> Complex64 {
2597        let mut result: Option<Complex64> = None;
2598
2599        if let Value::Base(sv) = self {
2600            if let ScalarValue::Complex(c) = sv {
2601                result = Some(*c);
2602            }
2603        }
2604        match result {
2605            None => panic!("expected complex value but got {:?}", self),
2606            Some(v) => v,
2607        }
2608    }
2609
2610    /// Expect a value to be a Boolean and return it. Panic if it's not the expected type.
2611    pub fn as_bool(&self) -> bool {
2612        let mut result: Option<bool> = None;
2613
2614        if let Value::Base(sv) = self {
2615            if let ScalarValue::Bool(b) = sv {
2616                result = Some(*b);
2617            }
2618        }
2619        match result {
2620            None => panic!("expected boolean value but got {:?}", self),
2621            Some(v) => v,
2622        }
2623    }
2624
2625    /// Expect a value to be a date and return it. Panic if it's not the expected type.
2626    pub fn as_date(&self) -> NaiveDate {
2627        let mut result: Option<NaiveDate> = None;
2628
2629        if let Value::Base(sv) = self {
2630            if let ScalarValue::Date(nd) = sv {
2631                result = Some(*nd);
2632            }
2633        }
2634        match result {
2635            None => panic!("expected date value but got {:?}", self),
2636            Some(v) => v,
2637        }
2638    }
2639
2640    /// Expect a value to be a date/time and return it. Panic if it's not the expected type.
2641    pub fn as_datetime(&self) -> DateTime<FixedOffset> {
2642        let mut result: Option<DateTime<FixedOffset>> = None;
2643
2644        if let Value::Base(sv) = self {
2645            if let ScalarValue::DateTime(dt) = sv {
2646                result = Some(*dt);
2647            }
2648        }
2649        match result {
2650            None => panic!("expected date/time value but got {:?}", self),
2651            Some(v) => v,
2652        }
2653    }
2654
2655    /// Expect a value to be a list and return it. Panic if it's not the expected type.
2656    pub fn as_list(&self) -> Vec<Value> {
2657        let mut result: Option<Vec<Value>> = None;
2658
2659        if let Value::List(lv) = self {
2660            result = Some(lv.clone());
2661        }
2662        match result {
2663            None => panic!("expected list value but got {:?}", self),
2664            Some(v) => v,
2665        }
2666    }
2667
2668    /// Expect a value to be a mapping and return it. Panic if it's not the expected type.
2669    pub fn as_mapping(&self) -> HashMap<String, Value> {
2670        let mut result: Option<HashMap<String, Value>> = None;
2671
2672        if let Value::Mapping(mv) = self {
2673            result = Some(mv.clone());
2674        }
2675        match result {
2676            None => panic!("expected mapping value but got {:?}", self),
2677            Some(v) => v,
2678        }
2679    }
2680
2681    /// Expect a value to be a sub-configuration and return it. Panic if it's not the expected type.
2682    pub fn as_config(&self) -> Config {
2683        let mut result: Option<Config> = None;
2684
2685        if let Value::Config(c) = self {
2686            result = Some(c.clone());
2687        }
2688        match result {
2689            None => panic!("expected config value but got {:?}", self),
2690            Some(v) => v,
2691        }
2692    }
2693}
2694
2695#[derive(Debug, Clone, PartialEq)]
2696pub(crate) enum InternalValue {
2697    Base(Value), // has been evaluated
2698    List(Vec<Rc<RefCell<InternalValue>>>),
2699    Mapping(HashMap<String, Rc<RefCell<InternalValue>>>),
2700    AST(ASTValue),
2701}
2702
2703impl InternalValue {
2704    /*
2705        fn is_float(&self) -> bool {
2706            match self {
2707                InternalValue::Base(cv) => match cv {
2708                    ConfigValue::Base(b) => match b {
2709                        ScalarValue::Float(_) => true,
2710                        _ => false,
2711                    },
2712                    _ => false,
2713                },
2714                _ => false,
2715            }
2716        }
2717
2718        fn is_complex(&self) -> bool {
2719            match self {
2720                InternalConfigValue::Base(cv) => match cv {
2721                    ConfigValue::Base(b) => match b {
2722                        ScalarValue::Complex(_) => true,
2723                        _ => false,
2724                    },
2725                    _ => false,
2726                },
2727                _ => false,
2728            }
2729        }
2730
2731        fn is_integer(&self) -> bool {
2732            match self {
2733                InternalConfigValue::Base(cv) => match cv {
2734                    ConfigValue::Base(b) => match b {
2735                        ScalarValue::Integer(_) => true,
2736                        _ => false,
2737                    },
2738                    _ => false,
2739                },
2740                _ => false,
2741            }
2742        }
2743
2744        fn is_bool(&self) -> bool {
2745            match self {
2746                InternalConfigValue::Base(cv) => match cv {
2747                    ConfigValue::Base(b) => match b {
2748                        ScalarValue::Bool(_) => true,
2749                        _ => false,
2750                    },
2751                    _ => false,
2752                },
2753                _ => false,
2754            }
2755        }
2756
2757        fn is_sequence(&self) -> bool {
2758            match self {
2759                InternalConfigValue::List(_) => true,
2760                InternalConfigValue::Base(cv) => match cv {
2761                    ConfigValue::List(_) => true,
2762                    _ => false,
2763                },
2764                _ => false,
2765            }
2766        }
2767
2768        fn is_mapping(&self) -> bool {
2769            match self {
2770                InternalConfigValue::Mapping(_) => true,
2771                InternalConfigValue::Base(cv) => match cv {
2772                    ConfigValue::Mapping(_) => true,
2773                    _ => false,
2774                },
2775                _ => false,
2776            }
2777        }
2778    */
2779
2780    fn make_int(i: i64) -> Self {
2781        InternalValue::Base(Value::Base(ScalarValue::Integer(i)))
2782    }
2783
2784    fn make_float(f: f64) -> Self {
2785        InternalValue::Base(Value::Base(ScalarValue::Float(f)))
2786    }
2787
2788    fn make_complex(c: Complex64) -> Self {
2789        InternalValue::Base(Value::Base(ScalarValue::Complex(c)))
2790    }
2791
2792    fn make_string(s: String) -> Self {
2793        InternalValue::Base(Value::Base(ScalarValue::String(s)))
2794    }
2795}
2796
2797/// This is the type of error returned from the high-level API for CFG configurations.
2798#[derive(Debug, PartialEq)]
2799pub enum ConfigError {
2800    /// This error is returned if the configuration text couldn't be parsed as
2801    /// valid CFG source. The underlying parser error is returned, which should
2802    /// contain location information.
2803    SyntaxError(RecognizerError),
2804    /// This error is returned if an attempt is made to query a configuration
2805    /// into which nothing has been loaded.
2806    NotLoaded,
2807    /// This error is returned if a file loaded as a top-level configuration is
2808    /// not a mapping or mapping body.
2809    MappingExpected,
2810    /// This error is returned if a string was expected, but not found. The
2811    /// location where it was expected is returned. This might be the location
2812    /// of an @ operator, whose operand must be a string be cause it represents
2813    /// the path to a file to be included as a sub-configuration.
2814    StringExpected(Location),
2815    /// This error is returned if a duplicate key is found when parsing a
2816    /// configuration. The key, the duplicate location and the original location
2817    /// are returned.
2818    DuplicateKey(String, Location, Location),
2819    /// This error is returned if a specified path is invalid (e.g. couldn't be
2820    /// canonocalized). The offending path is provided.
2821    BadFilePath(String),
2822    /// This error is returned if a file couldn't be found. The path that
2823    /// couldn't be found is provided.
2824    FileNotFound(String),
2825    /// This error is returned if a file couldn't be opened for reading. The
2826    /// path that couldn't be read is provided.
2827    FileReadFailed(String),
2828    /// This error is returned if an identifier is seen, but no lookup context
2829    /// has been provided.
2830    NoContext,
2831    /// This error is returned if an identifier is not a key in a specified
2832    /// lookup context.
2833    UnknownVariable(String, Location),
2834    /// This error is returned if a key is not present in a configuration or
2835    /// path therein. If the absence is in a path, the location within that
2836    /// path is returned, along with the missing key.
2837    NotPresent(String, Option<Location>),
2838    /// This error is returned if a string couldn't be parsed as a valid path.
2839    /// The underlying parser error is returned, which will include location
2840    /// information.
2841    InvalidPath(RecognizerError),
2842    /// This error is returned if a path operand isn't valid for the current
2843    /// container (e.g. string index for a list, or numeric index for a mapping).
2844    /// The source location where the error occurred are returned.
2845    InvalidPathOperand(Location),
2846    /// This error is returned if an index value is out of range. The bad index
2847    /// value and the source location where it was found are returned.
2848    IndexOutOfRange(i64, Location),
2849    /// This error is returned if an evaluation failed. A source location near
2850    /// to where the failure occurred is returned.
2851    EvaluationFailed(Location),
2852    /// This error is returned if a special string (back-tick string) couldn't
2853    /// be converted. The special string which couldn't be handled is returned.
2854    ConversionError(String),
2855    /// This error is returned if a reference cycle is detected. A list of the
2856    /// reference paths in the cycle, together with their locations, is returned.
2857    CircularReferenceError(Vec<(String, Location)>),
2858}
2859
2860#[derive(Debug, PartialEq)]
2861pub(crate) enum PathElement<'a> {
2862    Attribute(&'a Token),
2863    IndexedAccess(&'a ASTValue),
2864    SliceAccess(&'a ASTValue),
2865}
2866
2867/// Represents a CFG configuration.
2868///
2869#[derive(Debug, Clone, PartialEq)]
2870pub struct Config {
2871    /// If `true`, loaded configurations aren't allowed to have duplicate keys.
2872    /// If `false`, duplicate keys are allowed, and values encountered later
2873    /// overwrite values encountered earlier for the same key.
2874    pub no_duplicates: bool,
2875    //    pub strict_conversions: bool,
2876    root_dir: String,
2877    path: String,
2878    include_path: Vec<String>,
2879    string_converter: StringConverter,
2880    context: Option<HashMap<String, Value>>,
2881    data: Rc<RefCell<InternalValue>>,
2882    refs_seen: RefCell<HashSet<(String, Location)>>,
2883}
2884
2885impl fmt::Display for Config {
2886    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2887        let fname = Path::new(&self.path)
2888            .file_name()
2889            .expect("couldn't get file name")
2890            .to_str()
2891            .expect("couldn't convert file name to Unicode");
2892        let num_items = match &*self.data.borrow() {
2893            InternalValue::Mapping(hm) => hm.len(),
2894            _ => panic!("Unexpected type for data"),
2895        };
2896        write!(f, "Config(").unwrap();
2897        write!(f, "{}, {} items", fname, num_items).unwrap();
2898        write!(f, ")")
2899    }
2900}
2901
2902fn make_node(v: InternalValue) -> Rc<RefCell<InternalValue>> {
2903    Rc::new(RefCell::new(v))
2904}
2905
2906fn default_string_converter(s: &str, cfg: &Config) -> Option<Value> {
2907    let mut result = None;
2908
2909    fn get_i32(caps: &Captures, i: usize) -> i32 {
2910        caps.get(i).unwrap().as_str().parse::<i32>().unwrap()
2911    }
2912
2913    fn get_u32(caps: &Captures, i: usize) -> u32 {
2914        caps.get(i).unwrap().as_str().parse::<u32>().unwrap()
2915    }
2916
2917    /*
2918        fn get_str<'a>(caps: &'a Captures, i: usize) -> &'a str {
2919            caps.get(i).unwrap().as_str()
2920        }
2921    */
2922
2923    match ISO_DATETIME_PATTERN.captures(s) {
2924        Some(groups) => {
2925            let y = get_i32(&groups, 1);
2926            let m = get_u32(&groups, 2);
2927            let d = get_u32(&groups, 3);
2928            let has_time = groups.get(5).is_some();
2929            let nd = NaiveDate::from_ymd(y, m, d);
2930
2931            if !has_time {
2932                result = Some(Value::from(nd));
2933            } else {
2934                let h = get_u32(&groups, 8);
2935                let m = get_u32(&groups, 9);
2936                let s = get_u32(&groups, 10);
2937                let has_offset = groups.get(13).is_some();
2938                let nanos = match groups.get(11) {
2939                    None => 0,
2940                    Some(v) => (v.as_str().parse::<f64>().unwrap() * 1.0e9) as u32,
2941                };
2942                let time = NaiveTime::from_hms_nano(h, m, s, nanos);
2943                let datetime = NaiveDateTime::new(nd, time);
2944
2945                let offsecs = if !has_offset {
2946                    0
2947                } else {
2948                    let sign = if groups.get(13).unwrap().as_str() == "-" {
2949                        -1
2950                    } else {
2951                        1
2952                    };
2953                    let oh = get_i32(&groups, 14);
2954                    let om = get_i32(&groups, 15);
2955                    let os = match groups.get(17) {
2956                        None => 0,
2957                        Some(v) => v.as_str().parse::<i32>().unwrap(),
2958                    };
2959                    sign * (os + om * 60 + oh * 3600)
2960                };
2961                let offset = FixedOffset::east(offsecs);
2962                let dt = DateTime::<FixedOffset>::from_utc(datetime, offset);
2963                result = Some(Value::from(dt));
2964            }
2965        }
2966        None => match ENV_VALUE_PATTERN.captures(s) {
2967            Some(groups) => {
2968                let name = groups.get(1).unwrap().as_str();
2969
2970                match env::var(name) {
2971                    Err(_) => {
2972                        let has_pipe = groups.get(2).is_some();
2973
2974                        if !has_pipe {
2975                            result = Some(Value::Base(ScalarValue::None));
2976                        } else {
2977                            let s = groups.get(3).unwrap().as_str();
2978
2979                            result = Some(Value::from(s))
2980                        }
2981                    }
2982                    Ok(v) => result = Some(Value::from(v)),
2983                }
2984            }
2985            None => match INTERPOLATION_PATTERN.captures(s) {
2986                None => {}
2987                Some(_) => {
2988                    let mut failed = false;
2989                    let mut cp = 0;
2990                    let mut parts = vec![];
2991
2992                    for m in INTERPOLATION_PATTERN.find_iter(s) {
2993                        let sp = m.start();
2994                        let ep = m.end();
2995                        let path = &s[sp + 2..ep - 1];
2996
2997                        if cp < sp {
2998                            parts.push(s[cp..sp].to_string());
2999                        }
3000                        match cfg.get(path) {
3001                            Err(_) => {
3002                                failed = true;
3003                                break;
3004                            }
3005                            Ok(v) => {
3006                                parts.push(format!("{}", v));
3007                            }
3008                        }
3009                        cp = ep;
3010                    }
3011                    if !failed {
3012                        if cp < s.len() {
3013                            parts.push(s[cp..s.len()].to_string());
3014                        }
3015                        let rv = parts.join("");
3016                        result = Some(Value::from(rv.as_str()));
3017                    }
3018                }
3019            },
3020        },
3021    }
3022    result
3023}
3024
3025fn find_in_path(fname: &str, path: &[String]) -> Option<String> {
3026    for entry in path {
3027        let mut p = PathBuf::new();
3028
3029        p.push(entry);
3030        p.push(fname);
3031
3032        let path = p.as_path();
3033        if path.exists() {
3034            match path.to_str() {
3035                None => return None,
3036                Some(s) => return Some(s.to_string()),
3037            }
3038        }
3039    }
3040    None
3041}
3042
3043pub(crate) fn parse_path(s: &str) -> StdResult<ASTValue, RecognizerError> {
3044    let c = Cursor::new(s);
3045
3046    match Parser::new(Box::new(c)) {
3047        Err(e) => Err(e),
3048        Ok(mut parser) => {
3049            if parser.next_token.kind != TokenKind::Word {
3050                return Err(RecognizerError::UnexpectedToken(
3051                    token_text(TokenKind::Word),
3052                    token_text(parser.next_token.kind),
3053                    parser.next_token.start,
3054                ));
3055            }
3056            match parser.primary() {
3057                Ok(av) => {
3058                    if !parser.at_end() {
3059                        Err(RecognizerError::TrailingText(parser.next_token.start))
3060                    } else {
3061                        Ok(av)
3062                    }
3063                }
3064                Err(e) => Err(e),
3065            }
3066        }
3067    }
3068}
3069
3070// since Rust doesn't implement generator functions, we just unpack a path into a sequence
3071// using this function.
3072pub(crate) fn unpack_path<'a>(node: &'a ASTValue) -> Vec<PathElement<'a>> {
3073    let mut path = vec![];
3074
3075    fn visit<'a>(path: &mut Vec<PathElement<'a>>, node: &'a ASTValue) {
3076        match node {
3077            ASTValue::TokenValue(t) => path.push(PathElement::Attribute(&t)),
3078            ASTValue::Unary(un) => visit(path, &un.operand),
3079            ASTValue::Binary(bn) => {
3080                visit(path, &bn.left);
3081                match bn.kind {
3082                    TokenKind::Dot => match &*bn.right {
3083                        ASTValue::TokenValue(t) => path.push(PathElement::Attribute(&t)),
3084                        _ => panic!("unexpected node with attribute access: {:?}", bn.right),
3085                    },
3086                    TokenKind::LeftBracket => path.push(PathElement::IndexedAccess(&bn.right)),
3087                    TokenKind::Colon => path.push(PathElement::SliceAccess(&bn.right)),
3088                    _ => panic!("unpack_path not implemented for {:?}", bn),
3089                }
3090            }
3091            _ => panic!("unpack_path not implemented for {:?}", node),
3092        }
3093    }
3094
3095    visit(&mut path, node);
3096    path
3097}
3098
3099pub(crate) fn to_source(node: &ASTValue) -> String {
3100    let path = unpack_path(node);
3101    let mut parts = vec![];
3102
3103    for (i, element) in path.iter().enumerate() {
3104        match element {
3105            PathElement::Attribute(t) => {
3106                if i > 0 {
3107                    parts.push(".".to_string());
3108                }
3109                parts.push(t.text.clone());
3110            }
3111            PathElement::IndexedAccess(index) => {
3112                parts.push("[".to_string());
3113                parts.push(to_source(index));
3114                parts.push("]".to_string());
3115            }
3116            PathElement::SliceAccess(slice) => {
3117                parts.push("[".to_string());
3118                match slice {
3119                    ASTValue::Slice(_, start, stop, step) => {
3120                        if let Some(v) = &**start {
3121                            parts.push(to_source(v));
3122                        }
3123                        parts.push(":".to_string());
3124                        if let Some(v) = &**stop {
3125                            parts.push(to_source(v));
3126                        }
3127                        if let Some(v) = &**step {
3128                            parts.push(":".to_string());
3129                            parts.push(to_source(v));
3130                        }
3131                    }
3132                    _ => panic!("unexpected in slice element: {:?}", slice),
3133                }
3134                parts.push("]".to_string());
3135            }
3136        }
3137    }
3138    parts.join("")
3139}
3140
3141impl Default for Config {
3142    fn default() -> Self {
3143        Self::new()
3144    }
3145}
3146
3147impl Config {
3148    /// Return an empty configuration with default settings.
3149    pub fn new() -> Self {
3150        Self {
3151            no_duplicates: true,
3152            //            strict_conversions: true,
3153            root_dir: "".to_string(),
3154            path: "".to_string(),
3155            include_path: vec![],
3156            string_converter: StringConverter(default_string_converter),
3157            context: None,
3158            data: make_node(InternalValue::Mapping(HashMap::new())),
3159            refs_seen: RefCell::new(HashSet::new()),
3160        }
3161    }
3162
3163    /// Return a new configuration loaded from the file named by `file_path`.
3164    pub fn from_file(file_path: &str) -> StdResult<Self, ConfigError> {
3165        let mut result = Config::new();
3166
3167        match result.load_from_file(file_path) {
3168            Ok(()) => Ok(result),
3169            Err(e) => Err(e),
3170        }
3171    }
3172
3173    /// Add the directory `dir` to the end of the include path.
3174    pub fn add_include(&mut self, dir: &str) {
3175        self.include_path.push(dir.to_string());
3176    }
3177
3178    fn try_open_file(&self, path: &str) -> StdResult<File, ConfigError> {
3179        match File::open(path) {
3180            Err(e) => {
3181                warn!("File read failed for {}: {:?}", path, e);
3182                Err(ConfigError::FileReadFailed(path.to_string()))
3183            }
3184            Ok(f) => Ok(f),
3185        }
3186    }
3187
3188    fn set_path(&mut self, file_path: &str) -> bool {
3189        let p = PathBuf::from(file_path);
3190        let mut failed = false;
3191
3192        match canonicalize(&p) {
3193            Ok(cp) => match cp.to_str() {
3194                Some(s) => {
3195                    self.path = s.to_string();
3196                    match cp.parent() {
3197                        Some(pp) => match pp.to_str() {
3198                            None => failed = true,
3199                            Some(s) => self.root_dir = s.to_string(),
3200                        },
3201                        None => failed = true,
3202                    }
3203                }
3204                None => {
3205                    warn!("failed to convert {:?} to str", cp);
3206                    failed = true
3207                }
3208            },
3209            Err(_) => {
3210                warn!("failed to canonicalize {:?}", p);
3211                failed = true
3212            }
3213        };
3214        failed
3215    }
3216
3217    /// Load the configuration from the file named by `file_path`.
3218    pub fn load_from_file(&mut self, file_path: &str) -> StdResult<(), ConfigError> {
3219        match self.try_open_file(file_path) {
3220            Err(e) => Err(e),
3221            Ok(f) => match self.load(Box::new(f)) {
3222                Err(e) => Err(e),
3223                Ok(()) => {
3224                    if self.set_path(file_path) {
3225                        Err(ConfigError::BadFilePath(file_path.to_string()))
3226                    } else {
3227                        Ok(())
3228                    }
3229                }
3230            },
3231        }
3232    }
3233
3234    fn wrap_mapping(
3235        &self,
3236        items: &[(Token, ASTValue)],
3237    ) -> StdResult<HashMap<String, Rc<RefCell<InternalValue>>>, ConfigError> {
3238        // only allocate map when needed
3239        let mut maybe_seen: Option<HashMap<String, Location>> = if self.no_duplicates {
3240            Some(HashMap::new())
3241        } else {
3242            None
3243        };
3244        let mut result: HashMap<String, Rc<RefCell<InternalValue>>> = HashMap::new();
3245
3246        for (t, v) in items.iter() {
3247            let key: &str;
3248
3249            match &t.value {
3250                ScalarValue::Identifier(iv) => {
3251                    key = &iv;
3252                }
3253                ScalarValue::String(sv) => {
3254                    key = &sv;
3255                }
3256                _ => panic!("non-string key encountered"),
3257            }
3258            match maybe_seen {
3259                None => {
3260                    result.insert(key.to_string(), make_node(InternalValue::AST(v.clone())));
3261                }
3262                Some(ref mut seen) => match seen.get(key) {
3263                    Some(orig_loc) => {
3264                        return Err(ConfigError::DuplicateKey(
3265                            key.to_string(),
3266                            t.start,
3267                            *orig_loc,
3268                        ));
3269                    }
3270                    None => {
3271                        seen.insert(key.to_string(), t.start.clone());
3272                        result.insert(key.to_string(), make_node(InternalValue::AST(v.clone())));
3273                    }
3274                },
3275            }
3276        }
3277        Ok(result)
3278    }
3279
3280    fn wrap_sequence(&self, items: &[ASTValue]) -> Vec<Rc<RefCell<InternalValue>>> {
3281        let mut result = vec![];
3282
3283        for item in items.iter() {
3284            result.push(make_node(InternalValue::AST(item.clone())));
3285        }
3286        result
3287    }
3288
3289    /// Load the configuration from the reader `r`.
3290    pub fn load(&mut self, r: Box<dyn Read>) -> StdResult<(), ConfigError> {
3291        let mut parser = Parser::new(r).expect("unable to create parser");
3292
3293        match parser.container() {
3294            Err(e) => Err(ConfigError::SyntaxError(e)),
3295            Ok(node) => {
3296                // It must be a mapping, as we're at the root level
3297                match node {
3298                    ASTValue::Mapping(items) => match self.wrap_mapping(&items) {
3299                        Err(e) => Err(e),
3300                        Ok(data) => {
3301                            self.data = make_node(InternalValue::Mapping(data));
3302                            Ok(())
3303                        }
3304                    },
3305                    _ => Err(ConfigError::MappingExpected),
3306                }
3307            }
3308        }
3309    }
3310
3311    /// Set the given hashmap `context` as the place to look up identifiers
3312    /// encountered in the configuration.
3313    pub fn set_context(&mut self, context: HashMap<String, Value>) {
3314        self.context = Some(context)
3315    }
3316
3317    fn eval_at(&self, node: &ASTValue, loc: Location) -> StdResult<InternalValue, ConfigError> {
3318        match self.evaluate(node) {
3319            Err(e) => Err(e),
3320            Ok(v) => match v {
3321                InternalValue::Base(cv) => match cv {
3322                    Value::Base(tv) => match tv {
3323                        ScalarValue::String(mut fname) => {
3324                            let mut dirs = vec![];
3325                            let p = Path::new(&fname);
3326
3327                            if p.is_absolute() {
3328                                dirs.push(p.parent().unwrap().to_str().unwrap().to_string());
3329                                fname = p.file_name().unwrap().to_str().unwrap().to_string();
3330                            } else {
3331                                dirs.push(self.root_dir.clone());
3332                                dirs.extend_from_slice(&self.include_path);
3333                            }
3334
3335                            match find_in_path(&fname, &dirs) {
3336                                None => Err(ConfigError::FileNotFound(fname.to_string())),
3337                                Some(p) => {
3338                                    match self.try_open_file(&p) {
3339                                        Err(e) => Err(e),
3340                                        Ok(f) => {
3341                                            let mut parser = Parser::new(Box::new(f))
3342                                                .expect("unable to create parser");
3343
3344                                            match parser.container() {
3345                                                Err(e) => Err(ConfigError::SyntaxError(e)),
3346                                                Ok(node) => match node {
3347                                                    ASTValue::Mapping(items) => match self
3348                                                        .wrap_mapping(&items)
3349                                                    {
3350                                                        Err(e) => Err(e),
3351                                                        Ok(data) => {
3352                                                            // make a new config with the appropriate data
3353                                                            let data = make_node(
3354                                                                InternalValue::Mapping(data),
3355                                                            );
3356                                                            let mut cfg = Config::new();
3357
3358                                                            cfg.no_duplicates = self.no_duplicates;
3359                                                            cfg.context = self.context.clone();
3360                                                            cfg.include_path =
3361                                                                self.include_path.clone();
3362                                                            cfg.set_path(&p);
3363                                                            cfg.data = data;
3364                                                            Ok(InternalValue::Base(Value::Config(
3365                                                                cfg,
3366                                                            )))
3367                                                        }
3368                                                    },
3369                                                    ASTValue::List(items) => {
3370                                                        let mut result = vec![];
3371
3372                                                        for item in items {
3373                                                            result.push(make_node(
3374                                                                InternalValue::AST(item.clone()),
3375                                                            ));
3376                                                        }
3377                                                        Ok(InternalValue::List(result))
3378                                                    }
3379                                                    _ => {
3380                                                        todo!("included data is neither mapping nor list");
3381                                                    }
3382                                                },
3383                                            }
3384                                        }
3385                                    }
3386                                    //                                    match Config::from_file(&p) {
3387                                    //                                        Err(e) => Err(e),
3388                                    //                                        Ok(cfg) => {
3389                                    //                                            Ok(InternalConfigValue::Base(ConfigValue::Config(cfg)))
3390                                    //                                        }
3391                                    //                                    }
3392                                }
3393                            }
3394                        }
3395                        _ => Err(ConfigError::StringExpected(loc)),
3396                    },
3397                    _ => Err(ConfigError::StringExpected(loc)),
3398                },
3399                _ => todo!("unhandled internal config value"),
3400            },
3401        }
3402    }
3403
3404    fn eval_reference(&self, node: &ASTValue) -> StdResult<InternalValue, ConfigError> {
3405        self.get_from_path(node)
3406    }
3407
3408    fn eval_negation(
3409        &self,
3410        node: &ASTValue,
3411        loc: Location,
3412    ) -> StdResult<InternalValue, ConfigError> {
3413        match self.evaluate(node) {
3414            Err(e) => Err(e),
3415            Ok(v) => match &v {
3416                InternalValue::Base(cv) => match cv {
3417                    Value::Base(tv) => match tv {
3418                        ScalarValue::Integer(i) => Ok(InternalValue::make_int(-i)),
3419                        ScalarValue::Float(f) => Ok(InternalValue::make_float(-f)),
3420                        ScalarValue::Complex(c) => Ok(InternalValue::make_complex(-c)),
3421                        _ => {
3422                            warn!("cannot negate {:?}", v);
3423                            Err(ConfigError::EvaluationFailed(loc))
3424                        }
3425                    },
3426                    _ => {
3427                        warn!("cannot negate {:?}", v);
3428                        Err(ConfigError::EvaluationFailed(loc))
3429                    }
3430                },
3431                _ => {
3432                    warn!("cannot negate {:?}", v);
3433                    Err(ConfigError::EvaluationFailed(loc))
3434                }
3435            },
3436        }
3437    }
3438
3439    fn eval_unary(&self, node: &UnaryNode) -> StdResult<InternalValue, ConfigError> {
3440        match node.kind {
3441            TokenKind::At => self.eval_at(&node.operand, node.start),
3442            TokenKind::Dollar => self.eval_reference(&node.operand),
3443            TokenKind::Minus => self.eval_negation(&node.operand, node.start),
3444            _ => todo!("unhandled unary kind: {:?}", node.kind),
3445        }
3446    }
3447
3448    fn get_operands(
3449        &self,
3450        node: &BinaryNode,
3451    ) -> StdResult<(InternalValue, InternalValue), ConfigError> {
3452        let lhs = self.evaluate(&node.left)?;
3453        let rhs = self.evaluate(&node.right)?;
3454        Ok((lhs, rhs))
3455    }
3456
3457    fn merge_dicts(
3458        &self,
3459        left: &HashMap<String, Rc<RefCell<InternalValue>>>,
3460        right: &HashMap<String, Rc<RefCell<InternalValue>>>,
3461    ) -> StdResult<HashMap<String, Rc<RefCell<InternalValue>>>, ConfigError> {
3462        let mut result = left.clone();
3463
3464        for (k, v) in right.iter() {
3465            let key = k.clone();
3466
3467            match result.get(k) {
3468                None => {
3469                    // it's not in the target, so copy it over
3470                    result.insert(key, v.clone());
3471                }
3472                Some(ov) => {
3473                    // it's in the target with value ov. If ov and v are both mappings, merge them
3474                    // else overwrite target (left) with source (right). Either might be ASTs, and
3475                    // if so they need evaluating
3476                    let target: InternalValue;
3477
3478                    if let InternalValue::AST(node) = &*ov.borrow() {
3479                        target = self.evaluate(&node)?;
3480                    } else {
3481                        target = ov.borrow().clone();
3482                    }
3483                    if let InternalValue::Mapping(ref tm) = target {
3484                        let source: InternalValue;
3485
3486                        if let InternalValue::AST(node) = &*v.borrow() {
3487                            source = self.evaluate(&node)?;
3488                        } else {
3489                            source = ov.borrow().clone();
3490                        }
3491                        if let InternalValue::Mapping(ref sm) = source {
3492                            let merged = self.merge_dicts(tm, sm)?;
3493
3494                            result.insert(key, make_node(InternalValue::Mapping(merged)));
3495                        } else {
3496                            result.insert(key, v.clone());
3497                        }
3498                    } else {
3499                        result.insert(key, v.clone());
3500                    }
3501                }
3502            }
3503        }
3504        Ok(result)
3505    }
3506
3507    fn eval_add(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
3508        match self.get_operands(node) {
3509            Err(e) => Err(e),
3510            Ok((lhs, rhs)) => match &lhs {
3511                InternalValue::Base(cvlhs) => match &rhs {
3512                    InternalValue::Base(cvrhs) => match &cvlhs {
3513                        Value::Base(svlhs) => match &cvrhs {
3514                            Value::Base(svrhs) => match &svlhs {
3515                                ScalarValue::Integer(ilhs) => match &svrhs {
3516                                    ScalarValue::Integer(irhs) => {
3517                                        Ok(InternalValue::make_int(ilhs + irhs))
3518                                    }
3519                                    ScalarValue::Float(frhs) => {
3520                                        Ok(InternalValue::make_float(*ilhs as f64 + frhs))
3521                                    }
3522                                    ScalarValue::Complex(crhs) => {
3523                                        let clhs = Complex64::new(*ilhs as f64, 0.0);
3524
3525                                        Ok(InternalValue::make_complex(clhs + crhs))
3526                                    }
3527                                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3528                                },
3529                                ScalarValue::Float(flhs) => match &svrhs {
3530                                    ScalarValue::Integer(irhs) => {
3531                                        Ok(InternalValue::make_float(flhs + *irhs as f64))
3532                                    }
3533                                    ScalarValue::Float(frhs) => {
3534                                        Ok(InternalValue::make_float(flhs + frhs))
3535                                    }
3536                                    ScalarValue::Complex(crhs) => {
3537                                        let clhs = Complex64::new(*flhs, 0.0);
3538
3539                                        Ok(InternalValue::make_complex(clhs + crhs))
3540                                    }
3541                                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3542                                },
3543                                ScalarValue::Complex(clhs) => match &svrhs {
3544                                    ScalarValue::Integer(irhs) => {
3545                                        let crhs = Complex64::new(*irhs as f64, 0.0);
3546
3547                                        Ok(InternalValue::make_complex(clhs + crhs))
3548                                    }
3549                                    ScalarValue::Float(frhs) => {
3550                                        let crhs = Complex64::new(*frhs, 0.0);
3551
3552                                        Ok(InternalValue::make_complex(clhs + crhs))
3553                                    }
3554                                    ScalarValue::Complex(crhs) => {
3555                                        Ok(InternalValue::make_complex(clhs + crhs))
3556                                    }
3557                                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3558                                },
3559                                ScalarValue::String(slhs) => match &svrhs {
3560                                    ScalarValue::String(srhs) => {
3561                                        let mut r = String::new();
3562
3563                                        r.push_str(slhs);
3564                                        r.push_str(srhs);
3565                                        Ok(InternalValue::make_string(r))
3566                                    }
3567                                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3568                                },
3569                                _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3570                            },
3571                            _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3572                        },
3573                        Value::List(seqlhs) => match &cvrhs {
3574                            Value::List(seqrhs) => {
3575                                let mut result = seqlhs.clone();
3576
3577                                result.extend(seqrhs.iter().cloned());
3578                                Ok(InternalValue::Base(Value::List(result)))
3579                            }
3580                            _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3581                        },
3582                        _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3583                    },
3584                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3585                },
3586                InternalValue::List(llhs) => match &rhs {
3587                    InternalValue::List(lrhs) => {
3588                        let mut result = llhs.clone();
3589
3590                        result.extend(lrhs.iter().cloned());
3591                        Ok(InternalValue::List(result))
3592                    }
3593                    InternalValue::Base(b) => match b {
3594                        Value::List(seq) => match self.base_unwrap_list(llhs, false) {
3595                            Err(e) => Err(e),
3596                            Ok(mut result) => {
3597                                result.extend(seq.iter().cloned());
3598                                Ok(InternalValue::Base(Value::List(result)))
3599                            }
3600                        },
3601                        _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3602                    },
3603                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3604                },
3605                InternalValue::Mapping(mlhs) => match &rhs {
3606                    InternalValue::Mapping(mrhs) => match self.merge_dicts(mlhs, mrhs) {
3607                        Err(e) => Err(e),
3608                        Ok(v) => Ok(InternalValue::Mapping(v)),
3609                    },
3610                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3611                },
3612                _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3613            },
3614        }
3615    }
3616
3617    fn eval_subtract(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
3618        match self.get_operands(node) {
3619            Err(e) => Err(e),
3620            Ok((lhs, rhs)) => match &lhs {
3621                InternalValue::Base(cvlhs) => match &rhs {
3622                    InternalValue::Base(cvrhs) => match &cvlhs {
3623                        Value::Base(svlhs) => match &cvrhs {
3624                            Value::Base(svrhs) => match &svlhs {
3625                                ScalarValue::Integer(ilhs) => match &svrhs {
3626                                    ScalarValue::Integer(irhs) => {
3627                                        Ok(InternalValue::make_int(ilhs - irhs))
3628                                    }
3629                                    ScalarValue::Float(frhs) => {
3630                                        Ok(InternalValue::make_float(*ilhs as f64 - frhs))
3631                                    }
3632                                    ScalarValue::Complex(crhs) => {
3633                                        let clhs = Complex64::new(*ilhs as f64, 0.0);
3634
3635                                        Ok(InternalValue::make_complex(clhs - crhs))
3636                                    }
3637                                    _ => todo!("cannot subtract {:?} from {:?}", rhs, lhs),
3638                                },
3639                                ScalarValue::Float(flhs) => match &svrhs {
3640                                    ScalarValue::Integer(irhs) => {
3641                                        Ok(InternalValue::make_float(flhs - *irhs as f64))
3642                                    }
3643                                    ScalarValue::Float(frhs) => {
3644                                        Ok(InternalValue::make_float(flhs - frhs))
3645                                    }
3646                                    ScalarValue::Complex(crhs) => {
3647                                        let clhs = Complex64::new(*flhs, 0.0);
3648
3649                                        Ok(InternalValue::make_complex(clhs - crhs))
3650                                    }
3651                                    _ => todo!("cannot subtract {:?} from {:?}", rhs, lhs),
3652                                },
3653                                ScalarValue::Complex(clhs) => match &svrhs {
3654                                    ScalarValue::Integer(irhs) => {
3655                                        let crhs = Complex64::new(*irhs as f64, 0.0);
3656
3657                                        Ok(InternalValue::make_complex(clhs - crhs))
3658                                    }
3659                                    ScalarValue::Float(frhs) => {
3660                                        let crhs = Complex64::new(*frhs, 0.0);
3661
3662                                        Ok(InternalValue::make_complex(clhs - crhs))
3663                                    }
3664                                    ScalarValue::Complex(crhs) => {
3665                                        Ok(InternalValue::make_complex(clhs - crhs))
3666                                    }
3667                                    _ => todo!("cannot subtract {:?} from {:?}", rhs, lhs),
3668                                },
3669                                _ => todo!("cannot subtract {:?} from {:?}", rhs, lhs),
3670                            },
3671                            _ => todo!("cannot subtract {:?} from {:?}", rhs, lhs),
3672                        },
3673                        _ => todo!("cannot subtract {:?} from {:?}", rhs, lhs),
3674                    },
3675                    _ => todo!("cannot subtract {:?} from {:?}", rhs, lhs),
3676                },
3677                InternalValue::Mapping(mlhs) => match &rhs {
3678                    InternalValue::Mapping(mrhs) => {
3679                        let mut result = mlhs.clone();
3680
3681                        for (k, _) in mrhs.iter() {
3682                            match result.get(k) {
3683                                None => {}
3684                                Some(_) => {
3685                                    result.remove(k);
3686                                }
3687                            }
3688                        }
3689
3690                        Ok(InternalValue::Mapping(result))
3691                    }
3692                    _ => todo!("cannot subtract {:?} from {:?}", rhs, lhs),
3693                },
3694                _ => todo!("cannot subtract {:?} from {:?}", rhs, lhs),
3695            },
3696        }
3697    }
3698
3699    fn eval_multiply(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
3700        match self.get_operands(node) {
3701            Err(e) => Err(e),
3702            Ok((lhs, rhs)) => match &lhs {
3703                InternalValue::Base(cvlhs) => match &rhs {
3704                    InternalValue::Base(cvrhs) => match &cvlhs {
3705                        Value::Base(svlhs) => match &cvrhs {
3706                            Value::Base(svrhs) => match &svlhs {
3707                                ScalarValue::Integer(ilhs) => match &svrhs {
3708                                    ScalarValue::Integer(irhs) => {
3709                                        Ok(InternalValue::make_int(ilhs * irhs))
3710                                    }
3711                                    ScalarValue::Float(frhs) => {
3712                                        Ok(InternalValue::make_float(*ilhs as f64 * frhs))
3713                                    }
3714                                    ScalarValue::Complex(crhs) => {
3715                                        let clhs = Complex64::new(*ilhs as f64, 0.0);
3716
3717                                        Ok(InternalValue::make_complex(clhs * crhs))
3718                                    }
3719                                    _ => todo!("cannot multiply {:?} by {:?}", lhs, rhs),
3720                                },
3721                                ScalarValue::Float(flhs) => match &svrhs {
3722                                    ScalarValue::Integer(irhs) => {
3723                                        Ok(InternalValue::make_float(flhs * *irhs as f64))
3724                                    }
3725                                    ScalarValue::Float(frhs) => {
3726                                        Ok(InternalValue::make_float(flhs * frhs))
3727                                    }
3728                                    ScalarValue::Complex(crhs) => {
3729                                        let clhs = Complex64::new(*flhs, 0.0);
3730
3731                                        Ok(InternalValue::make_complex(clhs * crhs))
3732                                    }
3733                                    _ => todo!("cannot multiply {:?} by {:?}", lhs, rhs),
3734                                },
3735                                ScalarValue::Complex(clhs) => match &svrhs {
3736                                    ScalarValue::Integer(irhs) => {
3737                                        let crhs = Complex64::new(*irhs as f64, 0.0);
3738
3739                                        Ok(InternalValue::make_complex(clhs * crhs))
3740                                    }
3741                                    ScalarValue::Float(frhs) => {
3742                                        let crhs = Complex64::new(*frhs, 0.0);
3743
3744                                        Ok(InternalValue::make_complex(clhs * crhs))
3745                                    }
3746                                    ScalarValue::Complex(crhs) => {
3747                                        Ok(InternalValue::make_complex(clhs * crhs))
3748                                    }
3749                                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3750                                },
3751                                _ => todo!("cannot multiply {:?} by {:?}", lhs, rhs),
3752                            },
3753                            _ => todo!("cannot multiply {:?} by {:?}", lhs, rhs),
3754                        },
3755                        _ => todo!("cannot multiply {:?} by {:?}", lhs, rhs),
3756                    },
3757                    _ => todo!("cannot multiply {:?} by {:?}", lhs, rhs),
3758                },
3759                _ => todo!("cannot multiply {:?} by {:?}", lhs, rhs),
3760            },
3761        }
3762    }
3763
3764    fn eval_divide(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
3765        match self.get_operands(node) {
3766            Err(e) => Err(e),
3767            Ok((lhs, rhs)) => match &lhs {
3768                InternalValue::Base(cvlhs) => match &rhs {
3769                    InternalValue::Base(cvrhs) => match &cvlhs {
3770                        Value::Base(svlhs) => match &cvrhs {
3771                            Value::Base(svrhs) => match &svlhs {
3772                                ScalarValue::Integer(ilhs) => match &svrhs {
3773                                    ScalarValue::Integer(irhs) => Ok(InternalValue::make_float(
3774                                        (*ilhs as f64) / (*irhs as f64),
3775                                    )),
3776                                    ScalarValue::Float(frhs) => {
3777                                        Ok(InternalValue::make_float(*ilhs as f64 * frhs))
3778                                    }
3779                                    ScalarValue::Complex(crhs) => {
3780                                        let clhs = Complex64::new(*ilhs as f64, 0.0);
3781
3782                                        Ok(InternalValue::make_complex(clhs / crhs))
3783                                    }
3784                                    _ => todo!("cannot divide {:?} by {:?}", lhs, rhs),
3785                                },
3786                                ScalarValue::Float(flhs) => match &svrhs {
3787                                    ScalarValue::Integer(irhs) => {
3788                                        Ok(InternalValue::make_float(flhs - *irhs as f64))
3789                                    }
3790                                    ScalarValue::Float(frhs) => {
3791                                        Ok(InternalValue::make_float(flhs / frhs))
3792                                    }
3793                                    ScalarValue::Complex(crhs) => {
3794                                        let clhs = Complex64::new(*flhs, 0.0);
3795
3796                                        Ok(InternalValue::make_complex(clhs / crhs))
3797                                    }
3798                                    _ => todo!("cannot divide {:?} by {:?}", lhs, rhs),
3799                                },
3800                                ScalarValue::Complex(clhs) => match &svrhs {
3801                                    ScalarValue::Integer(irhs) => {
3802                                        let crhs = Complex64::new(*irhs as f64, 0.0);
3803
3804                                        Ok(InternalValue::make_complex(clhs / crhs))
3805                                    }
3806                                    ScalarValue::Float(frhs) => {
3807                                        let crhs = Complex64::new(*frhs, 0.0);
3808
3809                                        Ok(InternalValue::make_complex(clhs / crhs))
3810                                    }
3811                                    ScalarValue::Complex(crhs) => {
3812                                        Ok(InternalValue::make_complex(clhs / crhs))
3813                                    }
3814                                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3815                                },
3816                                _ => todo!("cannot divide {:?} by {:?}", lhs, rhs),
3817                            },
3818                            _ => todo!("cannot divide {:?} by {:?}", lhs, rhs),
3819                        },
3820                        _ => todo!("cannot divide {:?} by {:?}", lhs, rhs),
3821                    },
3822                    _ => todo!("cannot divide {:?} by {:?}", lhs, rhs),
3823                },
3824                _ => todo!("cannot divide {:?} by {:?}", lhs, rhs),
3825            },
3826        }
3827    }
3828
3829    fn eval_integer_divide(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
3830        match self.get_operands(node) {
3831            Err(e) => Err(e),
3832            Ok((lhs, rhs)) => match &lhs {
3833                InternalValue::Base(cvlhs) => match &rhs {
3834                    InternalValue::Base(cvrhs) => match &cvlhs {
3835                        Value::Base(svlhs) => match &cvrhs {
3836                            Value::Base(svrhs) => match &svlhs {
3837                                ScalarValue::Integer(ilhs) => match &svrhs {
3838                                    ScalarValue::Integer(irhs) => {
3839                                        Ok(InternalValue::make_int(ilhs / irhs))
3840                                    }
3841                                    _ => todo!("cannot integer-divide {:?} by {:?}", lhs, rhs),
3842                                },
3843                                _ => todo!("cannot integer-divide {:?} by {:?}", lhs, rhs),
3844                            },
3845                            _ => todo!("cannot integer-divide {:?} by {:?}", lhs, rhs),
3846                        },
3847                        _ => todo!("cannot integer-divide {:?} by {:?}", lhs, rhs),
3848                    },
3849                    _ => todo!("cannot integer-divide {:?} by {:?}", lhs, rhs),
3850                },
3851                _ => todo!("cannot integer-divide {:?} by {:?}", lhs, rhs),
3852            },
3853        }
3854    }
3855
3856    fn eval_modulo(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
3857        match self.get_operands(node) {
3858            Err(e) => Err(e),
3859            Ok((lhs, rhs)) => match &lhs {
3860                InternalValue::Base(cvlhs) => match &rhs {
3861                    InternalValue::Base(cvrhs) => match &cvlhs {
3862                        Value::Base(svlhs) => match &cvrhs {
3863                            Value::Base(svrhs) => match &svlhs {
3864                                ScalarValue::Integer(ilhs) => match &svrhs {
3865                                    ScalarValue::Integer(irhs) => {
3866                                        Ok(InternalValue::make_int(ilhs % irhs))
3867                                    }
3868                                    _ => todo!("cannot compute {:?} modulo {:?}", lhs, rhs),
3869                                },
3870                                _ => todo!("cannot compute {:?} modulo {:?}", lhs, rhs),
3871                            },
3872                            _ => todo!("cannot compute {:?} modulo {:?}", lhs, rhs),
3873                        },
3874                        _ => todo!("cannot compute {:?} modulo {:?}", lhs, rhs),
3875                    },
3876                    _ => todo!("cannot compute {:?} modulo {:?}", lhs, rhs),
3877                },
3878                _ => todo!("cannot compute {:?} modulo {:?}", lhs, rhs),
3879            },
3880        }
3881    }
3882
3883    fn eval_left_shift(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
3884        match self.get_operands(node) {
3885            Err(e) => Err(e),
3886            Ok((lhs, rhs)) => match &lhs {
3887                InternalValue::Base(cvlhs) => match &rhs {
3888                    InternalValue::Base(cvrhs) => match &cvlhs {
3889                        Value::Base(svlhs) => match &cvrhs {
3890                            Value::Base(svrhs) => match &svlhs {
3891                                ScalarValue::Integer(ilhs) => match &svrhs {
3892                                    ScalarValue::Integer(irhs) => {
3893                                        Ok(InternalValue::make_int(ilhs << irhs))
3894                                    }
3895                                    _ => todo!("cannot compute {:?} left-shift {:?}", lhs, rhs),
3896                                },
3897                                _ => todo!("cannot compute {:?} left-shift {:?}", lhs, rhs),
3898                            },
3899                            _ => todo!("cannot compute {:?} left-shift {:?}", lhs, rhs),
3900                        },
3901                        _ => todo!("cannot compute {:?} left-shift {:?}", lhs, rhs),
3902                    },
3903                    _ => todo!("cannot compute {:?} left-shift {:?}", lhs, rhs),
3904                },
3905                _ => todo!("cannot compute {:?} left-shift {:?}", lhs, rhs),
3906            },
3907        }
3908    }
3909
3910    fn eval_right_shift(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
3911        match self.get_operands(node) {
3912            Err(e) => Err(e),
3913            Ok((lhs, rhs)) => match &lhs {
3914                InternalValue::Base(cvlhs) => match &rhs {
3915                    InternalValue::Base(cvrhs) => match &cvlhs {
3916                        Value::Base(svlhs) => match &cvrhs {
3917                            Value::Base(svrhs) => match &svlhs {
3918                                ScalarValue::Integer(ilhs) => match &svrhs {
3919                                    ScalarValue::Integer(irhs) => {
3920                                        Ok(InternalValue::make_int(ilhs >> irhs))
3921                                    }
3922                                    _ => todo!("cannot compute {:?} right-shift {:?}", lhs, rhs),
3923                                },
3924                                _ => todo!("cannot compute {:?} right-shift {:?}", lhs, rhs),
3925                            },
3926                            _ => todo!("cannot compute {:?} right-shift {:?}", lhs, rhs),
3927                        },
3928                        _ => todo!("cannot compute {:?} right-shift {:?}", lhs, rhs),
3929                    },
3930                    _ => todo!("cannot compute {:?} right-shift {:?}", lhs, rhs),
3931                },
3932                _ => todo!("cannot compute {:?} right-shift {:?}", lhs, rhs),
3933            },
3934        }
3935    }
3936
3937    fn eval_power(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
3938        match self.get_operands(node) {
3939            Err(e) => Err(e),
3940            Ok((lhs, rhs)) => match &lhs {
3941                InternalValue::Base(cvlhs) => match &rhs {
3942                    InternalValue::Base(cvrhs) => match &cvlhs {
3943                        Value::Base(svlhs) => match &cvrhs {
3944                            Value::Base(svrhs) => match &svlhs {
3945                                ScalarValue::Integer(ilhs) => match &svrhs {
3946                                    ScalarValue::Integer(irhs) => {
3947                                        Ok(InternalValue::make_int(ilhs.pow(*irhs as u32)))
3948                                    }
3949                                    ScalarValue::Float(frhs) => {
3950                                        Ok(InternalValue::make_float((*ilhs as f64).powf(*frhs)))
3951                                    }
3952                                    ScalarValue::Complex(crhs) => {
3953                                        let clhs = Complex64::new(*ilhs as f64, 0.0);
3954
3955                                        Ok(InternalValue::make_complex(clhs.powc(*crhs)))
3956                                    }
3957                                    _ => todo!("cannot raise {:?} to the power of {:?}", lhs, rhs),
3958                                },
3959                                ScalarValue::Float(flhs) => match &svrhs {
3960                                    ScalarValue::Integer(irhs) => {
3961                                        Ok(InternalValue::make_float(flhs.powf(*irhs as f64)))
3962                                    }
3963                                    ScalarValue::Float(frhs) => {
3964                                        Ok(InternalValue::make_float(flhs.powf(*frhs)))
3965                                    }
3966                                    ScalarValue::Complex(crhs) => {
3967                                        let clhs = Complex64::new(*flhs, 0.0);
3968
3969                                        Ok(InternalValue::make_complex(clhs.powc(*crhs)))
3970                                    }
3971                                    _ => todo!("cannot raise {:?} to the power of {:?}", lhs, rhs),
3972                                },
3973                                ScalarValue::Complex(clhs) => match &svrhs {
3974                                    ScalarValue::Integer(irhs) => {
3975                                        let crhs = Complex64::new(*irhs as f64, 0.0);
3976
3977                                        Ok(InternalValue::make_complex(clhs.powc(crhs)))
3978                                    }
3979                                    ScalarValue::Float(frhs) => {
3980                                        let crhs = Complex64::new(*frhs, 0.0);
3981
3982                                        Ok(InternalValue::make_complex(clhs.powc(crhs)))
3983                                    }
3984                                    ScalarValue::Complex(crhs) => {
3985                                        Ok(InternalValue::make_complex(clhs.powc(*crhs)))
3986                                    }
3987                                    _ => todo!("cannot add {:?} and {:?}", lhs, rhs),
3988                                },
3989                                _ => todo!("cannot raise {:?} to the power of {:?}", lhs, rhs),
3990                            },
3991                            _ => todo!("cannot raise {:?} to the power of {:?}", lhs, rhs),
3992                        },
3993                        _ => todo!("cannot raise {:?} to the power of {:?}", lhs, rhs),
3994                    },
3995                    _ => todo!("cannot raise {:?} to the power of {:?}", lhs, rhs),
3996                },
3997                _ => todo!("cannot raise {:?} to the power of {:?}", lhs, rhs),
3998            },
3999        }
4000    }
4001
4002    fn eval_bitwise_and(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
4003        match self.get_operands(node) {
4004            Err(e) => Err(e),
4005            Ok((lhs, rhs)) => match &lhs {
4006                InternalValue::Base(cvlhs) => match &rhs {
4007                    InternalValue::Base(cvrhs) => match &cvlhs {
4008                        Value::Base(svlhs) => match &cvrhs {
4009                            Value::Base(svrhs) => match &svlhs {
4010                                ScalarValue::Integer(ilhs) => match &svrhs {
4011                                    ScalarValue::Integer(irhs) => {
4012                                        Ok(InternalValue::make_int(ilhs & irhs))
4013                                    }
4014                                    _ => todo!("cannot compute {:?} bit-and {:?}", lhs, rhs),
4015                                },
4016                                _ => todo!("cannot compute {:?} bit-and {:?}", lhs, rhs),
4017                            },
4018                            _ => todo!("cannot compute {:?} bit-and {:?}", lhs, rhs),
4019                        },
4020                        _ => todo!("cannot compute {:?} bit-and {:?}", lhs, rhs),
4021                    },
4022                    _ => todo!("cannot compute {:?} bit-and {:?}", lhs, rhs),
4023                },
4024                _ => todo!("cannot compute {:?} bit-and {:?}", lhs, rhs),
4025            },
4026        }
4027    }
4028
4029    fn eval_bitwise_or(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
4030        match self.get_operands(node) {
4031            Err(e) => Err(e),
4032            Ok((lhs, rhs)) => match &lhs {
4033                InternalValue::Base(cvlhs) => match &rhs {
4034                    InternalValue::Base(cvrhs) => match &cvlhs {
4035                        Value::Base(svlhs) => match &cvrhs {
4036                            Value::Base(svrhs) => match &svlhs {
4037                                ScalarValue::Integer(ilhs) => match &svrhs {
4038                                    ScalarValue::Integer(irhs) => {
4039                                        Ok(InternalValue::make_int(ilhs | irhs))
4040                                    }
4041                                    _ => todo!("cannot compute {:?} bit-or {:?}", lhs, rhs),
4042                                },
4043                                _ => todo!("cannot compute {:?} bit-or {:?}", lhs, rhs),
4044                            },
4045                            _ => todo!("cannot compute {:?} bit-or {:?}", lhs, rhs),
4046                        },
4047                        _ => todo!("cannot compute {:?} bit-or {:?}", lhs, rhs),
4048                    },
4049                    _ => todo!("cannot compute {:?} bit-or {:?}", lhs, rhs),
4050                },
4051                InternalValue::Mapping(mlhs) => match &rhs {
4052                    InternalValue::Mapping(mrhs) => match self.merge_dicts(mlhs, mrhs) {
4053                        Err(e) => Err(e),
4054                        Ok(v) => Ok(InternalValue::Mapping(v)),
4055                    },
4056                    _ => todo!("cannot compute {:?} bit-or {:?}", lhs, rhs),
4057                },
4058                _ => todo!("cannot compute {:?} bit-or {:?}", lhs, rhs),
4059            },
4060        }
4061    }
4062
4063    fn eval_bitwise_xor(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
4064        match self.get_operands(node) {
4065            Err(e) => Err(e),
4066            Ok((lhs, rhs)) => match &lhs {
4067                InternalValue::Base(cvlhs) => match &rhs {
4068                    InternalValue::Base(cvrhs) => match &cvlhs {
4069                        Value::Base(svlhs) => match &cvrhs {
4070                            Value::Base(svrhs) => match &svlhs {
4071                                ScalarValue::Integer(ilhs) => match &svrhs {
4072                                    ScalarValue::Integer(irhs) => {
4073                                        Ok(InternalValue::make_int(ilhs ^ irhs))
4074                                    }
4075                                    _ => todo!("cannot compute {:?} bit-xor {:?}", lhs, rhs),
4076                                },
4077                                _ => todo!("cannot compute {:?} bit-xor {:?}", lhs, rhs),
4078                            },
4079                            _ => todo!("cannot compute {:?} bit-xor {:?}", lhs, rhs),
4080                        },
4081                        _ => todo!("cannot compute {:?} bit-xor {:?}", lhs, rhs),
4082                    },
4083                    _ => todo!("cannot compute {:?} bit-xor {:?}", lhs, rhs),
4084                },
4085                _ => todo!("cannot compute {:?} bit-xor {:?}", lhs, rhs),
4086            },
4087        }
4088    }
4089
4090    fn eval_logical_or(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
4091        match self.evaluate(&node.left) {
4092            Err(e) => Err(e),
4093            Ok(v) => match &v {
4094                InternalValue::Base(cv) => match cv {
4095                    Value::Base(sv) => match sv {
4096                        ScalarValue::Bool(b) => {
4097                            if *b {
4098                                Ok(v)
4099                            } else {
4100                                self.evaluate(&node.right)
4101                            }
4102                        }
4103                        _ => Err(ConfigError::EvaluationFailed(node.start)),
4104                    },
4105                    _ => Err(ConfigError::EvaluationFailed(node.start)),
4106                },
4107                _ => Err(ConfigError::EvaluationFailed(node.start)),
4108            },
4109        }
4110    }
4111
4112    fn eval_logical_and(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
4113        match self.evaluate(&node.left) {
4114            Err(e) => Err(e),
4115            Ok(v) => match &v {
4116                InternalValue::Base(cv) => match cv {
4117                    Value::Base(sv) => match sv {
4118                        ScalarValue::Bool(b) => {
4119                            if !*b {
4120                                Ok(v)
4121                            } else {
4122                                self.evaluate(&node.right)
4123                            }
4124                        }
4125                        _ => Err(ConfigError::EvaluationFailed(node.start)),
4126                    },
4127                    _ => Err(ConfigError::EvaluationFailed(node.start)),
4128                },
4129                _ => Err(ConfigError::EvaluationFailed(node.start)),
4130            },
4131        }
4132    }
4133
4134    fn eval_binary(&self, node: &BinaryNode) -> StdResult<InternalValue, ConfigError> {
4135        match node.kind {
4136            TokenKind::Plus => self.eval_add(node),
4137            TokenKind::Minus => self.eval_subtract(node),
4138            TokenKind::Star => self.eval_multiply(node),
4139            TokenKind::Slash => self.eval_divide(node),
4140            TokenKind::SlashSlash => self.eval_integer_divide(node),
4141            TokenKind::Modulo => self.eval_modulo(node),
4142            TokenKind::Power => self.eval_power(node),
4143            TokenKind::LeftShift => self.eval_left_shift(node),
4144            TokenKind::RightShift => self.eval_right_shift(node),
4145            TokenKind::BitwiseAnd => self.eval_bitwise_and(node),
4146            TokenKind::BitwiseOr => self.eval_bitwise_or(node),
4147            TokenKind::BitwiseXor => self.eval_bitwise_xor(node),
4148            TokenKind::And => self.eval_logical_and(node),
4149            TokenKind::Or => self.eval_logical_or(node),
4150            _ => todo!("unhandled binary node {:?}", node.kind),
4151        }
4152    }
4153
4154    fn evaluate(&self, node: &ASTValue) -> StdResult<InternalValue, ConfigError> {
4155        match node {
4156            ASTValue::TokenValue(t) => match &t.value {
4157                ScalarValue::Identifier(s) => match self.context {
4158                    None => Err(ConfigError::NoContext),
4159                    Some(ref cmap) => match cmap.get(s) {
4160                        None => Err(ConfigError::UnknownVariable(s.clone(), t.start)),
4161                        Some(v) => Ok(InternalValue::Base(v.clone())),
4162                    },
4163                },
4164                ScalarValue::String(s) => {
4165                    if t.kind == TokenKind::BackTick {
4166                        match self.convert_string(&s) {
4167                            None => Err(ConfigError::ConversionError(s.to_string())),
4168                            Some(v) => Ok(InternalValue::Base(v)),
4169                        }
4170                    } else {
4171                        Ok(InternalValue::Base(Value::Base(t.value.clone())))
4172                    }
4173                }
4174                _ => Ok(InternalValue::Base(Value::Base(t.value.clone()))),
4175            },
4176            ASTValue::Unary(un) => self.eval_unary(&un),
4177            ASTValue::Binary(bn) => self.eval_binary(&bn),
4178            ASTValue::Mapping(items) => match self.wrap_mapping(&items) {
4179                Err(e) => Err(e),
4180                Ok(data) => Ok(InternalValue::Mapping(data)),
4181            },
4182            ASTValue::List(items) => Ok(InternalValue::List(self.wrap_sequence(items))),
4183            _ => todo!("other AST node evaluation: {:?}", node),
4184        }
4185    }
4186
4187    /// Returns ``true`` if this configuration contains the simple key ``key``
4188    /// (i.e. not a path), else ``false``.
4189    pub fn contains_key(&self, key: &str) -> bool {
4190        match &*self.data.borrow() {
4191            InternalValue::Mapping(hm) => hm.get(key).is_some(),
4192            _ => false,
4193        }
4194    }
4195
4196    fn get_location(&self, node: &ASTValue) -> StdResult<Location, ConfigError> {
4197        let result = match node {
4198            ASTValue::TokenValue(t) => t.start,
4199            ASTValue::Unary(un) => un.start,
4200            ASTValue::Binary(bn) => bn.start,
4201            ASTValue::Slice(loc, _, _, _) => *loc,
4202            _ => panic!("unable to determine position for {:?}", node),
4203        };
4204        Ok(result)
4205    }
4206
4207    fn get_slice_index_or_step(
4208        &self,
4209        pos: Location,
4210        maybe_node: &Option<ASTValue>,
4211    ) -> StdResult<Option<i64>, ConfigError> {
4212        match maybe_node {
4213            None => Ok(None),
4214            Some(node) => match self.evaluate(node) {
4215                Err(e) => Err(e),
4216                Ok(v) => match v {
4217                    InternalValue::Base(b) => match b {
4218                        Value::Base(sv) => match sv {
4219                            ScalarValue::Integer(i) => Ok(Some(i)),
4220                            _ => Err(ConfigError::InvalidPathOperand(pos)),
4221                        },
4222                        _ => Err(ConfigError::InvalidPathOperand(pos)),
4223                    },
4224                    _ => Err(ConfigError::InvalidPathOperand(pos)),
4225                },
4226            },
4227        }
4228    }
4229
4230    fn get_slice(
4231        &self,
4232        pos: Location,
4233        list: &[Rc<RefCell<InternalValue>>],
4234        start: Option<i64>,
4235        stop: Option<i64>,
4236        step: Option<i64>,
4237    ) -> StdResult<Vec<Rc<RefCell<InternalValue>>>, ConfigError> {
4238        let size = list.len() as i64;
4239        let step_value = match step {
4240            None => 1,
4241            Some(i) => i,
4242        };
4243        if step_value == 0 {
4244            return Err(ConfigError::InvalidPathOperand(pos));
4245        }
4246        let mut start_index = match start {
4247            None => 0,
4248            Some(mut i) => {
4249                if i < 0 {
4250                    if i >= -size {
4251                        i += size;
4252                    } else {
4253                        i = 0;
4254                    }
4255                } else if i >= size {
4256                    i = size - 1;
4257                };
4258                i
4259            }
4260        };
4261        let mut stop_index = match stop {
4262            None => size - 1,
4263            Some(mut i) => {
4264                if i < 0 {
4265                    if i >= -size {
4266                        i += size;
4267                    } else {
4268                        i = 0;
4269                    }
4270                };
4271                if i > size {
4272                    i = size;
4273                }
4274                if step_value < 0 {
4275                    i += 1;
4276                } else {
4277                    i -= 1;
4278                }
4279                i
4280            }
4281        };
4282        if step_value < 0 && start_index < stop_index {
4283            std::mem::swap(&mut stop_index, &mut start_index);
4284        }
4285        let mut i = start_index;
4286        let mut result = vec![];
4287        let mut not_done = if step_value > 0 {
4288            i <= stop_index
4289        } else {
4290            i >= stop_index
4291        };
4292        while not_done {
4293            result.push(list[i as usize].clone());
4294            i += step_value;
4295            not_done = if step_value > 0 {
4296                i <= stop_index
4297            } else {
4298                i >= stop_index
4299            };
4300        }
4301        Ok(result)
4302    }
4303
4304    fn reference_seen(&self, node: &ASTValue) -> bool {
4305        if let ASTValue::Unary(un) = node {
4306            if un.kind == TokenKind::Dollar {
4307                let k = (to_source(node), un.start);
4308
4309                if self.refs_seen.borrow().contains(&k) {
4310                    return true;
4311                }
4312                self.refs_seen.borrow_mut().insert(k);
4313            }
4314        }
4315        false
4316    }
4317
4318    fn get_from_path(&self, node: &ASTValue) -> StdResult<InternalValue, ConfigError> {
4319        let path = unpack_path(node);
4320        let mut result = self.data.clone();
4321
4322        for element in path.iter() {
4323            let new_result: Rc<RefCell<InternalValue>>;
4324
4325            match element {
4326                PathElement::Attribute(t) => {
4327                    let key = match t.kind {
4328                        TokenKind::Word => t.text.clone(),
4329                        TokenKind::String => match &t.value {
4330                            ScalarValue::String(s) => s.clone(),
4331                            _ => panic!("unexpected token value: {:?}", t.value),
4332                        },
4333                        _ => panic!("unexpected token kind: {:?}", t.kind),
4334                    };
4335                    match &*result.borrow() {
4336                        InternalValue::Base(b) => match b {
4337                            Value::Mapping(hm) => match hm.get(&key) {
4338                                None => return Err(ConfigError::NotPresent(key, Some(t.start))),
4339                                Some(v) => {
4340                                    new_result = make_node(InternalValue::Base(v.clone()));
4341                                }
4342                            },
4343                            Value::Config(cfg) => {
4344                                new_result = make_node(InternalValue::Base(cfg.get(&key)?));
4345                            }
4346                            _ => return Err(ConfigError::InvalidPathOperand(t.start)),
4347                        },
4348                        InternalValue::Mapping(hm) => {
4349                            match hm.get(&key) {
4350                                None => return Err(ConfigError::NotPresent(key, Some(t.start))),
4351                                Some(v) => {
4352                                    /*
4353
4354                                    If we decide to store back the evaluated version back into the
4355                                    map. we need to do the stuff below. Otherwise just clone it,
4356                                    and evaluate later
4357                                    if let InternalConfigValue::AST(node) = &*v.borrow() {
4358                                        // check for circular references
4359                                        if self.reference_seen(node) {
4360                                            let mut locations: Vec<Location> =
4361                                                self.refs_seen.borrow().iter().cloned().collect();
4362
4363                                            locations.sort();
4364                                            return Err(ConfigError::CircularReferenceError(
4365                                                locations,
4366                                            ));
4367                                        }
4368                                        // convert AST to internal config value of another type
4369                                        // and save it back
4370                                        new_result = make_node(self.evaluate(node)?)
4371                                    } else {
4372                                        new_result = v.clone();
4373                                    }
4374                                    */
4375                                    new_result = v.clone();
4376                                }
4377                            }
4378                        }
4379                        _ => return Err(ConfigError::InvalidPathOperand(t.start)),
4380                    }
4381                }
4382                PathElement::IndexedAccess(index_node) => {
4383                    let spos = self.get_location(index_node).unwrap();
4384
4385                    match &*result.borrow() {
4386                        InternalValue::List(lv) => {
4387                            let v = self.evaluate(index_node)?;
4388
4389                            match v {
4390                                InternalValue::Base(b) => match b {
4391                                    Value::Base(sv) => match sv {
4392                                        ScalarValue::Integer(mut index) => {
4393                                            let size = lv.len() as i64;
4394
4395                                            if index < 0 && index >= -size {
4396                                                index += size;
4397                                            }
4398                                            if index < 0 || index >= size {
4399                                                return Err(ConfigError::IndexOutOfRange(
4400                                                    index, spos,
4401                                                ));
4402                                            }
4403                                            /*
4404                                             * If we decide to save an evaluated version back into
4405                                             * the list, we would need to do that here. Otherwise,
4406                                             * evaluating below (after this match) is fine.
4407                                             */
4408                                            new_result = lv[index as usize].clone();
4409                                        }
4410                                        _ => return Err(ConfigError::InvalidPathOperand(spos)),
4411                                    },
4412                                    _ => return Err(ConfigError::InvalidPathOperand(spos)),
4413                                },
4414                                _ => return Err(ConfigError::InvalidPathOperand(spos)),
4415                            }
4416                        }
4417                        _ => return Err(ConfigError::InvalidPathOperand(spos)),
4418                    };
4419                }
4420                PathElement::SliceAccess(slice) => {
4421                    let spos = self.get_location(slice).unwrap();
4422
4423                    match &*result.borrow() {
4424                        InternalValue::List(lv) => match slice {
4425                            ASTValue::Slice(loc, start, stop, step) => {
4426                                let start_index = self.get_slice_index_or_step(*loc, &*start)?;
4427                                let stop_index = self.get_slice_index_or_step(*loc, &*stop)?;
4428                                let step_value = self.get_slice_index_or_step(*loc, &*step)?;
4429                                let slice =
4430                                    self.get_slice(*loc, lv, start_index, stop_index, step_value)?;
4431
4432                                new_result = make_node(InternalValue::List(slice))
4433                            }
4434                            _ => {
4435                                return Err(ConfigError::InvalidPathOperand(spos));
4436                            }
4437                        },
4438                        _ => return Err(ConfigError::InvalidPathOperand(spos)),
4439                    }
4440                }
4441            }
4442
4443            /*
4444             * If the result is an AST node, we evaluate it here. Note that we don't know where it
4445             * came from (e.g. list or mapping) so we can't save it back in the original container -
4446             * to do that, we have to do the evaluation in the individual branches of the match
4447             * above.
4448             */
4449            let mut evaluated: Option<InternalValue> = None;
4450
4451            if let InternalValue::AST(node) = &*new_result.borrow() {
4452                if self.reference_seen(node) {
4453                    let mut locations: Vec<(String, Location)> =
4454                        self.refs_seen.borrow().iter().cloned().collect();
4455
4456                    locations.sort();
4457                    return Err(ConfigError::CircularReferenceError(locations));
4458                }
4459                evaluated = Some(self.evaluate(node)?);
4460            }
4461            if let Some(icv) = evaluated {
4462                result = make_node(icv);
4463            } else {
4464                result = new_result;
4465            }
4466        }
4467        let r = (&*result).borrow().clone();
4468        Ok(r)
4469    }
4470
4471    fn base_unwrap_list(
4472        &self,
4473        items: &[Rc<RefCell<InternalValue>>],
4474        unwrap_configs: bool,
4475    ) -> StdResult<Vec<Value>, ConfigError> {
4476        let mut result = vec![];
4477
4478        for item in items {
4479            result.push(self.unwrap(&item.borrow(), unwrap_configs)?);
4480        }
4481        Ok(result)
4482    }
4483
4484    fn unwrap_list(
4485        &self,
4486        items: &[Rc<RefCell<InternalValue>>],
4487        unwrap_configs: bool,
4488    ) -> StdResult<Value, ConfigError> {
4489        match self.base_unwrap_list(items, unwrap_configs) {
4490            Err(e) => Err(e),
4491            Ok(v) => Ok(Value::List(v)),
4492        }
4493    }
4494
4495    fn base_unwrap_map(
4496        &self,
4497        map: &HashMap<String, Rc<RefCell<InternalValue>>>,
4498        unwrap_configs: bool,
4499    ) -> StdResult<HashMap<String, Value>, ConfigError> {
4500        let mut result: HashMap<String, Value> = HashMap::new();
4501
4502        for (k, v) in map.iter() {
4503            result.insert(k.to_string(), self.unwrap(&*v.borrow(), unwrap_configs)?);
4504        }
4505        Ok(result)
4506    }
4507
4508    fn unwrap_map(
4509        &self,
4510        map: &HashMap<String, Rc<RefCell<InternalValue>>>,
4511        unwrap_configs: bool,
4512    ) -> StdResult<Value, ConfigError> {
4513        match self.base_unwrap_map(map, unwrap_configs) {
4514            Err(e) => Err(e),
4515            Ok(v) => Ok(Value::Mapping(v)),
4516        }
4517    }
4518
4519    fn unwrap(&self, icv: &InternalValue, unwrap_configs: bool) -> StdResult<Value, ConfigError> {
4520        match icv {
4521            InternalValue::AST(node) => match self.evaluate(&node) {
4522                Err(e) => Err(e),
4523                Ok(icv) => self.unwrap(&icv, unwrap_configs),
4524            },
4525            InternalValue::Base(cv) => match cv {
4526                Value::Config(c) => {
4527                    if !unwrap_configs {
4528                        Ok(cv.clone())
4529                    } else {
4530                        Ok(Value::Mapping(c.as_mapping(unwrap_configs)?))
4531                    }
4532                }
4533                _ => Ok(cv.clone()),
4534            },
4535            InternalValue::List(items) => self.unwrap_list(&items, unwrap_configs),
4536            InternalValue::Mapping(hm) => self.unwrap_map(&hm, unwrap_configs),
4537        }
4538    }
4539
4540    /// Convert the configuration to a HashMap.
4541    ///
4542    /// If `unwrap_configs` is `true`, nested configurations are also converted
4543    /// to mappings. Otherwise, they are left as is.
4544    pub fn as_mapping(
4545        &self,
4546        unwrap_configs: bool,
4547    ) -> StdResult<HashMap<String, Value>, ConfigError> {
4548        let v = self.unwrap(&*self.data.borrow(), unwrap_configs)?;
4549
4550        match v {
4551            Value::Mapping(hm) => Ok(hm),
4552            _ => panic!("unexpected value returned: {:?}", v),
4553        }
4554    }
4555
4556    /// Returns the value for the specified configuration key.
4557    ///
4558    /// `key` can either be an identifier or a valid path.
4559    pub fn get(&self, key: &str) -> StdResult<Value, ConfigError> {
4560        self.refs_seen.borrow_mut().clear();
4561        match &*self.data.borrow() {
4562            InternalValue::Mapping(hm) => {
4563                if hm.is_empty() {
4564                    Err(ConfigError::NotLoaded)
4565                } else {
4566                    let iv = match hm.get(key) {
4567                        None => {
4568                            if is_identifier(key) {
4569                                Err(ConfigError::NotPresent(key.to_string(), None))
4570                            } else {
4571                                match parse_path(key) {
4572                                    Err(e) => Err(ConfigError::InvalidPath(e)),
4573                                    Ok(node) => self.get_from_path(&node),
4574                                }
4575                            }
4576                        }
4577                        Some(v) => {
4578                            let r = v.borrow();
4579                            Ok(r.clone())
4580                        }
4581                    };
4582                    match iv {
4583                        Err(e) => Err(e),
4584                        Ok(icv) => self.unwrap(&icv, false),
4585                    }
4586                }
4587            }
4588            _ => panic!("unexpected root data type"),
4589        }
4590    }
4591
4592    pub(crate) fn convert_string(&self, s: &str) -> Option<Value> {
4593        (self.string_converter.0)(s, &self)
4594    }
4595}