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