1use crate::atp::lexer::{
2 Token, Keyword, TimeUnit, TokenWithLocation, SourceLocation, SourceMap,
3};
4pub use crate::atp::types::SecretRef;
5use crate::atp::types::Duration;
6use crate::atp::ast::*;
7pub use crate::atp::types::Value;
8use crate::ops::engine::OperatorEngine;
9use crate::hel::error::HlxError;
10use std::collections::HashMap;
11use regex;
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum ProjectBlockType {
14 Brace,
15 Angle,
16 Bracket,
17 Colon,
18}
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum BlockKind {
21 Brace,
22 Angle,
23 Bracket,
24 Colon,
25}
26#[cfg(feature = "js")]
27use napi;
28pub struct Parser {
29 tokens: Vec<TokenWithLocation>,
30 source_map: Option<SourceMap>,
31 current: usize,
32 errors: Vec<ParseError>,
33 recovery_points: Vec<usize>,
34 operator_engine: Option<OperatorEngine>,
35 runtime_context: HashMap<String, String>,
36}
37#[derive(Debug, Clone)]
38pub struct ParseError {
39 pub message: String,
40 pub location: Option<SourceLocation>,
41 pub token_index: usize,
42 pub expected: Option<String>,
43 pub found: String,
44 pub context: String,
45}
46impl std::fmt::Display for ParseError {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 write!(f, "{}", self.message)?;
49 if let Some(expected) = &self.expected {
50 write!(f, " (expected: {}, found: {})", expected, self.found)?;
51 }
52 if !self.context.is_empty() {
53 write!(f, " in {}", self.context)?;
54 }
55 Ok(())
56 }
57}
58impl std::error::Error for ParseError {}
59impl AsRef<str> for ParseError {
60 fn as_ref(&self) -> &str {
61 &self.message
62 }
63}
64#[cfg(feature = "js")]
65impl From<ParseError> for napi::Error<ParseError> {
66 fn from(err: ParseError) -> Self {
67 napi::Error::new(err, napi::Status::GenericFailure)
68 }
69}
70impl ParseError {
71 pub fn format_with_source(&self, source: &str, tokens: &[Token]) -> String {
72 let mut line = 1;
73 let mut col = 1;
74 for (i, ch) in source.chars().enumerate() {
75 if i >= self.token_index {
76 break;
77 }
78 if ch == '\n' {
79 line += 1;
80 col = 1;
81 } else {
82 col += 1;
83 }
84 }
85 let lines: Vec<&str> = source.lines().collect();
86 let error_line = if line > 0 && line <= lines.len() {
87 lines[line - 1]
88 } else {
89 ""
90 };
91 let mut result = format!("Error at line {}, column {}:\n", line, col);
92 result.push_str(&format!(" {}\n", error_line));
93 result.push_str(&format!(" {}^\n", " ".repeat(col - 1)));
94 let token_info = if self.token_index < tokens.len() {
95 format!("{:?}", tokens[self.token_index])
96 } else {
97 "<EOF>".to_string()
98 };
99 if let Some(expected) = &self.expected {
100 result
101 .push_str(
102 &format!("Expected {}, found token {}\n", expected, token_info),
103 );
104 } else {
105 result.push_str(&format!("{}\n", self.message));
106 }
107 if !self.context.is_empty() {
108 result.push_str(&format!("Context: {}\n", self.context));
109 }
110 result
111 }
112}
113#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
114#[allow(dead_code)]
115enum Precedence {
116 Lowest = 0,
117 Pipeline = 1,
118 Logical = 2,
119 Equality = 3,
120 Comparison = 4,
121 Addition = 5,
122 Multiplication = 6,
123 Unary = 7,
124 Call = 8,
125 Index = 9,
126 Highest = 10,
127}
128impl Parser {
129 pub fn new(tokens: Vec<Token>) -> Self {
130 let tokens_with_location = tokens
131 .into_iter()
132 .enumerate()
133 .map(|(i, token)| {
134 TokenWithLocation {
135 token,
136 location: SourceLocation {
137 line: 1,
138 column: i + 1,
139 position: i,
140 },
141 }
142 })
143 .collect();
144 Parser {
145 tokens: tokens_with_location,
146 source_map: None,
147 current: 0,
148 errors: Vec::new(),
149 recovery_points: Vec::new(),
150 operator_engine: None,
151 runtime_context: HashMap::new(),
152 }
153 }
154 pub fn new_enhanced(tokens: Vec<TokenWithLocation>) -> Self {
155 Parser {
156 tokens,
157 source_map: None,
158 current: 0,
159 errors: Vec::new(),
160 recovery_points: Vec::new(),
161 operator_engine: None,
162 runtime_context: HashMap::new(),
163 }
164 }
165 pub fn new_with_source_map(source_map: SourceMap) -> Self {
166 let tokens = source_map.tokens.clone();
167 Parser {
168 tokens,
169 source_map: Some(source_map),
170 current: 0,
171 errors: Vec::new(),
172 recovery_points: Vec::new(),
173 operator_engine: None,
174 runtime_context: HashMap::new(),
175 }
176 }
177 fn add_error(&mut self, message: String, expected: Option<String>) {
178 let error = ParseError {
179 message,
180 location: self.current_location(),
181 token_index: self.current,
182 expected,
183 found: format!("{:?}", self.current_token()),
184 context: self.get_enhanced_context(),
185 };
186 self.errors.push(error);
187 }
188 fn get_context(&self) -> String {
189 if self.recovery_points.is_empty() {
190 "top-level".to_string()
191 } else {
192 match self.recovery_points.last() {
193 Some(_) => "inside declaration".to_string(),
194 None => "unknown".to_string(),
195 }
196 }
197 }
198 fn get_enhanced_context(&self) -> String {
199 let basic_context = self.get_context();
200 if let (Some(source_map), Some(location)) = (
201 &self.source_map,
202 &self.current_location(),
203 ) {
204 let source_context = source_map.get_context(location, 2);
205 format!("{} - Source context:\n{}", basic_context, source_context)
206 } else {
207 basic_context
208 }
209 }
210 fn recover_to_next_declaration(&mut self) {
211 while self.current_token() != &Token::Eof {
212 match self.current_token() {
213 Token::Keyword(k) => {
214 match k {
215 Keyword::Agent
216 | Keyword::Workflow
217 | Keyword::Memory
218 | Keyword::Context
219 | Keyword::Crew
220 | Keyword::Project
221 | Keyword::Pipeline
222 | Keyword::Load => {
223 break;
224 }
225 _ => {}
226 }
227 }
228 _ => {}
229 }
230 self.advance();
231 }
232 }
233 #[allow(dead_code)]
234 fn recover_to_closing_brace(&mut self) {
235 let mut brace_depth = 1;
236 while self.current_token() != &Token::Eof && brace_depth > 0 {
237 match self.current_token() {
238 Token::LeftBrace => brace_depth += 1,
239 Token::RightBrace => brace_depth -= 1,
240 _ => {}
241 }
242 if brace_depth > 0 {
243 self.advance();
244 }
245 }
246 }
247 fn current_token(&self) -> &Token {
248 self.tokens
249 .get(self.current)
250 .map(|token_with_loc| &token_with_loc.token)
251 .unwrap_or(&Token::Eof)
252 }
253 fn current_location(&self) -> Option<SourceLocation> {
254 self.tokens
255 .get(self.current)
256 .map(|token_with_loc| token_with_loc.location.clone())
257 }
258 fn peek_token(&self) -> &Token {
259 self.tokens
260 .get(self.current + 1)
261 .map(|token_with_loc| &token_with_loc.token)
262 .unwrap_or(&Token::Eof)
263 }
264 fn parse_enhanced_expression(&mut self) -> Result<Expression, String> {
265 let next_token = self.peek_token().clone();
266 match (self.current_token().clone(), &next_token) {
267 (Token::Identifier(name), Token::Assign) => {
268 self.advance();
269 Ok(Expression::Identifier(name))
270 }
271 (Token::LeftParen, _) => {
272 self.advance();
273 let expr = self.parse_enhanced_expression()?;
274 self.expect(Token::RightParen)?;
275 Ok(expr)
276 }
277 (Token::LeftBracket, _) => {
278 self.advance();
279 let mut elements = Vec::new();
280 while self.current_token() != &Token::RightBracket
281 && self.current_token() != &Token::Eof
282 {
283 self.skip_newlines();
284 if self.current_token() == &Token::RightBracket {
285 break;
286 }
287 elements.push(self.parse_enhanced_expression()?);
288 self.skip_newlines();
289 if self.current_token() == &Token::Comma {
290 self.advance();
291 }
292 }
293 self.expect(Token::RightBracket)?;
294 Ok(Expression::Array(elements))
295 }
296 _ => self.parse_primary_expression(),
297 }
298 }
299 fn advance(&mut self) -> Token {
300 let token = self.current_token().clone();
301 if self.current < self.tokens.len() {
302 self.current += 1;
303 }
304 token
305 }
306 fn expect(&mut self, expected: Token) -> Result<(), String> {
307 let token = self.current_token().clone();
308 if token == expected {
309 self.advance();
310 Ok(())
311 } else {
312 Err(format!("Expected {:?}, found {:?}", expected, token))
313 }
314 }
315 fn expect_identifier(&mut self) -> Result<String, String> {
316 match self.current_token() {
317 Token::Identifier(name) => {
318 let name = name.clone();
319 self.advance();
320 let (clean_name, is_var) = Self::peel_markers(&name);
321 if is_var {
322 Ok(self.resolve_variable(&clean_name, true))
323 } else {
324 Ok(name)
325 }
326 }
327 Token::String(name) => {
328 let name = name.clone();
329 self.advance();
330 let (clean_name, is_var) = Self::peel_markers(&name);
331 if is_var {
332 Ok(self.resolve_variable(&clean_name, true))
333 } else {
334 Ok(name)
335 }
336 }
337 _ => Err(format!("Expected identifier, found {:?}", self.current_token())),
338 }
339 }
340 fn skip_newlines(&mut self) {
341 while self.current_token() == &Token::Newline {
342 self.advance();
343 }
344 }
345 fn peel_markers(raw: &str) -> (String, bool) {
347 let mut s = raw.to_string();
348 let mut is_var = false;
349 if s.starts_with('!') {
350 s.remove(0);
351 is_var = true;
352 }
353 if s.ends_with('!') {
354 s.pop();
355 is_var = true;
356 }
357 (s, is_var)
358 }
359 fn resolve_variable(&self, name: &str, is_marked: bool) -> String {
361 if !is_marked {
362 return name.to_string();
363 }
364 if let Some(v) = self.runtime_context.get(name) {
365 return v.clone();
366 }
367 std::env::var(name).unwrap_or_else(|_| name.to_string())
368 }
369 fn expect_identifier_or_string(&mut self) -> Result<(String, bool), String> {
370 match self.current_token() {
371 Token::Identifier(raw) => {
372 let raw = raw.clone();
373 self.advance();
374 Ok(Self::peel_markers(&raw))
375 }
376 Token::String(raw) => {
377 let raw = raw.clone();
378 self.advance();
379 Ok(Self::peel_markers(&raw))
380 }
381 _ => {
382 Err(
383 format!(
384 "Expected identifier or string, found {:?}", self.current_token()
385 ),
386 )
387 }
388 }
389 }
390 fn build_full_name(&self, base: &str, sub: Option<String>) -> String {
391 if let Some(s) = sub { format!("{}.{}", base, s) } else { base.to_string() }
392 }
393 fn parse_at_operator_with_chain(
394 &mut self,
395 operator: String,
396 arg: String,
397 ) -> Result<Expression, String> {
398 self.advance();
399 let first_key = self.expect_identifier()?;
400 let mut value_opt = None;
401 if self.current_token() == &Token::LeftBracket {
402 self.advance();
403 let v = self.expect_identifier()?;
404 self.expect(Token::RightBracket)?;
405 value_opt = Some(v);
406 }
407 Ok(Expression::OperatorCall(operator, arg, Some(first_key), value_opt))
408 }
409 pub fn set_runtime_context(&mut self, context: HashMap<String, String>) {
410 self.runtime_context = context;
411 }
412 pub fn parse(&mut self) -> Result<HelixAst, String> {
413 let mut ast = HelixAst::new();
414 while self.current_token() != &Token::Eof {
415 self.skip_newlines();
416 let current_token = self.current_token().clone();
417 match current_token {
418 Token::Keyword(keyword) => {
419 self.recovery_points.push(self.current);
420 match self.parse_declaration(keyword.clone()) {
421 Ok(decl) => {
422 ast.add_declaration(decl);
423 self.recovery_points.pop();
424 }
425 Err(err) => {
426 self.add_error(
427 err.clone(),
428 Some(format!("valid {:?} declaration", keyword)),
429 );
430 self.recover_to_next_declaration();
431 self.recovery_points.pop();
432 }
433 }
434 }
435 Token::Tilde => {
436 self.advance();
437 match self.current_token() {
438 Token::Identifier(actual_name) => {
439 let actual_name = actual_name.clone();
440 self.recovery_points.push(self.current);
441 match self.parse_generic_declaration(actual_name.clone()) {
442 Ok(decl) => {
443 ast.add_declaration(decl);
444 self.recovery_points.pop();
445 }
446 Err(err) => {
447 self.add_error(
448 err.clone(),
449 Some(format!("valid ~{} declaration", actual_name)),
450 );
451 self.recover_to_next_declaration();
452 self.recovery_points.pop();
453 }
454 }
455 }
456 _ => {
457 self.add_error(
458 format!(
459 "Expected identifier after '~', found {:?}", self
460 .current_token()
461 ),
462 Some("identifier after tilde".to_string()),
463 );
464 self.recover_to_next_declaration();
465 }
466 }
467 }
468 Token::Identifier(identifier) => {
469 self.advance(); self.recovery_points.push(self.current);
471 match self.parse_generic_declaration(identifier.clone()) {
472 Ok(decl) => {
473 ast.add_declaration(decl);
474 self.recovery_points.pop();
475 }
476 Err(err) => {
477 self.add_error(
478 err.clone(),
479 Some(format!("valid {} declaration", identifier)),
480 );
481 self.recover_to_next_declaration();
482 self.recovery_points.pop();
483 }
484 }
485 }
486 Token::Eof => break,
487 _ => {
488 self.add_error(
489 format!("Unexpected token: {:?}", current_token),
490 Some("declaration keyword or identifier".to_string()),
491 );
492 self.recover_to_next_declaration();
493 }
494 }
495 self.skip_newlines();
496 }
497 if !self.errors.is_empty() {
498 let error_summary = self
499 .errors
500 .iter()
501 .map(|e| format!("{} at token {}", e.message, e.token_index))
502 .collect::<Vec<_>>()
503 .join("; ");
504 Err(format!("Parse errors: {}", error_summary))
505 } else {
506 Ok(ast)
507 }
508 }
509 fn parse_declaration(&mut self, keyword: Keyword) -> Result<Declaration, String> {
510 match keyword {
511 Keyword::Project => {
512 self.advance();
513 let (name, block_kind) = self.parse_project_variations()?;
514 match block_kind {
515 BlockKind::Brace => {
516 self.expect(Token::LeftBrace)?;
517 }
518 BlockKind::Angle => {
519 self.expect(Token::LessThan)?;
520 }
521 BlockKind::Bracket => {
522 self.expect(Token::LeftBracket)?;
523 }
524 BlockKind::Colon => {
525 self.expect(Token::Colon)?;
526 let properties = self.parse_properties()?;
527 self.expect(Token::Semicolon)?;
528 return Ok(Declaration::Project(ProjectDecl { name, properties }));
529 }
530 }
531 let properties = self.parse_properties()?;
532 match block_kind {
533 BlockKind::Brace => {
534 self.expect(Token::RightBrace)?;
535 }
536 BlockKind::Angle => {
537 self.expect(Token::GreaterThan)?;
538 }
539 BlockKind::Bracket => {
540 self.expect(Token::RightBracket)?;
541 }
542 BlockKind::Colon => {}
543 }
544 Ok(Declaration::Project(ProjectDecl { name, properties }))
545 }
546 Keyword::Agent => {
547 self.advance();
548 let name = if self.current_token() == &Token::LeftBrace {
549 String::new()
550 } else {
551 self.expect_identifier()?
552 };
553 self.expect(Token::LeftBrace)?;
554 let mut properties = HashMap::new();
555 let mut capabilities = None;
556 let mut backstory = None;
557 let tools = None;
558 while self.current_token() != &Token::RightBrace {
559 self.skip_newlines();
560 match self.current_token() {
561 Token::Keyword(Keyword::Capabilities) => {
562 self.advance();
563 capabilities = Some(self.parse_string_array()?);
564 }
565 Token::Keyword(Keyword::Backstory) => {
566 self.advance();
567 backstory = Some(self.parse_backstory_block()?);
568 }
569 Token::Identifier(key) => {
570 let key = key.clone();
571 self.advance();
572 self.expect(Token::Assign)?;
573 let value = self.parse_expression()?;
574 properties.insert(key, value);
575 }
576 Token::Keyword(keyword) => {
577 match keyword {
578 Keyword::Capabilities | Keyword::Backstory => {
579 return Err(
580 format!(
581 "Unexpected token in agent: {:?}", self.current_token()
582 ),
583 );
584 }
585 _ => {
586 let key = format!("{:?}", keyword).to_lowercase();
587 self.advance();
588 self.expect(Token::Assign)?;
589 let value = self.parse_expression()?;
590 properties.insert(key, value);
591 }
592 }
593 }
594 Token::RightBrace => break,
595 _ => {
596 return Err(
597 format!(
598 "Unexpected token in agent: {:?}", self.current_token()
599 ),
600 );
601 }
602 }
603 self.skip_newlines();
604 }
605 self.expect(Token::RightBrace)?;
606 Ok(
607 Declaration::Agent(AgentDecl {
608 name,
609 properties,
610 capabilities,
611 backstory,
612 tools,
613 }),
614 )
615 }
616 Keyword::Workflow => {
617 self.advance();
618 let name = self.expect_identifier()?;
619 self.expect(Token::LeftBrace)?;
620 let mut trigger = None;
621 let mut steps = Vec::new();
622 let mut pipeline = None;
623 let mut properties = HashMap::new();
624 while self.current_token() != &Token::RightBrace {
625 self.skip_newlines();
626 match self.current_token() {
627 Token::Keyword(Keyword::Trigger) => {
628 self.advance();
629 self.expect(Token::Assign)?;
630 trigger = Some(self.parse_trigger_config()?);
631 }
632 Token::Keyword(Keyword::Step) => {
633 steps.push(self.parse_step()?);
634 }
635 Token::Keyword(Keyword::Pipeline) => {
636 self.advance();
637 pipeline = Some(self.parse_pipeline_block()?);
638 }
639 Token::Keyword(Keyword::Timeout) => {
640 self.advance();
641 self.expect(Token::Assign)?;
642 let timeout_value = self.parse_expression()?;
643 properties.insert("timeout".to_string(), timeout_value);
644 }
645 Token::Identifier(key) => {
646 let key = key.clone();
647 self.advance();
648 self.expect(Token::Assign)?;
649 let value = self.parse_expression()?;
650 properties.insert(key, value);
651 }
652 Token::RightBrace => break,
653 _ => {
654 return Err(
655 format!(
656 "Unexpected token in workflow: {:?}", self.current_token()
657 ),
658 );
659 }
660 }
661 self.skip_newlines();
662 }
663 self.expect(Token::RightBrace)?;
664 Ok(
665 Declaration::Workflow(WorkflowDecl {
666 name,
667 trigger,
668 steps,
669 pipeline,
670 properties,
671 }),
672 )
673 }
674 Keyword::Memory => {
675 self.advance();
676 self.expect(Token::LeftBrace)?;
677 let mut provider = String::new();
678 let mut connection = String::new();
679 let mut embeddings = None;
680 let mut properties = HashMap::new();
681 while self.current_token() != &Token::RightBrace {
682 self.skip_newlines();
683 match self.current_token() {
684 Token::Keyword(Keyword::Embeddings) => {
685 self.advance();
686 embeddings = Some(self.parse_embeddings_block()?);
687 }
688 Token::Identifier(key) => {
689 let key = key.clone();
690 self.advance();
691 self.expect(Token::Assign)?;
692 let value = self.parse_expression()?;
693 match key.as_str() {
694 "provider" => {
695 provider = value.as_string().unwrap_or_default();
696 }
697 "connection" => {
698 connection = value.as_string().unwrap_or_default();
699 }
700 _ => {
701 properties.insert(key, value);
702 }
703 }
704 }
705 Token::RightBrace => break,
706 _ => {
707 return Err(
708 format!(
709 "Unexpected token in memory: {:?}", self.current_token()
710 ),
711 );
712 }
713 }
714 self.skip_newlines();
715 }
716 self.expect(Token::RightBrace)?;
717 Ok(
718 Declaration::Memory(MemoryDecl {
719 provider,
720 connection,
721 embeddings,
722 properties,
723 }),
724 )
725 }
726 Keyword::Context => {
727 self.advance();
728 let name = self.expect_identifier()?;
729 self.expect(Token::LeftBrace)?;
730 let mut environment = String::new();
731 let mut secrets = None;
732 let mut variables = None;
733 let mut properties = HashMap::new();
734 while self.current_token() != &Token::RightBrace {
735 self.skip_newlines();
736 match self.current_token() {
737 Token::Keyword(Keyword::Secrets) => {
738 self.advance();
739 secrets = Some(self.parse_secrets_block()?);
740 }
741 Token::Keyword(Keyword::Variables) => {
742 self.advance();
743 variables = Some(self.parse_variables_block()?);
744 }
745 Token::Identifier(key) => {
746 let key = key.clone();
747 self.advance();
748 self.expect(Token::Assign)?;
749 let value = self.parse_expression()?;
750 if key == "environment" {
751 environment = value.as_string().unwrap_or_default();
752 } else {
753 properties.insert(key, value);
754 }
755 }
756 Token::RightBrace => break,
757 _ => {
758 return Err(
759 format!(
760 "Unexpected token in context: {:?}", self.current_token()
761 ),
762 );
763 }
764 }
765 self.skip_newlines();
766 }
767 self.expect(Token::RightBrace)?;
768 Ok(
769 Declaration::Context(ContextDecl {
770 name,
771 environment,
772 secrets,
773 variables,
774 properties,
775 }),
776 )
777 }
778 Keyword::Crew => {
779 self.advance();
780 let name = self.expect_identifier()?;
781 self.expect(Token::LeftBrace)?;
782 let mut agents = Vec::new();
783 let mut process_type = None;
784 let mut properties = HashMap::new();
785 while self.current_token() != &Token::RightBrace {
786 self.skip_newlines();
787 match self.current_token() {
788 Token::Identifier(key) => {
789 let key = key.clone();
790 self.advance();
791 if key == "agents" {
792 agents = self.parse_string_array()?;
793 } else {
794 self.expect(Token::Assign)?;
795 let value = self.parse_expression()?;
796 if key == "process" {
797 process_type = value.as_string();
798 } else {
799 properties.insert(key, value);
800 }
801 }
802 }
803 Token::RightBrace => break,
804 _ => {
805 return Err(
806 format!(
807 "Unexpected token in crew: {:?}", self.current_token()
808 ),
809 );
810 }
811 }
812 self.skip_newlines();
813 }
814 self.expect(Token::RightBrace)?;
815 Ok(
816 Declaration::Crew(CrewDecl {
817 name,
818 agents,
819 process_type,
820 properties,
821 }),
822 )
823 }
824 Keyword::Pipeline => {
825 self.advance();
826 self.expect(Token::LeftBrace)?;
827 let pipeline = self.parse_pipeline_block()?;
828 self.expect(Token::RightBrace)?;
829 Ok(Declaration::Pipeline(pipeline))
830 }
831 Keyword::Task => {
832 self.advance();
833 let (name, block_kind) = self.parse_generic_variations("task".to_string())?;
834 match block_kind {
835 BlockKind::Brace => {
836 self.expect(Token::LeftBrace)?;
837 }
838 BlockKind::Angle => {
839 self.expect(Token::LessThan)?;
840 }
841 BlockKind::Bracket => {
842 self.expect(Token::LeftBracket)?;
843 }
844 BlockKind::Colon => {
845 self.expect(Token::Colon)?;
846 if self.current_token() == &Token::Semicolon {
847 self.advance();
848 }
849 return Ok(
850 Declaration::Task(TaskDecl {
851 name,
852 properties: HashMap::new(),
853 }),
854 );
855 }
856 }
857 let properties = self.parse_properties()?;
858 match block_kind {
859 BlockKind::Brace => {
860 self.expect(Token::RightBrace)?;
861 }
862 BlockKind::Angle => {
863 self.expect(Token::GreaterThan)?;
864 }
865 BlockKind::Bracket => {
866 self.expect(Token::RightBracket)?;
867 }
868 BlockKind::Colon => {}
869 }
870 Ok(Declaration::Task(TaskDecl { name, properties }))
871 }
872 Keyword::Load => {
873 self.advance();
874 let file_name = self.expect_identifier()?;
875 self.expect(Token::LeftBrace)?;
876 let properties = self.parse_properties()?;
877 self.expect(Token::RightBrace)?;
878 Ok(Declaration::Load(LoadDecl { file_name, properties }))
879 }
880 _ => Err(format!("Unexpected keyword: {:?}", keyword)),
881 }
882 }
883 fn parse_step(&mut self) -> Result<StepDecl, String> {
884 self.advance();
885 let name = self.expect_identifier()?;
886 self.expect(Token::LeftBrace)?;
887 let mut agent = None;
888 let mut crew = None;
889 let mut task = None;
890 let mut properties = HashMap::new();
891 while self.current_token() != &Token::RightBrace {
892 self.skip_newlines();
893 match self.current_token() {
894 Token::Keyword(Keyword::Timeout) => {
895 self.advance();
896 self.expect(Token::Assign)?;
897 let timeout_value = self.parse_expression()?;
898 properties.insert("timeout".to_string(), timeout_value);
899 }
900 Token::Identifier(key) => {
901 let key = key.clone();
902 self.advance();
903 match key.as_str() {
904 "agent" => {
905 self.expect(Token::Assign)?;
906 agent = self.parse_expression()?.as_string();
907 }
908 "crew" => {
909 self.expect(Token::Assign)?;
910 if self.current_token() == &Token::LeftBracket {
911 crew = Some(self.parse_string_array()?);
912 }
913 }
914 "task" => {
915 self.expect(Token::Assign)?;
916 task = self.parse_expression()?.as_string();
917 }
918 "retry" => {
919 let retry_config = self.parse_retry_block()?;
920 properties
921 .insert(
922 "retry".to_string(),
923 Expression::Object(retry_config),
924 );
925 }
926 _ => {
927 self.expect(Token::Assign)?;
928 let value = self.parse_expression()?;
929 properties.insert(key, value);
930 }
931 }
932 }
933 Token::Keyword(keyword) => {
934 let key = format!("{:?}", keyword).to_lowercase();
935 self.advance();
936 self.expect(Token::Assign)?;
937 match key.as_str() {
938 "agent" => {
939 agent = self.parse_expression()?.as_string();
940 }
941 _ => {
942 let value = self.parse_expression()?;
943 properties.insert(key, value);
944 }
945 }
946 }
947 Token::RightBrace => break,
948 _ => {
949 return Err(
950 format!("Unexpected token in step: {:?}", self.current_token()),
951 );
952 }
953 }
954 self.skip_newlines();
955 }
956 self.expect(Token::RightBrace)?;
957 Ok(StepDecl {
958 name,
959 agent,
960 crew,
961 task,
962 properties,
963 })
964 }
965 fn parse_retry_block(&mut self) -> Result<HashMap<String, Expression>, String> {
966 self.expect(Token::LeftBrace)?;
967 let mut retry_config = HashMap::new();
968 while self.current_token() != &Token::RightBrace {
969 self.skip_newlines();
970 if self.current_token() == &Token::RightBrace {
971 break;
972 }
973 let key = self.expect_identifier()?;
974 if self.peek_token() != &Token::Assign
975 && self.current_token() != &Token::Assign
976 {
977 return Err(
978 format!(
979 "Expected '=' after property key '{}', found {:?}", key, self
980 .current_token()
981 ),
982 );
983 }
984 self.expect(Token::Assign)?;
985 let value = self.parse_expression()?;
986 retry_config.insert(key, value);
987 self.skip_newlines();
988 }
989 self.expect(Token::RightBrace)?;
990 Ok(retry_config)
991 }
992 fn parse_trigger_config(&mut self) -> Result<Expression, String> {
993 if self.current_token() == &Token::LeftBrace {
994 self.advance();
995 let trigger_obj = self.parse_object()?;
996 Ok(Expression::Object(trigger_obj))
997 } else {
998 self.parse_expression()
999 }
1000 }
1001 fn parse_expression(&mut self) -> Result<Expression, String> {
1002 match self.current_token() {
1003 Token::LeftParen | Token::LeftBracket => self.parse_enhanced_expression(),
1004 _ => self.parse_expression_with_precedence(Precedence::Lowest),
1005 }
1006 }
1007 fn parse_expression_with_precedence(
1008 &mut self,
1009 min_precedence: Precedence,
1010 ) -> Result<Expression, String> {
1011 let mut left = self.parse_primary_expression()?;
1012 while !self.is_at_end() {
1013 let precedence = self.get_token_precedence(self.current_token());
1014 if precedence < min_precedence {
1015 break;
1016 }
1017 match self.current_token() {
1018 Token::Plus => {
1019 self.advance();
1020 let right = self.parse_expression_with_precedence(Precedence::Addition)?;
1021 left = Expression::BinaryOp(Box::new(left), BinaryOperator::Add, Box::new(right));
1022 }
1023 Token::Arrow => {
1024 self.advance();
1025 let mut pipeline = vec![];
1026 if let Expression::Identifier(id) = left {
1027 pipeline.push(id);
1028 } else if let Expression::Pipeline(mut p) = left {
1029 pipeline.append(&mut p);
1030 } else {
1031 return Err(format!("Invalid left side of pipeline: {:?}", left));
1032 }
1033 let right = self
1034 .parse_expression_with_precedence(Precedence::Pipeline)?;
1035 if let Expression::Identifier(id) = right {
1036 pipeline.push(id);
1037 } else if let Expression::Pipeline(mut p) = right {
1038 pipeline.append(&mut p);
1039 } else {
1040 return Err(
1041 format!("Invalid right side of pipeline: {:?}", right),
1042 );
1043 }
1044 left = Expression::Pipeline(pipeline);
1045 }
1046 _ => {
1047 break;
1048 }
1049 }
1050 }
1051 Ok(left)
1052 }
1053 fn parse_primary_expression(&mut self) -> Result<Expression, String> {
1054 match self.current_token() {
1055 Token::String(s) => {
1056 let s = s.clone();
1057 self.advance();
1058 let (clean_s, is_var) = Self::peel_markers(&s);
1059 if is_var {
1060 let resolved_value = self.resolve_variable(&clean_s, true);
1061 Ok(Expression::String(resolved_value))
1062 } else {
1063 Ok(Expression::String(s))
1064 }
1065 }
1066 Token::Number(n) => {
1067 let n = *n;
1068 self.advance();
1069 Ok(Expression::Number(n))
1070 }
1071 Token::Bool(b) => {
1072 let b = *b;
1073 self.advance();
1074 Ok(Expression::Bool(b))
1075 }
1076 Token::Duration(value, unit) => {
1077 let duration = Duration {
1078 value: *value,
1079 unit: match unit {
1080 TimeUnit::Seconds => crate::atp::types::TimeUnit::Seconds,
1081 TimeUnit::Minutes => crate::atp::types::TimeUnit::Minutes,
1082 TimeUnit::Hours => crate::atp::types::TimeUnit::Hours,
1083 TimeUnit::Days => crate::atp::types::TimeUnit::Days,
1084 },
1085 };
1086 self.advance();
1087 Ok(Expression::Duration(duration))
1088 }
1089 Token::Variable(v) => {
1090 let v = v.clone();
1091 self.advance();
1092 Ok(Expression::Variable(v))
1093 }
1094 Token::Reference(r) => {
1095 let operator = r.clone();
1096 self.advance();
1097 if self.current_token() == &Token::LeftBracket {
1098 self.advance();
1099 let arg = match self.current_token() {
1100 Token::String(s) => {
1101 let s = s.clone();
1102 self.advance();
1103 let (clean_s, is_var) = Self::peel_markers(&s);
1104 if is_var {
1105 self.resolve_variable(&clean_s, true)
1106 } else {
1107 s
1108 }
1109 }
1110 Token::Identifier(id) => {
1111 let id = id.clone();
1112 self.advance();
1113 let (clean_id, is_var) = Self::peel_markers(&id);
1114 if is_var {
1115 self.resolve_variable(&clean_id, true)
1116 } else {
1117 id
1118 }
1119 }
1120 _ => {
1121 return Err(
1122 format!(
1123 "Expected string or identifier inside @{}[ … ], found {:?}",
1124 operator, self.current_token()
1125 ),
1126 );
1127 }
1128 };
1129 if self.current_token() != &Token::RightBracket {
1130 return Err(
1131 format!(
1132 "Expected ']' after argument of @{}, found {:?}", operator,
1133 self.current_token()
1134 ),
1135 );
1136 }
1137 self.advance();
1138 if self.current_token() == &Token::Dot {
1139 return self.parse_at_operator_with_chain(operator, arg);
1140 }
1141 let mut params = HashMap::new();
1142 params.insert("arg".to_string(), Expression::String(arg));
1143 Ok(Expression::AtOperatorCall(operator, params))
1144 } else {
1145 if self.current_token() == &Token::LeftBracket {
1146 self.advance();
1147 let key = self.expect_identifier()?;
1148 self.expect(Token::RightBracket)?;
1149 if self.current_token() == &Token::Dot {
1150 self.advance();
1151 let sub_key = self.expect_identifier()?;
1152 if self.current_token() == &Token::LeftBracket {
1153 self.advance();
1154 let value = self.expect_identifier()?;
1155 self.expect(Token::RightBracket)?;
1156 Ok(
1157 Expression::OperatorCall(
1158 operator,
1159 key,
1160 Some(sub_key),
1161 Some(value),
1162 ),
1163 )
1164 } else {
1165 Ok(
1166 Expression::OperatorCall(operator, key, Some(sub_key), None),
1167 )
1168 }
1169 } else {
1170 Ok(Expression::IndexedReference(operator, key))
1171 }
1172 } else if self.current_token() == &Token::Dot {
1173 self.advance();
1174 let key = self.expect_identifier()?;
1175 if self.current_token() == &Token::LeftBracket {
1176 self.advance();
1177 let value = self.expect_identifier()?;
1178 self.expect(Token::RightBracket)?;
1179 Ok(
1180 Expression::OperatorCall(operator, key, None, Some(value)),
1181 )
1182 } else {
1183 Ok(Expression::OperatorCall(operator, key, None, None))
1184 }
1185 } else {
1186 Ok(Expression::Reference(operator))
1187 }
1188 }
1189 }
1190 Token::Identifier(i) => {
1191 let i = i.clone();
1192 self.advance();
1193 let (clean_i, is_var) = Self::peel_markers(&i);
1194 if is_var {
1195 let resolved_value = self.resolve_variable(&clean_i, true);
1196 Ok(Expression::String(resolved_value))
1197 } else {
1198 Ok(Expression::Identifier(i))
1199 }
1200 }
1201 Token::LeftBracket => {
1202 self.advance();
1203 let array = self.parse_array()?;
1204 Ok(Expression::Array(array))
1205 }
1206 Token::LeftBrace => {
1207 self.advance();
1208 let object = self.parse_object()?;
1209 Ok(Expression::Object(object))
1210 }
1211 Token::LeftParen => {
1212 self.advance();
1213 let expr = self.parse_expression()?;
1214 self.expect(Token::RightParen)?;
1215 Ok(expr)
1216 }
1217 _ => {
1218 Err(
1219 format!("Unexpected token in expression: {:?}", self.current_token()),
1220 )
1221 }
1222 }
1223 }
1224 fn get_token_precedence(&self, token: &Token) -> Precedence {
1225 match token {
1226 Token::Plus => Precedence::Addition,
1227 Token::Arrow => Precedence::Pipeline,
1228 _ => Precedence::Lowest,
1229 }
1230 }
1231 fn is_at_end(&self) -> bool {
1232 self.current_token() == &Token::Eof
1233 }
1234 fn parse_array(&mut self) -> Result<Vec<Expression>, String> {
1235 let mut elements = Vec::new();
1236 while self.current_token() != &Token::RightBracket {
1237 self.skip_newlines();
1238 if self.current_token() == &Token::RightBracket {
1239 break;
1240 }
1241 elements.push(self.parse_expression()?);
1242 if self.current_token() == &Token::Comma {
1243 self.advance();
1244 }
1245 self.skip_newlines();
1246 }
1247 self.expect(Token::RightBracket)?;
1248 Ok(elements)
1249 }
1250 fn parse_object(&mut self) -> Result<HashMap<String, Expression>, String> {
1251 let mut object = HashMap::new();
1252 while self.current_token() != &Token::RightBrace {
1253 self.skip_newlines();
1254 if self.current_token() == &Token::RightBrace {
1255 break;
1256 }
1257 let key = self.expect_identifier()?;
1258 if self.peek_token() != &Token::Assign
1259 && self.current_token() != &Token::Assign
1260 {
1261 return Err(
1262 format!(
1263 "Expected '=' after property key '{}', found {:?}", key, self
1264 .current_token()
1265 ),
1266 );
1267 }
1268 self.expect(Token::Assign)?;
1269 let value = self.parse_expression()?;
1270 object.insert(key, value);
1271 if self.current_token() == &Token::Comma {
1272 self.advance();
1273 }
1274 self.skip_newlines();
1275 }
1276 self.expect(Token::RightBrace)?;
1277 Ok(object)
1278 }
1279 fn parse_string_array(&mut self) -> Result<Vec<String>, String> {
1280 self.expect(Token::LeftBracket)?;
1281 let mut items = Vec::new();
1282 while self.current_token() != &Token::RightBracket {
1283 self.skip_newlines();
1284 if self.current_token() == &Token::RightBracket {
1285 break;
1286 }
1287 items.push(self.expect_identifier()?);
1288 if self.current_token() == &Token::Comma {
1289 self.advance();
1290 }
1291 self.skip_newlines();
1292 }
1293 self.expect(Token::RightBracket)?;
1294 Ok(items)
1295 }
1296 fn parse_properties(&mut self) -> Result<HashMap<String, Expression>, String> {
1297 let mut properties = HashMap::new();
1298 while self.current_token() != &Token::RightBrace
1299 && self.current_token() != &Token::GreaterThan
1300 && self.current_token() != &Token::RightBracket
1301 && self.current_token() != &Token::Semicolon
1302 {
1303 self.skip_newlines();
1304 if self.current_token() == &Token::RightBrace
1305 || self.current_token() == &Token::GreaterThan
1306 || self.current_token() == &Token::RightBracket
1307 || self.current_token() == &Token::Semicolon
1308 {
1309 break;
1310 }
1311 let key = match self.current_token() {
1312 Token::Identifier(name) => {
1313 let name = name.clone();
1314 self.advance();
1315 name
1316 }
1317 Token::Keyword(keyword) => {
1318 let keyword = keyword.clone();
1319 self.advance();
1320 format!("{:?}", keyword).to_lowercase()
1321 }
1322 _ => {
1323 return Err(
1324 format!(
1325 "Expected property key (identifier or keyword), found {:?}",
1326 self.current_token()
1327 ),
1328 );
1329 }
1330 };
1331 if self.peek_token() != &Token::Assign
1332 && self.current_token() != &Token::Assign
1333 {
1334 return Err(
1335 format!(
1336 "Expected '=' after property key '{}', found {:?}", key, self
1337 .current_token()
1338 ),
1339 );
1340 }
1341 self.expect(Token::Assign)?;
1342 let value = self.parse_expression()?;
1343 properties.insert(key, value);
1344 self.skip_newlines();
1345 }
1346 Ok(properties)
1347 }
1348 fn parse_backstory_block(&mut self) -> Result<BackstoryBlock, String> {
1349 self.expect(Token::LeftBrace)?;
1350 let mut lines = Vec::new();
1351 while self.current_token() != &Token::RightBrace {
1352 self.skip_newlines();
1353 match self.current_token() {
1354 Token::Identifier(text) | Token::String(text) => {
1355 lines.push(text.clone());
1356 self.advance();
1357 }
1358 Token::RightBrace => break,
1359 _ => {
1360 self.advance();
1361 }
1362 }
1363 }
1364 self.expect(Token::RightBrace)?;
1365 Ok(BackstoryBlock { lines })
1366 }
1367 fn parse_pipeline_block(&mut self) -> Result<PipelineDecl, String> {
1368 self.expect(Token::LeftBrace)?;
1369 let mut flow = Vec::new();
1370 while self.current_token() != &Token::RightBrace {
1371 self.skip_newlines();
1372 if let Token::Identifier(step) = self.current_token() {
1373 flow.push(PipelineNode::Step(step.clone()));
1374 self.advance();
1375 if self.current_token() == &Token::Arrow {
1376 self.advance();
1377 }
1378 } else if self.current_token() == &Token::RightBrace {
1379 break;
1380 } else {
1381 self.advance();
1382 }
1383 self.skip_newlines();
1384 }
1385 self.expect(Token::RightBrace)?;
1386 Ok(PipelineDecl { flow })
1387 }
1388 fn parse_embeddings_block(&mut self) -> Result<EmbeddingsDecl, String> {
1389 self.expect(Token::LeftBrace)?;
1390 let mut model = String::new();
1391 let mut dimensions = 0;
1392 let mut properties = HashMap::new();
1393 while self.current_token() != &Token::RightBrace {
1394 self.skip_newlines();
1395 let key = self.expect_identifier()?;
1396 if self.peek_token() != &Token::Assign
1397 && self.current_token() != &Token::Assign
1398 {
1399 return Err(
1400 format!(
1401 "Expected '=' after property key '{}', found {:?}", key, self
1402 .current_token()
1403 ),
1404 );
1405 }
1406 self.expect(Token::Assign)?;
1407 let value = self.parse_expression()?;
1408 match key.as_str() {
1409 "model" => model = value.as_string().unwrap_or_default(),
1410 "dimensions" => dimensions = value.as_number().unwrap_or(0.0) as u32,
1411 _ => {
1412 properties.insert(key, value);
1413 }
1414 }
1415 self.skip_newlines();
1416 }
1417 self.expect(Token::RightBrace)?;
1418 Ok(EmbeddingsDecl {
1419 model,
1420 dimensions,
1421 properties,
1422 })
1423 }
1424 fn parse_variables_block(&mut self) -> Result<HashMap<String, Expression>, String> {
1425 self.expect(Token::LeftBrace)?;
1426 let mut variables = HashMap::new();
1427 while self.current_token() != &Token::RightBrace {
1428 self.skip_newlines();
1429 if self.current_token() == &Token::RightBrace {
1430 break;
1431 }
1432 let key = match self.current_token().clone() {
1433 Token::Identifier(id) => {
1434 self.advance();
1435 id.clone()
1436 }
1437 Token::Keyword(kw) => {
1438 self.advance();
1439 format!("{:?}", kw).to_lowercase()
1440 }
1441 _ => {
1442 return Err(
1443 format!(
1444 "Expected identifier or keyword for variable name, found {:?}",
1445 self.current_token()
1446 ),
1447 );
1448 }
1449 };
1450 self.expect(Token::Assign)?;
1451 let value = self.parse_expression()?;
1452 variables.insert(key, value);
1453 self.skip_newlines();
1454 }
1455 self.expect(Token::RightBrace)?;
1456 Ok(variables)
1457 }
1458 fn parse_secrets_block(&mut self) -> Result<HashMap<String, SecretRef>, String> {
1459 self.expect(Token::LeftBrace)?;
1460 let mut secrets = HashMap::new();
1461 while self.current_token() != &Token::RightBrace {
1462 self.skip_newlines();
1463 let key = self.expect_identifier()?;
1464 self.expect(Token::Assign)?;
1465 let secret_ref = match self.current_token() {
1466 Token::Variable(var) => {
1467 let var = var.clone();
1468 self.advance();
1469 SecretRef::Environment(var)
1470 }
1471 Token::String(path) if path.starts_with("vault:") => {
1472 let path = path.clone();
1473 self.advance();
1474 SecretRef::Vault(path.trim_start_matches("vault:").to_string())
1475 }
1476 Token::String(path) if path.starts_with("file:") => {
1477 let path = path.clone();
1478 self.advance();
1479 SecretRef::File(path.trim_start_matches("file:").to_string())
1480 }
1481 _ => {
1482 return Err(
1483 format!("Invalid secret reference: {:?}", self.current_token()),
1484 );
1485 }
1486 };
1487 secrets.insert(key, secret_ref);
1488 self.skip_newlines();
1489 }
1490 self.expect(Token::RightBrace)?;
1491 Ok(secrets)
1492 }
1493 pub async fn execute_operator(
1494 &mut self,
1495 operator: &str,
1496 params: &str,
1497 ) -> Result<crate::atp::value::Value, Box<dyn std::error::Error + Send + Sync>> {
1498 if self.operator_engine.is_none() {
1499 self.operator_engine = Some(
1500 OperatorEngine::new()
1501 .await
1502 .map_err(|e| {
1503 Box::new(e) as Box<dyn std::error::Error + Send + Sync>
1504 })?,
1505 );
1506 }
1507 if let Some(ref engine) = self.operator_engine {
1508 match engine.execute_operator(operator, params).await {
1509 Ok(value) => Ok(value),
1510 Err(e) => {
1511 eprintln!("Operator execution error: {:?}", e);
1512 Ok(crate::atp::value::Value::String(format!("@{}({})", operator, params)))
1513 }
1514 }
1515 } else {
1516 Ok(crate::atp::value::Value::String(format!("@{}({})", operator, params)))
1517 }
1518 }
1519 pub async fn params_to_json(
1520 &mut self,
1521 params: &HashMap<String, Expression>,
1522 ) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
1523 let mut json_map = serde_json::Map::new();
1524 for (key, expr) in params {
1525 let value = Box::pin(self.evaluate_expression(expr)).await?;
1526 let json_value = self.value_to_json_value(&value);
1527 json_map.insert(key.clone(), json_value);
1528 }
1529 let json_obj = serde_json::Value::Object(json_map);
1530 Ok(serde_json::to_string(&json_obj)?)
1531 }
1532 fn value_to_json_value(&self, value: &crate::atp::value::Value) -> serde_json::Value {
1533 match value {
1534 crate::atp::value::Value::String(s) => serde_json::Value::String(s.clone()),
1535 crate::atp::value::Value::Number(n) => {
1536 serde_json::Number::from_f64(*n)
1537 .map(serde_json::Value::Number)
1538 .unwrap_or(serde_json::Value::Null)
1539 }
1540 crate::atp::value::Value::Bool(b) => serde_json::Value::Bool(*b),
1541 crate::atp::value::Value::Array(arr) => {
1542 let values: Vec<serde_json::Value> = arr
1543 .iter()
1544 .map(|v| self.value_to_json_value(v))
1545 .collect();
1546 serde_json::Value::Array(values)
1547 }
1548 crate::atp::value::Value::Object(obj) => {
1549 let mut map = serde_json::Map::new();
1550 for (k, v) in obj {
1551 map.insert(k.clone(), self.value_to_json_value(v));
1552 }
1553 serde_json::Value::Object(map)
1554 }
1555 crate::atp::value::Value::Null => serde_json::Value::Null,
1556 crate::atp::value::Value::Duration(d) => serde_json::Value::String(format!("{} {:?}", d.value, d.unit)),
1557 crate::atp::value::Value::Reference(r) => serde_json::Value::String(format!("@{}", r)),
1558 crate::atp::value::Value::Identifier(i) => serde_json::Value::String(i.clone()),
1559 }
1560 }
1561 pub async fn evaluate_expression(
1562 &mut self,
1563 expr: &Expression,
1564 ) -> Result<crate::atp::value::Value, Box<dyn std::error::Error + Send + Sync>> {
1565 match expr {
1566 Expression::String(s) => {
1567 if s.starts_with('@') || s.contains(" + ") || s.contains('?') {
1568 Ok(self.parse_value(s).await?)
1569 } else {
1570 Ok(crate::atp::value::Value::String(s.clone()))
1571 }
1572 }
1573 Expression::Number(n) => Ok(crate::atp::value::Value::Number(*n)),
1574 Expression::Bool(b) => Ok(crate::atp::value::Value::Bool(*b)),
1575 Expression::Array(arr) => {
1576 let mut values = Vec::new();
1577 for item in arr {
1578 values.push(Box::pin(self.evaluate_expression(item)).await?);
1579 }
1580 Ok(crate::atp::value::Value::Array(values))
1581 }
1582 Expression::Object(obj) => {
1583 let mut map = HashMap::new();
1584 for (key, expr) in obj {
1585 map.insert(
1586 key.clone(),
1587 Box::pin(self.evaluate_expression(expr)).await?,
1588 );
1589 }
1590 Ok(crate::atp::value::Value::Object(map))
1591 }
1592 Expression::OperatorCall(_operator, _key, _sub_key, _value) => {
1593 Err(
1594 Box::new(
1595 HlxError::validation_error(
1596 "OperatorCall not supported",
1597 "Use @ prefixed operators instead",
1598 ),
1599 ),
1600 )
1601 }
1602 Expression::AtOperatorCall(operator, params) => {
1603 match operator.as_str() {
1604 "env" => {
1605 let arg_expr = params
1606 .get("arg")
1607 .ok_or_else(|| HlxError::validation_error(
1608 "Missing argument for @env",
1609 "",
1610 ))?;
1611 let var_name = match arg_expr {
1612 Expression::String(s) => s.clone(),
1613 _ => {
1614 Box::pin(self.evaluate_expression(arg_expr))
1615 .await?
1616 .to_string()
1617 }
1618 };
1619 let val = self
1620 .runtime_context
1621 .get(&var_name)
1622 .cloned()
1623 .or_else(|| std::env::var(&var_name).ok())
1624 .ok_or_else(|| HlxError::validation_error(
1625 &format!("Env var '{}' not set", var_name),
1626 "",
1627 ))?;
1628 Ok(crate::atp::value::Value::String(val))
1629 }
1630 other => {
1631 let json_params = self.params_to_json(params).await?;
1632 self.execute_operator(&format!("@{}", other), &json_params).await
1633 }
1634 }
1635 }
1636 Expression::Identifier(name) => {
1637 let params = HashMap::new();
1638 let json_params = self.params_to_json(¶ms).await?;
1639 match self.execute_operator(&name, &json_params).await {
1640 Ok(value) => Ok(value),
1641 Err(_) => {
1642 let (clean_name, is_var) = Self::peel_markers(&name);
1643 Ok(
1644 crate::atp::value::Value::String(
1645 self.resolve_variable(&clean_name, is_var),
1646 ),
1647 )
1648 }
1649 }
1650 }
1651 _ => {
1652 Ok(
1653 crate::atp::value::Value::String(
1654 format!("Unsupported expression: {:?}", expr),
1655 ),
1656 )
1657 }
1658 }
1659 }
1660 pub async fn parse_value(
1661 &mut self,
1662 value: &str,
1663 ) -> Result<crate::atp::value::Value, Box<dyn std::error::Error + Send + Sync>> {
1664 let value = value.trim();
1665 let value = if value.ends_with(';') {
1666 value.trim_end_matches(';').trim()
1667 } else {
1668 value
1669 };
1670 match value {
1671 "true" => return Ok(crate::atp::value::Value::Bool(true)),
1672 "false" => return Ok(crate::atp::value::Value::Bool(false)),
1673 "null" => return Ok(crate::atp::value::Value::Null),
1674 _ => {}
1675 }
1676 if let Ok(num) = value.parse::<i64>() {
1677 return Ok(crate::atp::value::Value::Number(num as f64));
1678 }
1679 if let Ok(num) = value.parse::<f64>() {
1680 return Ok(crate::atp::value::Value::Number(num));
1681 }
1682 let operator_re = regex::Regex::new(r"^@([a-zA-Z_][a-zA-Z0-9_]*)\((.+)\)$")
1683 .unwrap();
1684 if let Some(captures) = operator_re.captures(value) {
1685 let operator = captures.get(1).unwrap().as_str();
1686 let params = captures.get(2).unwrap().as_str();
1687 return Ok(self.execute_operator(&format!("@{}", operator), params).await?);
1688 }
1689 if value.contains(" + ") {
1690 let parts: Vec<&str> = value.split(" + ").collect();
1691 let mut result = String::new();
1692 for part in parts {
1693 let part = part.trim().trim_matches('"').trim_matches('\'');
1694 result.push_str(&part);
1695 }
1696 return Ok(crate::atp::value::Value::String(result));
1697 }
1698 let ternary_re = regex::Regex::new(r"(.+?)\s*\?\s*(.+?)\s*:\s*(.+)").unwrap();
1699 if let Some(captures) = ternary_re.captures(value) {
1700 let condition = captures.get(1).unwrap().as_str().trim();
1701 let true_val = captures.get(2).unwrap().as_str().trim();
1702 let false_val = captures.get(3).unwrap().as_str().trim();
1703 if self.evaluate_condition(condition).await {
1704 return Box::pin(self.parse_value(true_val)).await;
1705 } else {
1706 return Box::pin(self.parse_value(false_val)).await;
1707 }
1708 }
1709 if (value.starts_with('"') && value.ends_with('"'))
1710 || (value.starts_with('\'') && value.ends_with('\''))
1711 {
1712 return Ok(
1713 crate::atp::value::Value::String(value[1..value.len() - 1].to_string()),
1714 );
1715 }
1716 Ok(crate::atp::value::Value::String(value.to_string()))
1717 }
1718 async fn evaluate_condition(&mut self, condition: &str) -> bool {
1719 let condition = condition.trim();
1720 if let Some(eq_pos) = condition.find("==") {
1721 let left = Box::pin(self.parse_value(condition[..eq_pos].trim()))
1722 .await
1723 .unwrap_or(crate::atp::value::Value::String("".to_string()));
1724 let right = Box::pin(self.parse_value(condition[eq_pos + 2..].trim()))
1725 .await
1726 .unwrap_or(crate::atp::value::Value::String("".to_string()));
1727 return left.to_string() == right.to_string();
1728 }
1729 if let Some(ne_pos) = condition.find("!=") {
1730 let left = Box::pin(self.parse_value(condition[..ne_pos].trim()))
1731 .await
1732 .unwrap_or(crate::atp::value::Value::String("".to_string()));
1733 let right = Box::pin(self.parse_value(condition[ne_pos + 2..].trim()))
1734 .await
1735 .unwrap_or(crate::atp::value::Value::String("".to_string()));
1736 return left.to_string() != right.to_string();
1737 }
1738 if let Some(gt_pos) = condition.find('>') {
1739 let left = Box::pin(self.parse_value(condition[..gt_pos].trim()))
1740 .await
1741 .unwrap_or(crate::atp::value::Value::String("".to_string()));
1742 let right = Box::pin(self.parse_value(condition[gt_pos + 1..].trim()))
1743 .await
1744 .unwrap_or(crate::atp::value::Value::String("".to_string()));
1745 if let (crate::atp::value::Value::Number(l), crate::atp::value::Value::Number(r)) = (
1746 &left,
1747 &right,
1748 ) {
1749 return l > r;
1750 }
1751 return left.to_string() > right.to_string();
1752 }
1753 let value = Box::pin(self.parse_value(condition))
1754 .await
1755 .unwrap_or(crate::atp::value::Value::String("".to_string()));
1756 match value {
1757 crate::atp::value::Value::Bool(b) => b,
1758 crate::atp::value::Value::String(s) => {
1759 !s.is_empty() && s != "false" && s != "null" && s != "0"
1760 }
1761 crate::atp::value::Value::Number(n) => n != 0.0,
1762 crate::atp::value::Value::Null => false,
1763 _ => true,
1764 }
1765 }
1766 fn parse_generic_declaration(
1767 &mut self,
1768 identifier: String,
1769 ) -> Result<Declaration, String> {
1770 let (name, block_kind) = self.parse_generic_variations(identifier)?;
1772 match block_kind {
1773 BlockKind::Brace => {
1774 self.expect(Token::LeftBrace)?;
1775 }
1776 BlockKind::Angle => {
1777 self.expect(Token::LessThan)?;
1778 }
1779 BlockKind::Bracket => {
1780 self.expect(Token::LeftBracket)?;
1781 }
1782 BlockKind::Colon => {
1783 self.expect(Token::Colon)?;
1784 let properties = self.parse_properties()?;
1785 self.expect(Token::Semicolon)?;
1786 return Ok(Declaration::Section(SectionDecl { name, properties }));
1787 }
1788 }
1789 let properties = self.parse_properties()?;
1790 match block_kind {
1791 BlockKind::Brace => {
1792 self.expect(Token::RightBrace)?;
1793 }
1794 BlockKind::Angle => {
1795 self.expect(Token::GreaterThan)?;
1796 }
1797 BlockKind::Bracket => {
1798 self.expect(Token::RightBracket)?;
1799 }
1800 BlockKind::Colon => {}
1801 }
1802 Ok(Declaration::Section(SectionDecl { name, properties }))
1803 }
1804 fn parse_generic_variations(
1805 &mut self,
1806 identifier: String,
1807 ) -> Result<(String, BlockKind), String> {
1808 let sub_name = match self.current_token() {
1809 Token::Identifier(s) => {
1810 let v = s.clone();
1811 self.advance();
1812 Some(v)
1813 }
1814 Token::String(s) => {
1815 let v = s.clone();
1816 self.advance();
1817 Some(v)
1818 }
1819 _ => None,
1820 };
1821 self.skip_newlines();
1822 let kind = match self.current_token() {
1823 Token::LeftBrace => BlockKind::Brace,
1824 Token::LessThan => BlockKind::Angle,
1825 Token::LeftBracket => BlockKind::Bracket,
1826 Token::Colon => BlockKind::Colon,
1827 _ => {
1828 return Err(
1829 format!(
1830 "Expected block delimiter after '{}', found {:?}", identifier,
1831 self.current_token()
1832 ),
1833 );
1834 }
1835 };
1836 match kind {
1837 BlockKind::Brace => {}
1838 BlockKind::Angle => {}
1839 BlockKind::Bracket => {}
1840 BlockKind::Colon => {
1841 }
1843 }
1844 Ok((self.build_full_name(&identifier, sub_name), kind))
1845 }
1846 fn parse_project_variations(&mut self) -> Result<(String, BlockKind), String> {
1847 self.parse_generic_variations("project".to_string())
1848 }
1849 fn convert_ops_value_to_types_value(&self, ops_value: crate::atp::value::Value) -> Value {
1850 match ops_value {
1851 crate::atp::value::Value::String(s) => Value::String(s),
1852 crate::atp::value::Value::Number(n) => Value::Number(n),
1853 crate::atp::value::Value::Bool(b) => Value::Bool(b),
1854 crate::atp::value::Value::Array(arr) => {
1855 Value::Array(arr.into_iter().map(|v| self.convert_ops_value_to_types_value(v)).collect())
1856 }
1857 crate::atp::value::Value::Object(obj) => {
1858 Value::Object(obj.into_iter().map(|(k, v)| (k, self.convert_ops_value_to_types_value(v))).collect())
1859 }
1860 crate::atp::value::Value::Null => Value::Null,
1861 crate::atp::value::Value::Duration(d) => Value::Duration(d),
1862 crate::atp::value::Value::Reference(r) => Value::Reference(r),
1863 crate::atp::value::Value::Identifier(i) => Value::Identifier(i),
1864 }
1865 }
1866}
1867pub fn parse(tokens: Vec<Token>) -> Result<HelixAst, ParseError> {
1868 let mut parser = Parser::new(tokens);
1869 parser
1870 .parse()
1871 .map_err(|msg| ParseError {
1872 message: msg,
1873 location: None,
1874 token_index: 0,
1875 expected: None,
1876 found: String::new(),
1877 context: String::new(),
1878 })
1879}