1use super::lexer::{
2 Token, Keyword, TimeUnit, TokenWithLocation, SourceLocation, SourceMap,
3};
4use super::ast::*;
5use crate::types::Duration;
6use std::collections::HashMap;
7pub struct Parser {
8 tokens: Vec<TokenWithLocation>,
9 source_map: Option<SourceMap>,
10 current: usize,
11 errors: Vec<ParseError>,
12 recovery_points: Vec<usize>,
13}
14#[derive(Debug, Clone)]
15pub struct ParseError {
16 pub message: String,
17 pub location: Option<SourceLocation>,
18 pub token_index: usize,
19 pub expected: Option<String>,
20 pub found: String,
21 pub context: String,
22}
23impl std::fmt::Display for ParseError {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "{}", self.message)?;
26 if let Some(expected) = &self.expected {
27 write!(f, " (expected: {}, found: {})", expected, self.found)?;
28 }
29 if !self.context.is_empty() {
30 write!(f, " in {}", self.context)?;
31 }
32 Ok(())
33 }
34}
35impl std::error::Error for ParseError {}
36impl ParseError {
37 pub fn format_with_source(&self, source: &str, tokens: &[Token]) -> String {
38 let mut line = 1;
39 let mut col = 1;
40 for (i, ch) in source.chars().enumerate() {
41 if i >= self.token_index {
42 break;
43 }
44 if ch == '\n' {
45 line += 1;
46 col = 1;
47 } else {
48 col += 1;
49 }
50 }
51 let lines: Vec<&str> = source.lines().collect();
52 let error_line = if line > 0 && line <= lines.len() {
53 lines[line - 1]
54 } else {
55 ""
56 };
57 let mut result = format!("Error at line {}, column {}:\n", line, col);
58 result.push_str(&format!(" {}\n", error_line));
59 result.push_str(&format!(" {}^\n", " ".repeat(col - 1)));
60 let token_info = if self.token_index < tokens.len() {
61 format!("{:?}", tokens[self.token_index])
62 } else {
63 "<EOF>".to_string()
64 };
65 if let Some(expected) = &self.expected {
66 result
67 .push_str(
68 &format!("Expected {}, found token {}\n", expected, token_info),
69 );
70 } else {
71 result.push_str(&format!("{}\n", self.message));
72 }
73 if !self.context.is_empty() {
74 result.push_str(&format!("Context: {}\n", self.context));
75 }
76 result
77 }
78}
79#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
80#[allow(dead_code)]
81enum Precedence {
82 Lowest = 0,
83 Pipeline = 1,
84 Logical = 2,
85 Equality = 3,
86 Comparison = 4,
87 Addition = 5,
88 Multiplication = 6,
89 Unary = 7,
90 Call = 8,
91 Index = 9,
92 Highest = 10,
93}
94impl Parser {
95 pub fn new(tokens: Vec<Token>) -> Self {
96 let tokens_with_location = tokens
97 .into_iter()
98 .enumerate()
99 .map(|(i, token)| {
100 TokenWithLocation {
101 token,
102 location: SourceLocation {
103 line: 1,
104 column: i + 1,
105 position: i,
106 },
107 }
108 })
109 .collect();
110 Parser {
111 tokens: tokens_with_location,
112 source_map: None,
113 current: 0,
114 errors: Vec::new(),
115 recovery_points: Vec::new(),
116 }
117 }
118 pub fn new_enhanced(tokens: Vec<TokenWithLocation>) -> Self {
119 Parser {
120 tokens,
121 source_map: None,
122 current: 0,
123 errors: Vec::new(),
124 recovery_points: Vec::new(),
125 }
126 }
127 pub fn new_with_source_map(source_map: SourceMap) -> Self {
128 let tokens = source_map.tokens.clone();
129 Parser {
130 tokens,
131 source_map: Some(source_map),
132 current: 0,
133 errors: Vec::new(),
134 recovery_points: Vec::new(),
135 }
136 }
137 fn add_error(&mut self, message: String, expected: Option<String>) {
138 let error = ParseError {
139 message,
140 location: self.current_location(),
141 token_index: self.current,
142 expected,
143 found: format!("{:?}", self.current_token()),
144 context: self.get_enhanced_context(),
145 };
146 self.errors.push(error);
147 }
148 fn get_context(&self) -> String {
149 if self.recovery_points.is_empty() {
150 "top-level".to_string()
151 } else {
152 match self.recovery_points.last() {
153 Some(_) => "inside declaration".to_string(),
154 None => "unknown".to_string(),
155 }
156 }
157 }
158 fn get_enhanced_context(&self) -> String {
159 let basic_context = self.get_context();
160 if let (Some(source_map), Some(location)) = (
161 &self.source_map,
162 &self.current_location(),
163 ) {
164 let source_context = source_map.get_context(location, 2);
165 format!("{} - Source context:\n{}", basic_context, source_context)
166 } else {
167 basic_context
168 }
169 }
170 fn recover_to_next_declaration(&mut self) {
171 while self.current_token() != &Token::Eof {
172 match self.current_token() {
173 Token::Keyword(k) => {
174 match k {
175 Keyword::Agent
176 | Keyword::Workflow
177 | Keyword::Memory
178 | Keyword::Context
179 | Keyword::Crew
180 | Keyword::Project
181 | Keyword::Pipeline
182 | Keyword::Load => {
183 break;
184 }
185 _ => {}
186 }
187 }
188 _ => {}
189 }
190 self.advance();
191 }
192 }
193 #[allow(dead_code)]
194 fn recover_to_closing_brace(&mut self) {
195 let mut brace_depth = 1;
196 while self.current_token() != &Token::Eof && brace_depth > 0 {
197 match self.current_token() {
198 Token::LeftBrace => brace_depth += 1,
199 Token::RightBrace => brace_depth -= 1,
200 _ => {}
201 }
202 if brace_depth > 0 {
203 self.advance();
204 }
205 }
206 }
207 fn current_token(&self) -> &Token {
208 self.tokens
209 .get(self.current)
210 .map(|token_with_loc| &token_with_loc.token)
211 .unwrap_or(&Token::Eof)
212 }
213 fn current_location(&self) -> Option<SourceLocation> {
214 self.tokens
215 .get(self.current)
216 .map(|token_with_loc| token_with_loc.location.clone())
217 }
218 fn peek_token(&self) -> &Token {
219 self.tokens
220 .get(self.current + 1)
221 .map(|token_with_loc| &token_with_loc.token)
222 .unwrap_or(&Token::Eof)
223 }
224 fn parse_enhanced_expression(&mut self) -> Result<Expression, String> {
225 let next_token = self.peek_token().clone();
226 match (self.current_token().clone(), &next_token) {
227 (Token::Identifier(name), Token::Assign) => {
228 self.advance();
229 Ok(Expression::Identifier(name))
230 }
231 (Token::LeftParen, _) => {
232 self.advance();
233 let expr = self.parse_enhanced_expression()?;
234 self.expect(Token::RightParen)?;
235 Ok(expr)
236 }
237 (Token::LeftBracket, _) => {
238 self.advance();
239 let mut elements = Vec::new();
240 while self.current_token() != &Token::RightBracket
241 && self.current_token() != &Token::Eof
242 {
243 self.skip_newlines();
244 if self.current_token() == &Token::RightBracket {
245 break;
246 }
247 elements.push(self.parse_enhanced_expression()?);
248 self.skip_newlines();
249 if self.current_token() == &Token::Comma {
250 self.advance();
251 }
252 }
253 self.expect(Token::RightBracket)?;
254 Ok(Expression::Array(elements))
255 }
256 _ => self.parse_primary_expression(),
257 }
258 }
259 fn advance(&mut self) -> Token {
260 let token = self.current_token().clone();
261 if self.current < self.tokens.len() {
262 self.current += 1;
263 }
264 token
265 }
266 fn expect(&mut self, expected: Token) -> Result<(), String> {
267 let token = self.current_token().clone();
268 if token == expected {
269 self.advance();
270 Ok(())
271 } else {
272 Err(format!("Expected {:?}, found {:?}", expected, token))
273 }
274 }
275 fn expect_identifier(&mut self) -> Result<String, String> {
276 match self.current_token() {
277 Token::Identifier(name) => {
278 let name = name.clone();
279 self.advance();
280 Ok(name)
281 }
282 Token::String(name) => {
283 let name = name.clone();
284 self.advance();
285 Ok(name)
286 }
287 _ => Err(format!("Expected identifier, found {:?}", self.current_token())),
288 }
289 }
290 fn skip_newlines(&mut self) {
291 while self.current_token() == &Token::Newline {
292 self.advance();
293 }
294 }
295 pub fn parse(&mut self) -> Result<HelixAst, String> {
296 let mut ast = HelixAst::new();
297 while self.current_token() != &Token::Eof {
298 self.skip_newlines();
299 let current_token = self.current_token().clone();
300 match current_token {
301 Token::Keyword(keyword) => {
302 self.recovery_points.push(self.current);
303 match self.parse_declaration(keyword.clone()) {
304 Ok(decl) => {
305 ast.add_declaration(decl);
306 self.recovery_points.pop();
307 }
308 Err(err) => {
309 self.add_error(
310 err.clone(),
311 Some(format!("valid {:?} declaration", keyword)),
312 );
313 self.recover_to_next_declaration();
314 self.recovery_points.pop();
315 }
316 }
317 }
318 Token::Identifier(section_name) => {
319 self.recovery_points.push(self.current);
321 self.advance(); self.expect(Token::LeftBrace)?;
323 let properties = self.parse_properties()?;
324 self.expect(Token::RightBrace)?;
325 ast.add_declaration(Declaration::Section(SectionDecl {
326 name: section_name.clone(),
327 properties,
328 }));
329 self.recovery_points.pop();
330 }
331 Token::Eof => break,
332 _ => {
333 self.add_error(
334 format!("Unexpected token: {:?}", current_token),
335 Some("declaration keyword or identifier".to_string()),
336 );
337 self.recover_to_next_declaration();
338 }
339 }
340 self.skip_newlines();
341 }
342 if !self.errors.is_empty() {
343 let error_summary = self
344 .errors
345 .iter()
346 .map(|e| format!("{} at token {}", e.message, e.token_index))
347 .collect::<Vec<_>>()
348 .join("; ");
349 Err(format!("Parse errors: {}", error_summary))
350 } else {
351 Ok(ast)
352 }
353 }
354 fn parse_declaration(&mut self, keyword: Keyword) -> Result<Declaration, String> {
355 match keyword {
356 Keyword::Project => {
357 self.advance();
358 let name = self.expect_identifier()?;
359 self.expect(Token::LeftBrace)?;
360 let properties = self.parse_properties()?;
361 self.expect(Token::RightBrace)?;
362 Ok(Declaration::Project(ProjectDecl { name, properties }))
363 }
364 Keyword::Agent => {
365 self.advance();
366 let name = self.expect_identifier()?;
367 self.expect(Token::LeftBrace)?;
368 let mut properties = HashMap::new();
369 let mut capabilities = None;
370 let mut backstory = None;
371 let tools = None;
372 while self.current_token() != &Token::RightBrace {
373 self.skip_newlines();
374 match self.current_token() {
375 Token::Keyword(Keyword::Capabilities) => {
376 self.advance();
377 capabilities = Some(self.parse_string_array()?);
378 }
379 Token::Keyword(Keyword::Backstory) => {
380 self.advance();
381 backstory = Some(self.parse_backstory_block()?);
382 }
383 Token::Identifier(key) => {
384 let key = key.clone();
385 self.advance();
386 self.expect(Token::Assign)?;
387 let value = self.parse_expression()?;
388 properties.insert(key, value);
389 }
390 Token::Keyword(keyword) => {
391 match keyword {
392 Keyword::Capabilities | Keyword::Backstory => {
393 return Err(
394 format!(
395 "Unexpected token in agent: {:?}", self.current_token()
396 ),
397 );
398 }
399 _ => {
400 let key = format!("{:?}", keyword).to_lowercase();
401 self.advance();
402 self.expect(Token::Assign)?;
403 let value = self.parse_expression()?;
404 properties.insert(key, value);
405 }
406 }
407 }
408 Token::RightBrace => break,
409 _ => {
410 return Err(
411 format!(
412 "Unexpected token in agent: {:?}", self.current_token()
413 ),
414 );
415 }
416 }
417 self.skip_newlines();
418 }
419 self.expect(Token::RightBrace)?;
420 Ok(
421 Declaration::Agent(AgentDecl {
422 name,
423 properties,
424 capabilities,
425 backstory,
426 tools,
427 }),
428 )
429 }
430 Keyword::Workflow => {
431 self.advance();
432 let name = self.expect_identifier()?;
433 self.expect(Token::LeftBrace)?;
434 let mut trigger = None;
435 let mut steps = Vec::new();
436 let mut pipeline = None;
437 let mut properties = HashMap::new();
438 while self.current_token() != &Token::RightBrace {
439 self.skip_newlines();
440 match self.current_token() {
441 Token::Keyword(Keyword::Trigger) => {
442 self.advance();
443 self.expect(Token::Assign)?;
444 trigger = Some(self.parse_trigger_config()?);
445 }
446 Token::Keyword(Keyword::Step) => {
447 steps.push(self.parse_step()?);
448 }
449 Token::Keyword(Keyword::Pipeline) => {
450 self.advance();
451 pipeline = Some(self.parse_pipeline_block()?);
452 }
453 Token::Keyword(Keyword::Timeout) => {
454 self.advance();
455 self.expect(Token::Assign)?;
456 let timeout_value = self.parse_expression()?;
457 properties.insert("timeout".to_string(), timeout_value);
458 }
459 Token::Identifier(key) => {
460 let key = key.clone();
461 self.advance();
462 self.expect(Token::Assign)?;
463 let value = self.parse_expression()?;
464 properties.insert(key, value);
465 }
466 Token::RightBrace => break,
467 _ => {
468 return Err(
469 format!(
470 "Unexpected token in workflow: {:?}", self.current_token()
471 ),
472 );
473 }
474 }
475 self.skip_newlines();
476 }
477 self.expect(Token::RightBrace)?;
478 Ok(
479 Declaration::Workflow(WorkflowDecl {
480 name,
481 trigger,
482 steps,
483 pipeline,
484 properties,
485 }),
486 )
487 }
488 Keyword::Memory => {
489 self.advance();
490 self.expect(Token::LeftBrace)?;
491 let mut provider = String::new();
492 let mut connection = String::new();
493 let mut embeddings = None;
494 let mut properties = HashMap::new();
495 while self.current_token() != &Token::RightBrace {
496 self.skip_newlines();
497 match self.current_token() {
498 Token::Keyword(Keyword::Embeddings) => {
499 self.advance();
500 embeddings = Some(self.parse_embeddings_block()?);
501 }
502 Token::Identifier(key) => {
503 let key = key.clone();
504 self.advance();
505 self.expect(Token::Assign)?;
506 let value = self.parse_expression()?;
507 match key.as_str() {
508 "provider" => {
509 provider = value.as_string().unwrap_or_default();
510 }
511 "connection" => {
512 connection = value.as_string().unwrap_or_default();
513 }
514 _ => {
515 properties.insert(key, value);
516 }
517 }
518 }
519 Token::RightBrace => break,
520 _ => {
521 return Err(
522 format!(
523 "Unexpected token in memory: {:?}", self.current_token()
524 ),
525 );
526 }
527 }
528 self.skip_newlines();
529 }
530 self.expect(Token::RightBrace)?;
531 Ok(
532 Declaration::Memory(MemoryDecl {
533 provider,
534 connection,
535 embeddings,
536 properties,
537 }),
538 )
539 }
540 Keyword::Context => {
541 self.advance();
542 let name = self.expect_identifier()?;
543 self.expect(Token::LeftBrace)?;
544 let mut environment = String::new();
545 let mut secrets = None;
546 let mut variables = None;
547 let mut properties = HashMap::new();
548 while self.current_token() != &Token::RightBrace {
549 self.skip_newlines();
550 match self.current_token() {
551 Token::Keyword(Keyword::Secrets) => {
552 self.advance();
553 secrets = Some(self.parse_secrets_block()?);
554 }
555 Token::Keyword(Keyword::Variables) => {
556 self.advance();
557 variables = Some(self.parse_variables_block()?);
558 }
559 Token::Identifier(key) => {
560 let key = key.clone();
561 self.advance();
562 self.expect(Token::Assign)?;
563 let value = self.parse_expression()?;
564 if key == "environment" {
565 environment = value.as_string().unwrap_or_default();
566 } else {
567 properties.insert(key, value);
568 }
569 }
570 Token::RightBrace => break,
571 _ => {
572 return Err(
573 format!(
574 "Unexpected token in context: {:?}", self.current_token()
575 ),
576 );
577 }
578 }
579 self.skip_newlines();
580 }
581 self.expect(Token::RightBrace)?;
582 Ok(
583 Declaration::Context(ContextDecl {
584 name,
585 environment,
586 secrets,
587 variables,
588 properties,
589 }),
590 )
591 }
592 Keyword::Crew => {
593 self.advance();
594 let name = self.expect_identifier()?;
595 self.expect(Token::LeftBrace)?;
596 let mut agents = Vec::new();
597 let mut process_type = None;
598 let mut properties = HashMap::new();
599 while self.current_token() != &Token::RightBrace {
600 self.skip_newlines();
601 match self.current_token() {
602 Token::Identifier(key) => {
603 let key = key.clone();
604 self.advance();
605 if key == "agents" {
606 agents = self.parse_string_array()?;
607 } else {
608 self.expect(Token::Assign)?;
609 let value = self.parse_expression()?;
610 if key == "process" {
611 process_type = value.as_string();
612 } else {
613 properties.insert(key, value);
614 }
615 }
616 }
617 Token::RightBrace => break,
618 _ => {
619 return Err(
620 format!(
621 "Unexpected token in crew: {:?}", self.current_token()
622 ),
623 );
624 }
625 }
626 self.skip_newlines();
627 }
628 self.expect(Token::RightBrace)?;
629 Ok(
630 Declaration::Crew(CrewDecl {
631 name,
632 agents,
633 process_type,
634 properties,
635 }),
636 )
637 }
638 Keyword::Pipeline => {
639 self.advance();
640 self.expect(Token::LeftBrace)?;
641 let pipeline = self.parse_pipeline_block()?;
642 self.expect(Token::RightBrace)?;
643 Ok(Declaration::Pipeline(pipeline))
644 }
645 Keyword::Load => {
646 self.advance();
647 let file_name = self.expect_identifier()?;
648 self.expect(Token::LeftBrace)?;
649 let properties = self.parse_properties()?;
650 self.expect(Token::RightBrace)?;
651 Ok(Declaration::Load(LoadDecl { file_name, properties }))
652 }
653 _ => Err(format!("Unexpected keyword: {:?}", keyword)),
654 }
655 }
656 fn parse_step(&mut self) -> Result<StepDecl, String> {
657 self.advance();
658 let name = self.expect_identifier()?;
659 self.expect(Token::LeftBrace)?;
660 let mut agent = None;
661 let mut crew = None;
662 let mut task = None;
663 let mut properties = HashMap::new();
664 while self.current_token() != &Token::RightBrace {
665 self.skip_newlines();
666 match self.current_token() {
667 Token::Keyword(Keyword::Timeout) => {
668 self.advance();
669 self.expect(Token::Assign)?;
670 let timeout_value = self.parse_expression()?;
671 properties.insert("timeout".to_string(), timeout_value);
672 }
673 Token::Identifier(key) => {
674 let key = key.clone();
675 self.advance();
676 match key.as_str() {
677 "agent" => {
678 self.expect(Token::Assign)?;
679 agent = self.parse_expression()?.as_string();
680 }
681 "crew" => {
682 self.expect(Token::Assign)?;
683 if self.current_token() == &Token::LeftBracket {
684 crew = Some(self.parse_string_array()?);
685 }
686 }
687 "task" => {
688 self.expect(Token::Assign)?;
689 task = self.parse_expression()?.as_string();
690 }
691 "retry" => {
692 let retry_config = self.parse_retry_block()?;
693 properties
694 .insert(
695 "retry".to_string(),
696 Expression::Object(retry_config),
697 );
698 }
699 _ => {
700 self.expect(Token::Assign)?;
701 let value = self.parse_expression()?;
702 properties.insert(key, value);
703 }
704 }
705 }
706 Token::Keyword(keyword) => {
707 let key = format!("{:?}", keyword).to_lowercase();
708 self.advance();
709 self.expect(Token::Assign)?;
710 match key.as_str() {
711 "agent" => {
712 agent = self.parse_expression()?.as_string();
713 }
714 _ => {
715 let value = self.parse_expression()?;
716 properties.insert(key, value);
717 }
718 }
719 }
720 Token::RightBrace => break,
721 _ => {
722 return Err(
723 format!("Unexpected token in step: {:?}", self.current_token()),
724 );
725 }
726 }
727 self.skip_newlines();
728 }
729 self.expect(Token::RightBrace)?;
730 Ok(StepDecl {
731 name,
732 agent,
733 crew,
734 task,
735 properties,
736 })
737 }
738 fn parse_retry_block(&mut self) -> Result<HashMap<String, Expression>, String> {
739 self.expect(Token::LeftBrace)?;
740 let mut retry_config = HashMap::new();
741 while self.current_token() != &Token::RightBrace {
742 self.skip_newlines();
743 if self.current_token() == &Token::RightBrace {
744 break;
745 }
746 let key = self.expect_identifier()?;
747 if self.peek_token() != &Token::Assign
748 && self.current_token() != &Token::Assign
749 {
750 return Err(
751 format!(
752 "Expected '=' after property key '{}', found {:?}", key, self
753 .current_token()
754 ),
755 );
756 }
757 self.expect(Token::Assign)?;
758 let value = self.parse_expression()?;
759 retry_config.insert(key, value);
760 self.skip_newlines();
761 }
762 self.expect(Token::RightBrace)?;
763 Ok(retry_config)
764 }
765 fn parse_trigger_config(&mut self) -> Result<Expression, String> {
766 if self.current_token() == &Token::LeftBrace {
767 self.advance();
768 let trigger_obj = self.parse_object()?;
769 Ok(Expression::Object(trigger_obj))
770 } else {
771 self.parse_expression()
772 }
773 }
774 fn parse_expression(&mut self) -> Result<Expression, String> {
775 match self.current_token() {
776 Token::LeftParen | Token::LeftBracket => self.parse_enhanced_expression(),
777 _ => self.parse_expression_with_precedence(Precedence::Lowest),
778 }
779 }
780 fn parse_expression_with_precedence(
781 &mut self,
782 min_precedence: Precedence,
783 ) -> Result<Expression, String> {
784 let mut left = self.parse_primary_expression()?;
785 while !self.is_at_end() {
786 let precedence = self.get_token_precedence(self.current_token());
787 if precedence < min_precedence {
788 break;
789 }
790 match self.current_token() {
791 Token::Arrow => {
792 self.advance();
793 let mut pipeline = vec![];
794 if let Expression::Identifier(id) = left {
795 pipeline.push(id);
796 } else if let Expression::Pipeline(mut p) = left {
797 pipeline.append(&mut p);
798 } else {
799 return Err(format!("Invalid left side of pipeline: {:?}", left));
800 }
801 let right = self
802 .parse_expression_with_precedence(Precedence::Pipeline)?;
803 if let Expression::Identifier(id) = right {
804 pipeline.push(id);
805 } else if let Expression::Pipeline(mut p) = right {
806 pipeline.append(&mut p);
807 } else {
808 return Err(
809 format!("Invalid right side of pipeline: {:?}", right),
810 );
811 }
812 left = Expression::Pipeline(pipeline);
813 }
814 _ => {
815 break;
816 }
817 }
818 }
819 Ok(left)
820 }
821 fn parse_primary_expression(&mut self) -> Result<Expression, String> {
822 match self.current_token() {
823 Token::String(s) => {
824 let s = s.clone();
825 self.advance();
826 Ok(Expression::String(s))
827 }
828 Token::Number(n) => {
829 let n = *n;
830 self.advance();
831 Ok(Expression::Number(n))
832 }
833 Token::Bool(b) => {
834 let b = *b;
835 self.advance();
836 Ok(Expression::Bool(b))
837 }
838 Token::Duration(value, unit) => {
839 let duration = Duration {
840 value: *value,
841 unit: match unit {
842 TimeUnit::Seconds => crate::types::TimeUnit::Seconds,
843 TimeUnit::Minutes => crate::types::TimeUnit::Minutes,
844 TimeUnit::Hours => crate::types::TimeUnit::Hours,
845 TimeUnit::Days => crate::types::TimeUnit::Days,
846 },
847 };
848 self.advance();
849 Ok(Expression::Duration(duration))
850 }
851 Token::Variable(v) => {
852 let v = v.clone();
853 self.advance();
854 Ok(Expression::Variable(v))
855 }
856 Token::Reference(r) => {
857 let r = r.clone();
858 self.advance();
859 if self.current_token() == &Token::LeftBracket {
860 self.advance();
861 let key = self.expect_identifier()?;
862 self.expect(Token::RightBracket)?;
863 Ok(Expression::IndexedReference(r, key))
864 } else {
865 Ok(Expression::Reference(r))
866 }
867 }
868 Token::Identifier(i) => {
869 let i = i.clone();
870 self.advance();
871 Ok(Expression::Identifier(i))
872 }
873 Token::LeftBracket => {
874 self.advance();
875 let array = self.parse_array()?;
876 Ok(Expression::Array(array))
877 }
878 Token::LeftBrace => {
879 self.advance();
880 let object = self.parse_object()?;
881 Ok(Expression::Object(object))
882 }
883 Token::LeftParen => {
884 self.advance();
885 let expr = self.parse_expression()?;
886 self.expect(Token::RightParen)?;
887 Ok(expr)
888 }
889 _ => {
890 Err(
891 format!("Unexpected token in expression: {:?}", self.current_token()),
892 )
893 }
894 }
895 }
896 fn get_token_precedence(&self, token: &Token) -> Precedence {
897 match token {
898 Token::Arrow => Precedence::Pipeline,
899 _ => Precedence::Lowest,
900 }
901 }
902 fn is_at_end(&self) -> bool {
903 self.current_token() == &Token::Eof
904 }
905 fn parse_array(&mut self) -> Result<Vec<Expression>, String> {
906 let mut elements = Vec::new();
907 while self.current_token() != &Token::RightBracket {
908 self.skip_newlines();
909 if self.current_token() == &Token::RightBracket {
910 break;
911 }
912 elements.push(self.parse_expression()?);
913 if self.current_token() == &Token::Comma {
914 self.advance();
915 }
916 self.skip_newlines();
917 }
918 self.expect(Token::RightBracket)?;
919 Ok(elements)
920 }
921 fn parse_object(&mut self) -> Result<HashMap<String, Expression>, String> {
922 let mut object = HashMap::new();
923 while self.current_token() != &Token::RightBrace {
924 self.skip_newlines();
925 if self.current_token() == &Token::RightBrace {
926 break;
927 }
928 let key = self.expect_identifier()?;
929 if self.peek_token() != &Token::Assign
930 && self.current_token() != &Token::Assign
931 {
932 return Err(
933 format!(
934 "Expected '=' after property key '{}', found {:?}", key, self
935 .current_token()
936 ),
937 );
938 }
939 self.expect(Token::Assign)?;
940 let value = self.parse_expression()?;
941 object.insert(key, value);
942 if self.current_token() == &Token::Comma {
943 self.advance();
944 }
945 self.skip_newlines();
946 }
947 self.expect(Token::RightBrace)?;
948 Ok(object)
949 }
950 fn parse_string_array(&mut self) -> Result<Vec<String>, String> {
951 self.expect(Token::LeftBracket)?;
952 let mut items = Vec::new();
953 while self.current_token() != &Token::RightBracket {
954 self.skip_newlines();
955 if self.current_token() == &Token::RightBracket {
956 break;
957 }
958 items.push(self.expect_identifier()?);
959 if self.current_token() == &Token::Comma {
960 self.advance();
961 }
962 self.skip_newlines();
963 }
964 self.expect(Token::RightBracket)?;
965 Ok(items)
966 }
967 fn parse_properties(&mut self) -> Result<HashMap<String, Expression>, String> {
968 let mut properties = HashMap::new();
969 while self.current_token() != &Token::RightBrace {
970 self.skip_newlines();
971 if self.current_token() == &Token::RightBrace {
972 break;
973 }
974 let key = self.expect_identifier()?;
975 if self.peek_token() != &Token::Assign
976 && self.current_token() != &Token::Assign
977 {
978 return Err(
979 format!(
980 "Expected '=' after property key '{}', found {:?}", key, self
981 .current_token()
982 ),
983 );
984 }
985 self.expect(Token::Assign)?;
986 let value = self.parse_expression()?;
987 properties.insert(key, value);
988 self.skip_newlines();
989 }
990 Ok(properties)
991 }
992 fn parse_backstory_block(&mut self) -> Result<BackstoryBlock, String> {
993 self.expect(Token::LeftBrace)?;
994 let mut lines = Vec::new();
995 while self.current_token() != &Token::RightBrace {
996 self.skip_newlines();
997 match self.current_token() {
998 Token::Identifier(text) | Token::String(text) => {
999 lines.push(text.clone());
1000 self.advance();
1001 }
1002 Token::RightBrace => break,
1003 _ => {
1004 self.advance();
1005 }
1006 }
1007 }
1008 self.expect(Token::RightBrace)?;
1009 Ok(BackstoryBlock { lines })
1010 }
1011 fn parse_pipeline_block(&mut self) -> Result<PipelineDecl, String> {
1012 self.expect(Token::LeftBrace)?;
1013 let mut flow = Vec::new();
1014 while self.current_token() != &Token::RightBrace {
1015 self.skip_newlines();
1016 if let Token::Identifier(step) = self.current_token() {
1017 flow.push(PipelineNode::Step(step.clone()));
1018 self.advance();
1019 if self.current_token() == &Token::Arrow {
1020 self.advance();
1021 }
1022 } else if self.current_token() == &Token::RightBrace {
1023 break;
1024 } else {
1025 self.advance();
1026 }
1027 self.skip_newlines();
1028 }
1029 self.expect(Token::RightBrace)?;
1030 Ok(PipelineDecl { flow })
1031 }
1032 fn parse_embeddings_block(&mut self) -> Result<EmbeddingsDecl, String> {
1033 self.expect(Token::LeftBrace)?;
1034 let mut model = String::new();
1035 let mut dimensions = 0;
1036 let mut properties = HashMap::new();
1037 while self.current_token() != &Token::RightBrace {
1038 self.skip_newlines();
1039 let key = self.expect_identifier()?;
1040 if self.peek_token() != &Token::Assign
1041 && self.current_token() != &Token::Assign
1042 {
1043 return Err(
1044 format!(
1045 "Expected '=' after property key '{}', found {:?}", key, self
1046 .current_token()
1047 ),
1048 );
1049 }
1050 self.expect(Token::Assign)?;
1051 let value = self.parse_expression()?;
1052 match key.as_str() {
1053 "model" => model = value.as_string().unwrap_or_default(),
1054 "dimensions" => dimensions = value.as_number().unwrap_or(0.0) as u32,
1055 _ => {
1056 properties.insert(key, value);
1057 }
1058 }
1059 self.skip_newlines();
1060 }
1061 self.expect(Token::RightBrace)?;
1062 Ok(EmbeddingsDecl {
1063 model,
1064 dimensions,
1065 properties,
1066 })
1067 }
1068 fn parse_variables_block(&mut self) -> Result<HashMap<String, Expression>, String> {
1069 self.expect(Token::LeftBrace)?;
1070 let mut variables = HashMap::new();
1071 while self.current_token() != &Token::RightBrace {
1072 self.skip_newlines();
1073 if self.current_token() == &Token::RightBrace {
1074 break;
1075 }
1076 let key = match self.current_token().clone() {
1077 Token::Identifier(id) => {
1078 self.advance();
1079 id.clone()
1080 }
1081 Token::Keyword(kw) => {
1082 self.advance();
1083 format!("{:?}", kw).to_lowercase()
1084 }
1085 _ => {
1086 return Err(
1087 format!(
1088 "Expected identifier or keyword for variable name, found {:?}",
1089 self.current_token()
1090 ),
1091 );
1092 }
1093 };
1094 self.expect(Token::Assign)?;
1095 let value = self.parse_expression()?;
1096 variables.insert(key, value);
1097 self.skip_newlines();
1098 }
1099 self.expect(Token::RightBrace)?;
1100 Ok(variables)
1101 }
1102 fn parse_secrets_block(&mut self) -> Result<HashMap<String, SecretRef>, String> {
1103 self.expect(Token::LeftBrace)?;
1104 let mut secrets = HashMap::new();
1105 while self.current_token() != &Token::RightBrace {
1106 self.skip_newlines();
1107 let key = self.expect_identifier()?;
1108 self.expect(Token::Assign)?;
1109 let secret_ref = match self.current_token() {
1110 Token::Variable(var) => {
1111 let var = var.clone();
1112 self.advance();
1113 SecretRef::Environment(var)
1114 }
1115 Token::String(path) if path.starts_with("vault:") => {
1116 let path = path.clone();
1117 self.advance();
1118 SecretRef::Vault(path.trim_start_matches("vault:").to_string())
1119 }
1120 Token::String(path) if path.starts_with("file:") => {
1121 let path = path.clone();
1122 self.advance();
1123 SecretRef::File(path.trim_start_matches("file:").to_string())
1124 }
1125 _ => {
1126 return Err(
1127 format!("Invalid secret reference: {:?}", self.current_token()),
1128 );
1129 }
1130 };
1131 secrets.insert(key, secret_ref);
1132 self.skip_newlines();
1133 }
1134 self.expect(Token::RightBrace)?;
1135 Ok(secrets)
1136 }
1137}
1138pub fn parse(tokens: Vec<Token>) -> Result<HelixAst, ParseError> {
1139 let mut parser = Parser::new(tokens);
1140 parser
1141 .parse()
1142 .map_err(|msg| ParseError {
1143 message: msg,
1144 location: None,
1145 token_index: 0,
1146 expected: None,
1147 found: String::new(),
1148 context: String::new(),
1149 })
1150}