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 if let Token::Keyword(keyword) = self.current_token().clone() {
300 self.recovery_points.push(self.current);
301 match self.parse_declaration(keyword.clone()) {
302 Ok(decl) => {
303 ast.add_declaration(decl);
304 self.recovery_points.pop();
305 }
306 Err(err) => {
307 self.add_error(
308 err.clone(),
309 Some(format!("valid {:?} declaration", keyword)),
310 );
311 self.recover_to_next_declaration();
312 self.recovery_points.pop();
313 }
314 }
315 } else {
316 match self.current_token() {
317 Token::Eof => break,
318 _ => {
319 self.add_error(
320 format!("Unexpected token: {:?}", self.current_token()),
321 Some("declaration keyword".to_string()),
322 );
323 self.recover_to_next_declaration();
324 }
325 }
326 }
327 self.skip_newlines();
328 }
329 if !self.errors.is_empty() {
330 let error_summary = self
331 .errors
332 .iter()
333 .map(|e| format!("{} at token {}", e.message, e.token_index))
334 .collect::<Vec<_>>()
335 .join("; ");
336 Err(format!("Parse errors: {}", error_summary))
337 } else {
338 Ok(ast)
339 }
340 }
341 fn parse_declaration(&mut self, keyword: Keyword) -> Result<Declaration, String> {
342 match keyword {
343 Keyword::Project => {
344 self.advance();
345 let name = self.expect_identifier()?;
346 self.expect(Token::LeftBrace)?;
347 let properties = self.parse_properties()?;
348 self.expect(Token::RightBrace)?;
349 Ok(Declaration::Project(ProjectDecl { name, properties }))
350 }
351 Keyword::Agent => {
352 self.advance();
353 let name = self.expect_identifier()?;
354 self.expect(Token::LeftBrace)?;
355 let mut properties = HashMap::new();
356 let mut capabilities = None;
357 let mut backstory = None;
358 let tools = None;
359 while self.current_token() != &Token::RightBrace {
360 self.skip_newlines();
361 match self.current_token() {
362 Token::Keyword(Keyword::Capabilities) => {
363 self.advance();
364 capabilities = Some(self.parse_string_array()?);
365 }
366 Token::Keyword(Keyword::Backstory) => {
367 self.advance();
368 backstory = Some(self.parse_backstory_block()?);
369 }
370 Token::Identifier(key) => {
371 let key = key.clone();
372 self.advance();
373 self.expect(Token::Assign)?;
374 let value = self.parse_expression()?;
375 properties.insert(key, value);
376 }
377 Token::Keyword(keyword) => {
378 match keyword {
379 Keyword::Capabilities | Keyword::Backstory => {
380 return Err(
381 format!(
382 "Unexpected token in agent: {:?}", self.current_token()
383 ),
384 );
385 }
386 _ => {
387 let key = format!("{:?}", keyword).to_lowercase();
388 self.advance();
389 self.expect(Token::Assign)?;
390 let value = self.parse_expression()?;
391 properties.insert(key, value);
392 }
393 }
394 }
395 Token::RightBrace => break,
396 _ => {
397 return Err(
398 format!(
399 "Unexpected token in agent: {:?}", self.current_token()
400 ),
401 );
402 }
403 }
404 self.skip_newlines();
405 }
406 self.expect(Token::RightBrace)?;
407 Ok(
408 Declaration::Agent(AgentDecl {
409 name,
410 properties,
411 capabilities,
412 backstory,
413 tools,
414 }),
415 )
416 }
417 Keyword::Workflow => {
418 self.advance();
419 let name = self.expect_identifier()?;
420 self.expect(Token::LeftBrace)?;
421 let mut trigger = None;
422 let mut steps = Vec::new();
423 let mut pipeline = None;
424 let mut properties = HashMap::new();
425 while self.current_token() != &Token::RightBrace {
426 self.skip_newlines();
427 match self.current_token() {
428 Token::Keyword(Keyword::Trigger) => {
429 self.advance();
430 self.expect(Token::Assign)?;
431 trigger = Some(self.parse_trigger_config()?);
432 }
433 Token::Keyword(Keyword::Step) => {
434 steps.push(self.parse_step()?);
435 }
436 Token::Keyword(Keyword::Pipeline) => {
437 self.advance();
438 pipeline = Some(self.parse_pipeline_block()?);
439 }
440 Token::Keyword(Keyword::Timeout) => {
441 self.advance();
442 self.expect(Token::Assign)?;
443 let timeout_value = self.parse_expression()?;
444 properties.insert("timeout".to_string(), timeout_value);
445 }
446 Token::Identifier(key) => {
447 let key = key.clone();
448 self.advance();
449 self.expect(Token::Assign)?;
450 let value = self.parse_expression()?;
451 properties.insert(key, value);
452 }
453 Token::RightBrace => break,
454 _ => {
455 return Err(
456 format!(
457 "Unexpected token in workflow: {:?}", self.current_token()
458 ),
459 );
460 }
461 }
462 self.skip_newlines();
463 }
464 self.expect(Token::RightBrace)?;
465 Ok(
466 Declaration::Workflow(WorkflowDecl {
467 name,
468 trigger,
469 steps,
470 pipeline,
471 properties,
472 }),
473 )
474 }
475 Keyword::Memory => {
476 self.advance();
477 self.expect(Token::LeftBrace)?;
478 let mut provider = String::new();
479 let mut connection = String::new();
480 let mut embeddings = None;
481 let mut properties = HashMap::new();
482 while self.current_token() != &Token::RightBrace {
483 self.skip_newlines();
484 match self.current_token() {
485 Token::Keyword(Keyword::Embeddings) => {
486 self.advance();
487 embeddings = Some(self.parse_embeddings_block()?);
488 }
489 Token::Identifier(key) => {
490 let key = key.clone();
491 self.advance();
492 self.expect(Token::Assign)?;
493 let value = self.parse_expression()?;
494 match key.as_str() {
495 "provider" => {
496 provider = value.as_string().unwrap_or_default();
497 }
498 "connection" => {
499 connection = value.as_string().unwrap_or_default();
500 }
501 _ => {
502 properties.insert(key, value);
503 }
504 }
505 }
506 Token::RightBrace => break,
507 _ => {
508 return Err(
509 format!(
510 "Unexpected token in memory: {:?}", self.current_token()
511 ),
512 );
513 }
514 }
515 self.skip_newlines();
516 }
517 self.expect(Token::RightBrace)?;
518 Ok(
519 Declaration::Memory(MemoryDecl {
520 provider,
521 connection,
522 embeddings,
523 properties,
524 }),
525 )
526 }
527 Keyword::Context => {
528 self.advance();
529 let name = self.expect_identifier()?;
530 self.expect(Token::LeftBrace)?;
531 let mut environment = String::new();
532 let mut secrets = None;
533 let mut variables = None;
534 let mut properties = HashMap::new();
535 while self.current_token() != &Token::RightBrace {
536 self.skip_newlines();
537 match self.current_token() {
538 Token::Keyword(Keyword::Secrets) => {
539 self.advance();
540 secrets = Some(self.parse_secrets_block()?);
541 }
542 Token::Keyword(Keyword::Variables) => {
543 self.advance();
544 variables = Some(self.parse_variables_block()?);
545 }
546 Token::Identifier(key) => {
547 let key = key.clone();
548 self.advance();
549 self.expect(Token::Assign)?;
550 let value = self.parse_expression()?;
551 if key == "environment" {
552 environment = value.as_string().unwrap_or_default();
553 } else {
554 properties.insert(key, value);
555 }
556 }
557 Token::RightBrace => break,
558 _ => {
559 return Err(
560 format!(
561 "Unexpected token in context: {:?}", self.current_token()
562 ),
563 );
564 }
565 }
566 self.skip_newlines();
567 }
568 self.expect(Token::RightBrace)?;
569 Ok(
570 Declaration::Context(ContextDecl {
571 name,
572 environment,
573 secrets,
574 variables,
575 properties,
576 }),
577 )
578 }
579 Keyword::Crew => {
580 self.advance();
581 let name = self.expect_identifier()?;
582 self.expect(Token::LeftBrace)?;
583 let mut agents = Vec::new();
584 let mut process_type = None;
585 let mut properties = HashMap::new();
586 while self.current_token() != &Token::RightBrace {
587 self.skip_newlines();
588 match self.current_token() {
589 Token::Identifier(key) => {
590 let key = key.clone();
591 self.advance();
592 if key == "agents" {
593 agents = self.parse_string_array()?;
594 } else {
595 self.expect(Token::Assign)?;
596 let value = self.parse_expression()?;
597 if key == "process" {
598 process_type = value.as_string();
599 } else {
600 properties.insert(key, value);
601 }
602 }
603 }
604 Token::RightBrace => break,
605 _ => {
606 return Err(
607 format!(
608 "Unexpected token in crew: {:?}", self.current_token()
609 ),
610 );
611 }
612 }
613 self.skip_newlines();
614 }
615 self.expect(Token::RightBrace)?;
616 Ok(
617 Declaration::Crew(CrewDecl {
618 name,
619 agents,
620 process_type,
621 properties,
622 }),
623 )
624 }
625 Keyword::Pipeline => {
626 self.advance();
627 self.expect(Token::LeftBrace)?;
628 let pipeline = self.parse_pipeline_block()?;
629 self.expect(Token::RightBrace)?;
630 Ok(Declaration::Pipeline(pipeline))
631 }
632 Keyword::Load => {
633 self.advance();
634 let file_name = self.expect_identifier()?;
635 self.expect(Token::LeftBrace)?;
636 let properties = self.parse_properties()?;
637 self.expect(Token::RightBrace)?;
638 Ok(Declaration::Load(LoadDecl { file_name, properties }))
639 }
640 _ => Err(format!("Unexpected keyword: {:?}", keyword)),
641 }
642 }
643 fn parse_step(&mut self) -> Result<StepDecl, String> {
644 self.advance();
645 let name = self.expect_identifier()?;
646 self.expect(Token::LeftBrace)?;
647 let mut agent = None;
648 let mut crew = None;
649 let mut task = None;
650 let mut properties = HashMap::new();
651 while self.current_token() != &Token::RightBrace {
652 self.skip_newlines();
653 match self.current_token() {
654 Token::Keyword(Keyword::Timeout) => {
655 self.advance();
656 self.expect(Token::Assign)?;
657 let timeout_value = self.parse_expression()?;
658 properties.insert("timeout".to_string(), timeout_value);
659 }
660 Token::Identifier(key) => {
661 let key = key.clone();
662 self.advance();
663 match key.as_str() {
664 "agent" => {
665 self.expect(Token::Assign)?;
666 agent = self.parse_expression()?.as_string();
667 }
668 "crew" => {
669 self.expect(Token::Assign)?;
670 if self.current_token() == &Token::LeftBracket {
671 crew = Some(self.parse_string_array()?);
672 }
673 }
674 "task" => {
675 self.expect(Token::Assign)?;
676 task = self.parse_expression()?.as_string();
677 }
678 "retry" => {
679 let retry_config = self.parse_retry_block()?;
680 properties
681 .insert(
682 "retry".to_string(),
683 Expression::Object(retry_config),
684 );
685 }
686 _ => {
687 self.expect(Token::Assign)?;
688 let value = self.parse_expression()?;
689 properties.insert(key, value);
690 }
691 }
692 }
693 Token::Keyword(keyword) => {
694 let key = format!("{:?}", keyword).to_lowercase();
695 self.advance();
696 self.expect(Token::Assign)?;
697 match key.as_str() {
698 "agent" => {
699 agent = self.parse_expression()?.as_string();
700 }
701 _ => {
702 let value = self.parse_expression()?;
703 properties.insert(key, value);
704 }
705 }
706 }
707 Token::RightBrace => break,
708 _ => {
709 return Err(
710 format!("Unexpected token in step: {:?}", self.current_token()),
711 );
712 }
713 }
714 self.skip_newlines();
715 }
716 self.expect(Token::RightBrace)?;
717 Ok(StepDecl {
718 name,
719 agent,
720 crew,
721 task,
722 properties,
723 })
724 }
725 fn parse_retry_block(&mut self) -> Result<HashMap<String, Expression>, String> {
726 self.expect(Token::LeftBrace)?;
727 let mut retry_config = HashMap::new();
728 while self.current_token() != &Token::RightBrace {
729 self.skip_newlines();
730 if self.current_token() == &Token::RightBrace {
731 break;
732 }
733 let key = self.expect_identifier()?;
734 if self.peek_token() != &Token::Assign
735 && self.current_token() != &Token::Assign
736 {
737 return Err(
738 format!(
739 "Expected '=' after property key '{}', found {:?}", key, self
740 .current_token()
741 ),
742 );
743 }
744 self.expect(Token::Assign)?;
745 let value = self.parse_expression()?;
746 retry_config.insert(key, value);
747 self.skip_newlines();
748 }
749 self.expect(Token::RightBrace)?;
750 Ok(retry_config)
751 }
752 fn parse_trigger_config(&mut self) -> Result<Expression, String> {
753 if self.current_token() == &Token::LeftBrace {
754 self.advance();
755 let trigger_obj = self.parse_object()?;
756 Ok(Expression::Object(trigger_obj))
757 } else {
758 self.parse_expression()
759 }
760 }
761 fn parse_expression(&mut self) -> Result<Expression, String> {
762 match self.current_token() {
763 Token::LeftParen | Token::LeftBracket => self.parse_enhanced_expression(),
764 _ => self.parse_expression_with_precedence(Precedence::Lowest),
765 }
766 }
767 fn parse_expression_with_precedence(
768 &mut self,
769 min_precedence: Precedence,
770 ) -> Result<Expression, String> {
771 let mut left = self.parse_primary_expression()?;
772 while !self.is_at_end() {
773 let precedence = self.get_token_precedence(self.current_token());
774 if precedence < min_precedence {
775 break;
776 }
777 match self.current_token() {
778 Token::Arrow => {
779 self.advance();
780 let mut pipeline = vec![];
781 if let Expression::Identifier(id) = left {
782 pipeline.push(id);
783 } else if let Expression::Pipeline(mut p) = left {
784 pipeline.append(&mut p);
785 } else {
786 return Err(format!("Invalid left side of pipeline: {:?}", left));
787 }
788 let right = self
789 .parse_expression_with_precedence(Precedence::Pipeline)?;
790 if let Expression::Identifier(id) = right {
791 pipeline.push(id);
792 } else if let Expression::Pipeline(mut p) = right {
793 pipeline.append(&mut p);
794 } else {
795 return Err(
796 format!("Invalid right side of pipeline: {:?}", right),
797 );
798 }
799 left = Expression::Pipeline(pipeline);
800 }
801 _ => {
802 break;
803 }
804 }
805 }
806 Ok(left)
807 }
808 fn parse_primary_expression(&mut self) -> Result<Expression, String> {
809 match self.current_token() {
810 Token::String(s) => {
811 let s = s.clone();
812 self.advance();
813 Ok(Expression::String(s))
814 }
815 Token::Number(n) => {
816 let n = *n;
817 self.advance();
818 Ok(Expression::Number(n))
819 }
820 Token::Bool(b) => {
821 let b = *b;
822 self.advance();
823 Ok(Expression::Bool(b))
824 }
825 Token::Duration(value, unit) => {
826 let duration = Duration {
827 value: *value,
828 unit: match unit {
829 TimeUnit::Seconds => crate::types::TimeUnit::Seconds,
830 TimeUnit::Minutes => crate::types::TimeUnit::Minutes,
831 TimeUnit::Hours => crate::types::TimeUnit::Hours,
832 TimeUnit::Days => crate::types::TimeUnit::Days,
833 },
834 };
835 self.advance();
836 Ok(Expression::Duration(duration))
837 }
838 Token::Variable(v) => {
839 let v = v.clone();
840 self.advance();
841 Ok(Expression::Variable(v))
842 }
843 Token::Reference(r) => {
844 let r = r.clone();
845 self.advance();
846 if self.current_token() == &Token::LeftBracket {
847 self.advance();
848 let key = self.expect_identifier()?;
849 self.expect(Token::RightBracket)?;
850 Ok(Expression::IndexedReference(r, key))
851 } else {
852 Ok(Expression::Reference(r))
853 }
854 }
855 Token::Identifier(i) => {
856 let i = i.clone();
857 self.advance();
858 Ok(Expression::Identifier(i))
859 }
860 Token::LeftBracket => {
861 self.advance();
862 let array = self.parse_array()?;
863 Ok(Expression::Array(array))
864 }
865 Token::LeftBrace => {
866 self.advance();
867 let object = self.parse_object()?;
868 Ok(Expression::Object(object))
869 }
870 Token::LeftParen => {
871 self.advance();
872 let expr = self.parse_expression()?;
873 self.expect(Token::RightParen)?;
874 Ok(expr)
875 }
876 _ => {
877 Err(
878 format!("Unexpected token in expression: {:?}", self.current_token()),
879 )
880 }
881 }
882 }
883 fn get_token_precedence(&self, token: &Token) -> Precedence {
884 match token {
885 Token::Arrow => Precedence::Pipeline,
886 _ => Precedence::Lowest,
887 }
888 }
889 fn is_at_end(&self) -> bool {
890 self.current_token() == &Token::Eof
891 }
892 fn parse_array(&mut self) -> Result<Vec<Expression>, String> {
893 let mut elements = Vec::new();
894 while self.current_token() != &Token::RightBracket {
895 self.skip_newlines();
896 if self.current_token() == &Token::RightBracket {
897 break;
898 }
899 elements.push(self.parse_expression()?);
900 if self.current_token() == &Token::Comma {
901 self.advance();
902 }
903 self.skip_newlines();
904 }
905 self.expect(Token::RightBracket)?;
906 Ok(elements)
907 }
908 fn parse_object(&mut self) -> Result<HashMap<String, Expression>, String> {
909 let mut object = HashMap::new();
910 while self.current_token() != &Token::RightBrace {
911 self.skip_newlines();
912 if self.current_token() == &Token::RightBrace {
913 break;
914 }
915 let key = self.expect_identifier()?;
916 if self.peek_token() != &Token::Assign
917 && self.current_token() != &Token::Assign
918 {
919 return Err(
920 format!(
921 "Expected '=' after property key '{}', found {:?}", key, self
922 .current_token()
923 ),
924 );
925 }
926 self.expect(Token::Assign)?;
927 let value = self.parse_expression()?;
928 object.insert(key, value);
929 if self.current_token() == &Token::Comma {
930 self.advance();
931 }
932 self.skip_newlines();
933 }
934 self.expect(Token::RightBrace)?;
935 Ok(object)
936 }
937 fn parse_string_array(&mut self) -> Result<Vec<String>, String> {
938 self.expect(Token::LeftBracket)?;
939 let mut items = Vec::new();
940 while self.current_token() != &Token::RightBracket {
941 self.skip_newlines();
942 if self.current_token() == &Token::RightBracket {
943 break;
944 }
945 items.push(self.expect_identifier()?);
946 if self.current_token() == &Token::Comma {
947 self.advance();
948 }
949 self.skip_newlines();
950 }
951 self.expect(Token::RightBracket)?;
952 Ok(items)
953 }
954 fn parse_properties(&mut self) -> Result<HashMap<String, Expression>, String> {
955 let mut properties = HashMap::new();
956 while self.current_token() != &Token::RightBrace {
957 self.skip_newlines();
958 if self.current_token() == &Token::RightBrace {
959 break;
960 }
961 let key = self.expect_identifier()?;
962 if self.peek_token() != &Token::Assign
963 && self.current_token() != &Token::Assign
964 {
965 return Err(
966 format!(
967 "Expected '=' after property key '{}', found {:?}", key, self
968 .current_token()
969 ),
970 );
971 }
972 self.expect(Token::Assign)?;
973 let value = self.parse_expression()?;
974 properties.insert(key, value);
975 self.skip_newlines();
976 }
977 Ok(properties)
978 }
979 fn parse_backstory_block(&mut self) -> Result<BackstoryBlock, String> {
980 self.expect(Token::LeftBrace)?;
981 let mut lines = Vec::new();
982 while self.current_token() != &Token::RightBrace {
983 self.skip_newlines();
984 match self.current_token() {
985 Token::Identifier(text) | Token::String(text) => {
986 lines.push(text.clone());
987 self.advance();
988 }
989 Token::RightBrace => break,
990 _ => {
991 self.advance();
992 }
993 }
994 }
995 self.expect(Token::RightBrace)?;
996 Ok(BackstoryBlock { lines })
997 }
998 fn parse_pipeline_block(&mut self) -> Result<PipelineDecl, String> {
999 self.expect(Token::LeftBrace)?;
1000 let mut flow = Vec::new();
1001 while self.current_token() != &Token::RightBrace {
1002 self.skip_newlines();
1003 if let Token::Identifier(step) = self.current_token() {
1004 flow.push(PipelineNode::Step(step.clone()));
1005 self.advance();
1006 if self.current_token() == &Token::Arrow {
1007 self.advance();
1008 }
1009 } else if self.current_token() == &Token::RightBrace {
1010 break;
1011 } else {
1012 self.advance();
1013 }
1014 self.skip_newlines();
1015 }
1016 self.expect(Token::RightBrace)?;
1017 Ok(PipelineDecl { flow })
1018 }
1019 fn parse_embeddings_block(&mut self) -> Result<EmbeddingsDecl, String> {
1020 self.expect(Token::LeftBrace)?;
1021 let mut model = String::new();
1022 let mut dimensions = 0;
1023 let mut properties = HashMap::new();
1024 while self.current_token() != &Token::RightBrace {
1025 self.skip_newlines();
1026 let key = self.expect_identifier()?;
1027 if self.peek_token() != &Token::Assign
1028 && self.current_token() != &Token::Assign
1029 {
1030 return Err(
1031 format!(
1032 "Expected '=' after property key '{}', found {:?}", key, self
1033 .current_token()
1034 ),
1035 );
1036 }
1037 self.expect(Token::Assign)?;
1038 let value = self.parse_expression()?;
1039 match key.as_str() {
1040 "model" => model = value.as_string().unwrap_or_default(),
1041 "dimensions" => dimensions = value.as_number().unwrap_or(0.0) as u32,
1042 _ => {
1043 properties.insert(key, value);
1044 }
1045 }
1046 self.skip_newlines();
1047 }
1048 self.expect(Token::RightBrace)?;
1049 Ok(EmbeddingsDecl {
1050 model,
1051 dimensions,
1052 properties,
1053 })
1054 }
1055 fn parse_variables_block(&mut self) -> Result<HashMap<String, Expression>, String> {
1056 self.expect(Token::LeftBrace)?;
1057 let mut variables = HashMap::new();
1058 while self.current_token() != &Token::RightBrace {
1059 self.skip_newlines();
1060 if self.current_token() == &Token::RightBrace {
1061 break;
1062 }
1063 let key = match self.current_token().clone() {
1064 Token::Identifier(id) => {
1065 self.advance();
1066 id.clone()
1067 }
1068 Token::Keyword(kw) => {
1069 self.advance();
1070 format!("{:?}", kw).to_lowercase()
1071 }
1072 _ => {
1073 return Err(
1074 format!(
1075 "Expected identifier or keyword for variable name, found {:?}",
1076 self.current_token()
1077 ),
1078 );
1079 }
1080 };
1081 self.expect(Token::Assign)?;
1082 let value = self.parse_expression()?;
1083 variables.insert(key, value);
1084 self.skip_newlines();
1085 }
1086 self.expect(Token::RightBrace)?;
1087 Ok(variables)
1088 }
1089 fn parse_secrets_block(&mut self) -> Result<HashMap<String, SecretRef>, String> {
1090 self.expect(Token::LeftBrace)?;
1091 let mut secrets = HashMap::new();
1092 while self.current_token() != &Token::RightBrace {
1093 self.skip_newlines();
1094 let key = self.expect_identifier()?;
1095 self.expect(Token::Assign)?;
1096 let secret_ref = match self.current_token() {
1097 Token::Variable(var) => {
1098 let var = var.clone();
1099 self.advance();
1100 SecretRef::Environment(var)
1101 }
1102 Token::String(path) if path.starts_with("vault:") => {
1103 let path = path.clone();
1104 self.advance();
1105 SecretRef::Vault(path.trim_start_matches("vault:").to_string())
1106 }
1107 Token::String(path) if path.starts_with("file:") => {
1108 let path = path.clone();
1109 self.advance();
1110 SecretRef::File(path.trim_start_matches("file:").to_string())
1111 }
1112 _ => {
1113 return Err(
1114 format!("Invalid secret reference: {:?}", self.current_token()),
1115 );
1116 }
1117 };
1118 secrets.insert(key, secret_ref);
1119 self.skip_newlines();
1120 }
1121 self.expect(Token::RightBrace)?;
1122 Ok(secrets)
1123 }
1124}
1125pub fn parse(tokens: Vec<Token>) -> Result<HelixAst, ParseError> {
1126 let mut parser = Parser::new(tokens);
1127 parser
1128 .parse()
1129 .map_err(|msg| ParseError {
1130 message: msg,
1131 location: None,
1132 token_index: 0,
1133 expected: None,
1134 found: String::new(),
1135 context: String::new(),
1136 })
1137}