1use crate::ast::*;
4use crate::error::{JsonnetError, Result};
5use crate::lexer::{Lexer, Token, TokenWithPos};
6use crate::value::JsonnetValue;
7
8pub struct Parser {
10 tokens: Vec<TokenWithPos>,
11 current: usize,
12}
13
14impl Parser {
15 pub fn new() -> Self {
17 Parser {
18 tokens: Vec::new(),
19 current: 0,
20 }
21 }
22
23 pub fn parse(&mut self, source: &str) -> Result<Program> {
25 let mut lexer = Lexer::new(source);
26 self.tokens = lexer.tokenize()?;
27 self.current = 0;
28
29 let mut program = Program::new();
30
31 while !self.is_at_end() {
32 let stmt = self.parse_statement()?;
33 program.add_statement(stmt);
34
35 if self.match_token(Token::Semicolon) {
37 }
39 }
40
41 Ok(program)
42 }
43
44 pub fn parse_expression(&mut self, source: &str) -> Result<Expr> {
46 let mut lexer = Lexer::new(source);
47 self.tokens = lexer.tokenize()?;
48 self.current = 0;
49 self.parse_expr()
50 }
51
52 fn parse_statement(&mut self) -> Result<Stmt> {
54 if self.match_token(Token::Local) {
55 self.parse_local_statement()
56 } else if self.match_token(Token::Assert) {
57 self.parse_assert_statement()
58 } else {
59 Ok(Stmt::Expr(self.parse_conditional()?))
60 }
61 }
62
63 fn parse_local_expression(&mut self) -> Result<Expr> {
65 let mut bindings = Vec::new();
66
67 loop {
68 let name = self.consume_identifier("Expected identifier after local")?;
69 self.consume_token(Token::Assign, "Expected '=' after identifier")?;
70 let expr = self.parse_conditional()?;
71 bindings.push((name, expr));
72
73 if !self.match_token(Token::Comma) {
74 break;
75 }
76 }
77
78 self.consume_token(Token::Semicolon, "Expected ';' after local bindings")?;
79 let body = self.parse_conditional()?;
80
81 Ok(Expr::Local {
82 bindings,
83 body: Box::new(body),
84 })
85 }
86
87 fn parse_expr(&mut self) -> Result<Expr> {
89 self.parse_conditional()
90 }
91
92 fn parse_local_statement(&mut self) -> Result<Stmt> {
94 let mut bindings = Vec::new();
95
96 loop {
97 let name = self.consume_identifier("Expected identifier after local")?;
98 self.consume_token(Token::Equal, "Expected '=' after identifier")?;
99 let expr = self.parse_expr()?;
100 bindings.push((name, expr));
101
102 if !self.match_token(Token::Comma) {
103 break;
104 }
105 }
106
107 self.consume_token(Token::Semicolon, "Expected ';' after local bindings")?;
108 let _body = self.parse_expr()?;
109
110 Ok(Stmt::Local(bindings))
111 }
112
113 fn parse_assert_statement(&mut self) -> Result<Stmt> {
115 let cond = self.parse_conditional()?;
116 let message = if self.match_token(Token::Colon) {
117 Some(self.parse_conditional()?)
118 } else {
119 None
120 };
121
122 self.consume_token(Token::Semicolon, "Expected ';' after assert")?;
123 let _expr = self.parse_conditional()?;
124
125 Ok(Stmt::Assert { cond, message })
126 }
127
128 fn parse_conditional(&mut self) -> Result<Expr> {
130 if self.match_token(Token::If) {
131 let cond = self.parse_conditional()?;
132 self.consume_token(Token::Then, "Expected 'then' after if condition")?;
133 let then_branch = self.parse_conditional()?;
134 let else_branch = if self.match_token(Token::Else) {
135 Some(self.parse_conditional()?)
136 } else {
137 None
138 };
139
140 Ok(Expr::If {
141 cond: Box::new(cond),
142 then_branch: Box::new(then_branch),
143 else_branch: else_branch.map(Box::new),
144 })
145 } else {
146 self.parse_binary(0)
147 }
148 }
149
150 fn parse_binary(&mut self, precedence: u8) -> Result<Expr> {
152 let mut left = self.parse_unary()?;
153
154 while let Some(op) = self.get_binary_op() {
155 let op_precedence = self.get_precedence(&op);
156 if op_precedence <= precedence {
157 break;
158 }
159
160 self.advance();
161 let right = self.parse_binary(op_precedence)?;
162 left = Expr::BinaryOp {
163 left: Box::new(left),
164 op,
165 right: Box::new(right),
166 };
167 }
168
169 Ok(left)
170 }
171
172 fn parse_unary(&mut self) -> Result<Expr> {
174 if self.match_token(Token::Not) {
175 Ok(Expr::UnaryOp {
176 op: UnaryOp::Not,
177 expr: Box::new(self.parse_unary()?),
178 })
179 } else if self.match_token(Token::Minus) {
180 Ok(Expr::UnaryOp {
181 op: UnaryOp::Neg,
182 expr: Box::new(self.parse_unary()?),
183 })
184 } else if self.match_token(Token::Local) {
185 self.parse_local_expression()
186 } else if self.match_token(Token::Plus) {
187 Ok(Expr::UnaryOp {
188 op: UnaryOp::Pos,
189 expr: Box::new(self.parse_unary()?),
190 })
191 } else {
192 self.parse_postfix()
193 }
194 }
195
196 fn parse_postfix(&mut self) -> Result<Expr> {
198 let mut expr = self.parse_primary()?;
199
200 loop {
201 if self.match_token(Token::LParen) {
202 let mut args = Vec::new();
204 if !self.check_token(Token::RParen) {
205 loop {
206 args.push(self.parse_conditional()?);
207 if !self.match_token(Token::Comma) {
208 break;
209 }
210 }
211 }
212 self.consume_token(Token::RParen, "Expected ')' after function arguments")?;
213 expr = Expr::Call {
214 func: Box::new(expr),
215 args,
216 };
217 } else if self.match_token(Token::Dot) {
218 let field_name = self.consume_identifier("Expected identifier after '.'")?;
220 expr = Expr::Index {
221 target: Box::new(expr),
222 index: Box::new(Expr::Literal(JsonnetValue::string(field_name))),
223 };
224 } else if self.match_token(Token::LBracket) {
225 let index = self.parse_conditional()?;
227 self.consume_token(Token::RBracket, "Expected ']' after array index")?;
228 expr = Expr::Index {
229 target: Box::new(expr),
230 index: Box::new(index),
231 };
232 } else {
233 break;
234 }
235 }
236
237 Ok(expr)
238 }
239
240 fn parse_primary(&mut self) -> Result<Expr> {
242 if self.match_token(Token::Function) {
243 self.consume_token(Token::LParen, "Expected '(' after function")?;
245 let mut parameters = Vec::new();
246 if !self.check_token(Token::RParen) {
247 loop {
248 let param = self.consume_identifier("Expected parameter name")?;
249 parameters.push(param);
250 if !self.match_token(Token::Comma) {
251 break;
252 }
253 }
254 }
255 self.consume_token(Token::RParen, "Expected ')' after function parameters")?;
256 let body = self.parse_conditional()?;
257 Ok(Expr::Function {
258 parameters,
259 body: Box::new(body),
260 })
261 } else if self.match_token(Token::LBrace) {
262 self.parse_object()
263 } else if self.match_token(Token::LBracket) {
264 self.parse_array()
265 } else if self.match_token(Token::Null) {
266 Ok(Expr::Literal(crate::value::JsonnetValue::Null))
267 } else if self.match_token(Token::True) {
268 Ok(Expr::Literal(crate::value::JsonnetValue::boolean(true)))
269 } else if self.match_token(Token::False) {
270 Ok(Expr::Literal(crate::value::JsonnetValue::boolean(false)))
271 } else if let Some(token) = self.peek_token().cloned() {
272 match token {
273 Token::Number(n) => {
274 self.advance();
275 Ok(Expr::Literal(crate::value::JsonnetValue::number(n)))
276 }
277 Token::String(s) => {
278 self.advance();
279 Ok(Expr::Literal(crate::value::JsonnetValue::string(s)))
280 }
281 Token::StringInterpolation(parts) => {
282 self.advance();
283 let interpolation_parts: Vec<StringInterpolationPart> = parts.into_iter()
284 .map(|part| match part {
285 crate::lexer::StringPart::Literal(s) =>
286 StringInterpolationPart::Literal(s),
287 crate::lexer::StringPart::Interpolation(var) =>
288 StringInterpolationPart::Interpolation(Box::new(Expr::Var(var))),
289 })
290 .collect();
291 Ok(Expr::StringInterpolation(interpolation_parts))
292 }
293 Token::Identifier(id) => {
294 self.advance();
295 Ok(Expr::Var(id))
296 }
297 _ => {
298 if self.match_token(Token::LParen) {
299 let expr = self.parse_expr()?;
300 self.consume_token(Token::RParen, "Expected ')' after expression")?;
301 Ok(expr)
302 } else if self.match_token(Token::LBracket) {
303 self.parse_array()
304 } else if self.match_token(Token::LBrace) {
305 self.parse_object()
306 } else {
307 Err(self.error("Expected expression"))
308 }
309 }
310 }
311 } else {
312 Err(self.error("Expected expression"))
313 }
314 }
315
316 fn parse_array(&mut self) -> Result<Expr> {
318 if self.check_token(Token::RBracket) {
320 self.advance();
322 return Ok(Expr::Array(Vec::new()));
323 }
324
325 let first_expr = self.parse_conditional()?;
326
327 if self.match_token(Token::For) {
328 let var_name = self.consume_identifier("Expected variable name after 'for'")?;
330 self.consume_token(Token::In, "Expected 'in' after variable name")?;
331 let array_expr = self.parse_conditional()?;
332
333 let condition = if self.match_token(Token::If) {
334 Some(self.parse_conditional()?)
335 } else {
336 None
337 };
338
339 self.consume_token(Token::RBracket, "Expected ']' after array comprehension")?;
340
341 Ok(Expr::ArrayComp {
342 expr: Box::new(first_expr),
343 var: var_name,
344 array: Box::new(array_expr),
345 cond: condition.map(Box::new),
346 })
347 } else {
348 let mut elements = vec![first_expr];
350
351 while self.match_token(Token::Comma) {
352 elements.push(self.parse_conditional()?);
353 }
354
355 self.consume_token(Token::RBracket, "Expected ']' after array elements")?;
356 Ok(Expr::Array(elements))
357 }
358 }
359
360 fn parse_object(&mut self) -> Result<Expr> {
362 let mut fields = Vec::new();
363
364 if !self.check_token(Token::RBrace) {
365 loop {
366 let field = self.parse_object_field()?;
367 fields.push(field);
368 if !self.match_token(Token::Comma) {
369 break;
370 }
371 }
372 }
373
374 self.consume_token(Token::RBrace, "Expected '}' after object fields")?;
375 Ok(Expr::Object(fields))
376 }
377
378 fn parse_object_field(&mut self) -> Result<ObjectField> {
380 let name = self.parse_field_name()?;
381 let visibility = if self.match_token(Token::DoubleColon) {
382 Visibility::Hidden
383 } else if self.match_token(Token::Plus) {
384 Visibility::Forced
385 } else {
386 Visibility::Normal
387 };
388
389 self.consume_token(Token::Colon, "Expected ':' after field name")?;
390 let expr = self.parse_conditional()?;
391
392 Ok(ObjectField {
393 name,
394 visibility,
395 expr: Box::new(expr),
396 })
397 }
398
399 fn parse_field_name(&mut self) -> Result<FieldName> {
401 if let Some(token) = self.peek_token().cloned() {
402 match token {
403 Token::Identifier(id) => {
404 self.advance();
405 Ok(FieldName::Fixed(id))
406 }
407 Token::String(s) => {
408 self.advance();
409 Ok(FieldName::Fixed(s))
410 }
411 _ => {
412 if self.match_token(Token::LBracket) {
413 let expr = self.parse_conditional()?;
414 self.consume_token(Token::RBracket, "Expected ']' after computed field name")?;
415 Ok(FieldName::Computed(Box::new(expr)))
416 } else {
417 Err(self.error("Expected field name"))
418 }
419 }
420 }
421 } else {
422 Err(self.error("Expected field name"))
423 }
424 }
425
426 fn get_binary_op(&mut self) -> Option<BinaryOp> {
428 match self.peek_token() {
429 Some(Token::Plus) => Some(BinaryOp::Add),
430 Some(Token::Minus) => Some(BinaryOp::Sub),
431 Some(Token::Star) => Some(BinaryOp::Mul),
432 Some(Token::Slash) => Some(BinaryOp::Div),
433 Some(Token::Percent) => Some(BinaryOp::Mod),
434 Some(Token::Equal) => Some(BinaryOp::Eq),
435 Some(Token::NotEqual) => Some(BinaryOp::Ne),
436 Some(Token::Less) => Some(BinaryOp::Lt),
437 Some(Token::LessEqual) => Some(BinaryOp::Le),
438 Some(Token::Greater) => Some(BinaryOp::Gt),
439 Some(Token::GreaterEqual) => Some(BinaryOp::Ge),
440 Some(Token::And) => Some(BinaryOp::And),
441 Some(Token::Or) => Some(BinaryOp::Or),
442 Some(Token::In) => Some(BinaryOp::In),
443 _ => None,
444 }
445 }
446
447 fn get_precedence(&self, op: &BinaryOp) -> u8 {
449 match op {
450 BinaryOp::Or => 1,
451 BinaryOp::And => 2,
452 BinaryOp::In => 3,
453 BinaryOp::Eq | BinaryOp::Ne => 4,
454 BinaryOp::Lt | BinaryOp::Le | BinaryOp::Gt | BinaryOp::Ge => 5,
455 BinaryOp::Add | BinaryOp::Sub | BinaryOp::Concat => 6,
456 BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod => 7,
457 BinaryOp::BitAnd | BinaryOp::BitOr | BinaryOp::BitXor => 8,
458 BinaryOp::ShiftL | BinaryOp::ShiftR => 9,
459 }
460 }
461
462 fn check_token(&self, token: Token) -> bool {
464 if self.is_at_end() {
465 false
466 } else {
467 std::mem::discriminant(&self.tokens[self.current].token) == std::mem::discriminant(&token)
468 }
469 }
470
471 fn match_token(&mut self, token: Token) -> bool {
473 if self.check_token(token) {
474 self.advance();
475 true
476 } else {
477 false
478 }
479 }
480
481 fn consume_token(&mut self, token: Token, message: &str) -> Result<()> {
483 if self.match_token(token) {
484 Ok(())
485 } else {
486 Err(self.error(message))
487 }
488 }
489
490 fn consume_identifier(&mut self, message: &str) -> Result<String> {
492 if let Some(token) = self.peek_token().cloned() {
493 match token {
494 Token::Identifier(id) => {
495 self.advance();
496 Ok(id)
497 }
498 _ => Err(self.error(message)),
499 }
500 } else {
501 Err(self.error(message))
502 }
503 }
504
505 fn peek_token(&self) -> Option<&Token> {
507 if self.is_at_end() {
508 None
509 } else {
510 Some(&self.tokens[self.current].token)
511 }
512 }
513
514 fn advance(&mut self) {
516 if !self.is_at_end() {
517 self.current += 1;
518 }
519 }
520
521 fn is_at_end(&self) -> bool {
523 self.current >= self.tokens.len() ||
524 matches!(self.tokens[self.current].token, Token::Eof)
525 }
526
527 fn error(&self, message: &str) -> JsonnetError {
529 if self.is_at_end() {
530 JsonnetError::parse_error(0, 0, format!("{} at end", message))
531 } else {
532 let pos = &self.tokens[self.current].position;
533 JsonnetError::parse_error(pos.line, pos.column, message.to_string())
534 }
535 }
536}
537
538impl Default for Parser {
539 fn default() -> Self {
540 Self::new()
541 }
542}
543
544#[cfg(test)]
545mod tests {
546 use super::*;
547
548 #[test]
549 fn test_parse_null() {
550 let mut parser = Parser::new();
551 let program = parser.parse("null").unwrap();
552 assert_eq!(program.statements.len(), 1);
553 match &program.statements[0] {
554 Stmt::Expr(Expr::Literal(val)) => assert_eq!(val, &crate::value::JsonnetValue::Null),
555 _ => panic!("Expected literal expression"),
556 }
557 }
558
559 #[test]
560 fn test_parse_boolean() {
561 let mut parser = Parser::new();
562 let program = parser.parse("true").unwrap();
563 assert_eq!(program.statements.len(), 1);
564 match &program.statements[0] {
565 Stmt::Expr(Expr::Literal(val)) => assert_eq!(val, &crate::value::JsonnetValue::boolean(true)),
566 _ => panic!("Expected literal expression"),
567 }
568 }
569
570 #[test]
571 fn test_parse_number() {
572 let mut parser = Parser::new();
573 let program = parser.parse("42.5").unwrap();
574 assert_eq!(program.statements.len(), 1);
575 match &program.statements[0] {
576 Stmt::Expr(Expr::Literal(val)) => assert_eq!(val, &crate::value::JsonnetValue::number(42.5)),
577 _ => panic!("Expected literal expression"),
578 }
579 }
580
581 #[test]
582 fn test_parse_string() {
583 let mut parser = Parser::new();
584 let program = parser.parse(r#""hello""#).unwrap();
585 assert_eq!(program.statements.len(), 1);
586 match &program.statements[0] {
587 Stmt::Expr(Expr::Literal(val)) => {
588 if let crate::value::JsonnetValue::String(s) = val {
589 assert_eq!(s, "hello");
590 } else {
591 panic!("Expected string value");
592 }
593 }
594 _ => panic!("Expected string literal expression"),
595 }
596 }
597
598 #[test]
599 fn test_parse_binary_op() {
600 let mut parser = Parser::new();
601 let program = parser.parse("1 + 2").unwrap();
602 assert_eq!(program.statements.len(), 1);
603 match &program.statements[0] {
604 Stmt::Expr(Expr::BinaryOp { left, op, right }) => {
605 match (&**left, op, &**right) {
606 (Expr::Literal(l), BinaryOp::Add, Expr::Literal(r)) => {
607 assert_eq!(l, &crate::value::JsonnetValue::number(1.0));
608 assert_eq!(r, &crate::value::JsonnetValue::number(2.0));
609 }
610 _ => panic!("Expected binary addition"),
611 }
612 }
613 _ => panic!("Expected binary operation"),
614 }
615 }
616
617 #[test]
618 fn test_parse_array() {
619 let mut parser = Parser::new();
620 let program = parser.parse("[1, 2, 3]").unwrap();
621 assert_eq!(program.statements.len(), 1);
622 match &program.statements[0] {
623 Stmt::Expr(Expr::Array(elements)) => {
624 assert_eq!(elements.len(), 3);
625 match (&elements[0], &elements[1], &elements[2]) {
626 (Expr::Literal(a), Expr::Literal(b), Expr::Literal(c)) => {
627 assert_eq!(a, &crate::value::JsonnetValue::number(1.0));
628 assert_eq!(b, &crate::value::JsonnetValue::number(2.0));
629 assert_eq!(c, &crate::value::JsonnetValue::number(3.0));
630 }
631 _ => panic!("Expected number literals"),
632 }
633 }
634 _ => panic!("Expected array expression"),
635 }
636 }
637
638 #[test]
639 fn test_parse_object() {
640 let mut parser = Parser::new();
641 let program = parser.parse(r#"{ name: "test", value: 42 }"#).unwrap();
642 assert_eq!(program.statements.len(), 1);
643 match &program.statements[0] {
644 Stmt::Expr(Expr::Object(fields)) => {
645 assert_eq!(fields.len(), 2);
646 assert!(matches!(fields[0].name, FieldName::Fixed(_)));
648 }
649 _ => panic!("Expected object expression"),
650 }
651 }
652
653 #[test]
654 fn test_parse_array_comprehension() {
655 let mut parser = Parser::new();
656 let program = parser.parse(r#"[x * 2 for x in [1, 2, 3]]"#);
657 match program {
658 Ok(program) => {
659 match &program.statements[0] {
660 Stmt::Expr(Expr::ArrayComp { expr, var, array, cond }) => {
661 assert_eq!(var, "x");
662 assert!(cond.is_none());
663 println!("Array comprehension parsed successfully");
665 }
666 _ => panic!("Expected array comprehension"),
667 }
668 }
669 Err(e) => {
670 println!("Parse error: {:?}", e);
671 panic!("Failed to parse array comprehension: {:?}", e);
672 }
673 }
674 }
675
676 #[test]
677 fn test_parse_object_quoted_fields() {
678 let mut lexer = crate::lexer::Lexer::new(r#"{ "name": "test" }"#);
680 let tokens = lexer.tokenize();
681 match tokens {
682 Ok(tokens) => {
683 println!("Tokens generated:");
684 for token in &tokens {
685 println!(" {:?}", token.token);
686 }
687 }
688 Err(e) => {
689 println!("Lexer error: {:?}", e);
690 }
691 }
692
693 let mut parser = Parser::new();
695 let program = parser.parse(r#"{ "name": "test" }"#);
696 match program {
697 Ok(program) => {
698 println!("Parsed successfully");
699 match &program.statements[0] {
700 Stmt::Expr(Expr::Object(fields)) => {
701 println!("Object has {} fields", fields.len());
702 for field in fields {
703 println!("Field: {:?}", field.name);
704 }
705 }
706 _ => println!("Not an object expression"),
707 }
708 }
709 Err(e) => {
710 println!("Parse error: {:?}", e);
711 }
714 }
715 }
716
717 #[test]
718 fn test_parse_conditional() {
719 let mut parser = Parser::new();
720 let program = parser.parse("if true then 1 else 0").unwrap();
721 assert_eq!(program.statements.len(), 1);
722 match &program.statements[0] {
723 Stmt::Expr(Expr::If { cond, then_branch, else_branch: Some(else_branch) }) => {
724 match (&**cond, &**then_branch, &**else_branch) {
725 (Expr::Literal(c), Expr::Literal(t), Expr::Literal(e)) => {
726 assert_eq!(c, &crate::value::JsonnetValue::boolean(true));
727 assert_eq!(t, &crate::value::JsonnetValue::number(1.0));
728 assert_eq!(e, &crate::value::JsonnetValue::number(0.0));
729 }
730 _ => panic!("Expected conditional structure"),
731 }
732 }
733 _ => panic!("Expected if expression"),
734 }
735 }
736}