Skip to main content

nxs/
parser.rs

1use crate::error::{NxsError, Result};
2use crate::lexer::Token;
3
4#[derive(Debug, Clone)]
5pub enum Value {
6    Int(i64),
7    Float(f64),
8    Bool(bool),
9    Keyword(String),
10    Str(String),
11    Time(i64),
12    Binary(Vec<u8>),
13    Link(i32),
14    Macro(String),
15    Null,
16    Object(Vec<Field>),
17    List(Vec<Value>),
18}
19
20#[derive(Debug, Clone)]
21pub struct Field {
22    pub key: String,
23    pub value: Value,
24}
25
26pub struct Parser {
27    tokens: Vec<Token>,
28    pos: usize,
29    depth: usize,
30}
31
32const MAX_DEPTH: usize = 64;
33
34impl Parser {
35    pub fn new(tokens: Vec<Token>) -> Self {
36        Parser {
37            tokens,
38            pos: 0,
39            depth: 0,
40        }
41    }
42
43    /// Resume parsing after leading pragma tokens.
44    pub fn set_pos(&mut self, pos: usize) {
45        self.pos = pos;
46    }
47
48    fn peek(&self) -> &Token {
49        self.tokens.get(self.pos).unwrap_or(&Token::Eof)
50    }
51
52    fn advance(&mut self) -> &Token {
53        let t = self.tokens.get(self.pos).unwrap_or(&Token::Eof);
54        self.pos += 1;
55        t
56    }
57
58    fn expect(&mut self, expected: &Token) -> Result<()> {
59        let t = self.advance().clone();
60        if &t == expected {
61            Ok(())
62        } else {
63            Err(NxsError::ParseError(format!(
64                "expected {expected:?}, got {t:?}"
65            )))
66        }
67    }
68
69    pub fn parse_file(&mut self) -> Result<Vec<Field>> {
70        let mut fields = Vec::new();
71        while self.peek() != &Token::Eof {
72            fields.push(self.parse_field()?);
73        }
74        Ok(fields)
75    }
76
77    fn parse_field(&mut self) -> Result<Field> {
78        let key = match self.advance().clone() {
79            Token::Ident(s) => s,
80            other => {
81                return Err(NxsError::ParseError(format!(
82                    "expected field key, got {other:?}"
83                )));
84            }
85        };
86
87        // Colon is optional if followed by `{` (shorthand object syntax)
88        if self.peek() == &Token::Colon {
89            self.advance();
90        }
91
92        let value = self.parse_value()?;
93        Ok(Field { key, value })
94    }
95
96    fn parse_value(&mut self) -> Result<Value> {
97        match self.peek().clone() {
98            Token::LBrace => self.parse_object(),
99            Token::LBracket => self.parse_list(),
100            Token::Int(n) => {
101                self.advance();
102                Ok(Value::Int(n))
103            }
104            Token::Float(f) => {
105                self.advance();
106                Ok(Value::Float(f))
107            }
108            Token::Bool(b) => {
109                self.advance();
110                Ok(Value::Bool(b))
111            }
112            Token::Keyword(s) => {
113                self.advance();
114                Ok(Value::Keyword(s))
115            }
116            Token::Str(s) => {
117                self.advance();
118                Ok(Value::Str(s))
119            }
120            Token::Time(ns) => {
121                self.advance();
122                Ok(Value::Time(ns))
123            }
124            Token::Binary(b) => {
125                self.advance();
126                Ok(Value::Binary(b))
127            }
128            Token::Link(n) => {
129                self.advance();
130                Ok(Value::Link(n))
131            }
132            Token::Macro(s) => {
133                self.advance();
134                Ok(Value::Macro(s))
135            }
136            Token::Null => {
137                self.advance();
138                Ok(Value::Null)
139            }
140            other => Err(NxsError::ParseError(format!(
141                "unexpected token for value: {other:?}"
142            ))),
143        }
144    }
145
146    fn parse_object(&mut self) -> Result<Value> {
147        self.depth += 1;
148        if self.depth > MAX_DEPTH {
149            return Err(NxsError::RecursionLimit);
150        }
151        self.expect(&Token::LBrace)?;
152        let mut fields = Vec::new();
153        while self.peek() != &Token::RBrace && self.peek() != &Token::Eof {
154            fields.push(self.parse_field()?);
155            // optional comma between fields
156            if self.peek() == &Token::Comma {
157                self.advance();
158            }
159        }
160        self.expect(&Token::RBrace)?;
161        self.depth -= 1;
162        Ok(Value::Object(fields))
163    }
164
165    fn parse_list(&mut self) -> Result<Value> {
166        self.expect(&Token::LBracket)?;
167        let mut elems = Vec::new();
168        let mut sigil_tag: Option<&'static str> = None;
169
170        while self.peek() != &Token::RBracket && self.peek() != &Token::Eof {
171            let v = self.parse_value()?;
172            let tag = sigil_name(&v);
173            match sigil_tag {
174                None => sigil_tag = Some(tag),
175                Some(expected) if expected != tag => return Err(NxsError::ListTypeMismatch),
176                _ => {}
177            }
178            elems.push(v);
179            if self.peek() == &Token::Comma {
180                self.advance();
181            }
182        }
183        self.expect(&Token::RBracket)?;
184        Ok(Value::List(elems))
185    }
186}
187
188fn sigil_name(v: &Value) -> &'static str {
189    match v {
190        Value::Int(_) => "int",
191        Value::Float(_) => "float",
192        Value::Bool(_) => "bool",
193        Value::Keyword(_) => "keyword",
194        Value::Str(_) => "str",
195        Value::Time(_) => "time",
196        Value::Binary(_) => "binary",
197        Value::Link(_) => "link",
198        Value::Macro(_) => "macro",
199        Value::Null => "null",
200        Value::Object(_) => "object",
201        Value::List(_) => "list",
202    }
203}