sea_core/parser/
ast.rs

1use crate::graph::Graph;
2use crate::parser::error::{ParseError, ParseResult};
3use crate::parser::{ParseOptions, Rule, SeaParser};
4use crate::patterns::Pattern;
5use crate::policy::{
6    AggregateFunction, BinaryOp, Expression, Policy, PolicyKind as CorePolicyKind,
7    PolicyModality as CorePolicyModality, Quantifier as PolicyQuantifier, UnaryOp, WindowSpec,
8};
9use crate::primitives::{ConceptChange, Entity, Flow, RelationType, Resource, Role, Severity};
10use crate::units::unit_from_string;
11use crate::SemanticVersion;
12use chrono::Duration;
13use pest::iterators::{Pair, Pairs};
14use pest::{Parser, Span};
15use rust_decimal::prelude::ToPrimitive;
16use rust_decimal::Decimal;
17use serde::{Deserialize, Serialize};
18use serde_json::json;
19use serde_json::Value as JsonValue;
20use std::collections::HashMap;
21
22/// File-level metadata from header annotations
23#[derive(Debug, Clone, PartialEq, Default)]
24pub struct FileMetadata {
25    pub namespace: Option<String>,
26    pub version: Option<String>,
27    pub owner: Option<String>,
28    pub profile: Option<String>,
29    pub imports: Vec<ImportDecl>,
30}
31
32/// Import declaration for a module file
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
34pub struct ImportDecl {
35    pub specifier: ImportSpecifier,
36    pub from_module: String,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
40pub enum ImportSpecifier {
41    Named(Vec<ImportItem>),
42    Wildcard(String),
43}
44
45#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
46pub struct ImportItem {
47    pub name: String,
48    pub alias: Option<String>,
49}
50
51/// Policy metadata
52#[derive(Debug, Clone, PartialEq)]
53pub struct PolicyMetadata {
54    pub kind: Option<PolicyKind>,
55    pub modality: Option<PolicyModality>,
56    pub priority: Option<i32>,
57    pub rationale: Option<String>,
58    pub tags: Vec<String>,
59}
60
61#[derive(Debug, Clone, PartialEq)]
62pub enum PolicyKind {
63    Constraint,
64    Derivation,
65    Obligation,
66}
67
68impl std::fmt::Display for PolicyKind {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        match self {
71            PolicyKind::Constraint => write!(f, "Constraint"),
72            PolicyKind::Derivation => write!(f, "Derivation"),
73            PolicyKind::Obligation => write!(f, "Obligation"),
74        }
75    }
76}
77
78#[derive(Debug, Clone, PartialEq)]
79pub enum PolicyModality {
80    Obligation,
81    Prohibition,
82    Permission,
83}
84
85impl std::fmt::Display for PolicyModality {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        match self {
88            PolicyModality::Obligation => write!(f, "Obligation"),
89            PolicyModality::Prohibition => write!(f, "Prohibition"),
90            PolicyModality::Permission => write!(f, "Permission"),
91        }
92    }
93}
94
95/// Metric declaration AST node
96#[derive(Debug, Clone, PartialEq)]
97pub struct MetricMetadata {
98    pub refresh_interval: Option<Duration>,
99    pub unit: Option<String>,
100    pub threshold: Option<Decimal>,
101    pub severity: Option<Severity>,
102    pub target: Option<Decimal>,
103    pub window: Option<Duration>,
104}
105
106#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
107pub enum TargetFormat {
108    Calm,
109    Kg,
110    Sbvr,
111    Protobuf,
112}
113
114impl std::fmt::Display for TargetFormat {
115    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116        match self {
117            TargetFormat::Calm => write!(f, "CALM"),
118            TargetFormat::Kg => write!(f, "KG"),
119            TargetFormat::Sbvr => write!(f, "SBVR"),
120            TargetFormat::Protobuf => write!(f, "Protobuf"),
121        }
122    }
123}
124
125#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
126pub struct MappingRule {
127    pub primitive_type: String,
128    pub primitive_name: String,
129    pub target_type: String,
130    pub fields: HashMap<String, JsonValue>,
131}
132
133#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
134pub struct ProjectionOverride {
135    pub primitive_type: String,
136    pub primitive_name: String,
137    pub fields: HashMap<String, JsonValue>,
138}
139
140/// Abstract Syntax Tree for SEA DSL
141#[derive(Debug, Clone, PartialEq)]
142pub struct Ast {
143    pub metadata: FileMetadata,
144    pub declarations: Vec<AstNode>,
145}
146
147/// AST Node types
148#[derive(Debug, Clone, PartialEq)]
149pub enum AstNode {
150    Export(Box<AstNode>),
151    Entity {
152        name: String,
153        version: Option<String>,
154        annotations: HashMap<String, JsonValue>,
155        domain: Option<String>,
156    },
157    Resource {
158        name: String,
159        unit_name: Option<String>,
160        domain: Option<String>,
161    },
162    Flow {
163        resource_name: String,
164        from_entity: String,
165        to_entity: String,
166        quantity: Option<i32>,
167    },
168    Pattern {
169        name: String,
170        regex: String,
171    },
172    Role {
173        name: String,
174        domain: Option<String>,
175    },
176    Relation {
177        name: String,
178        subject_role: String,
179        predicate: String,
180        object_role: String,
181        via_flow: Option<String>,
182    },
183    Dimension {
184        name: String,
185    },
186    UnitDeclaration {
187        symbol: String,
188        dimension: String,
189        factor: Decimal,
190        base_unit: String,
191    },
192    Policy {
193        name: String,
194        version: Option<String>,
195        metadata: PolicyMetadata,
196        expression: Expression,
197    },
198    Instance {
199        name: String,
200        entity_type: String,
201        fields: HashMap<String, Expression>,
202    },
203    ConceptChange {
204        name: String,
205        from_version: String,
206        to_version: String,
207        migration_policy: String,
208        breaking_change: bool,
209    },
210    Metric {
211        name: String,
212        expression: Expression,
213        metadata: MetricMetadata,
214    },
215    MappingDecl {
216        name: String,
217        target: TargetFormat,
218        rules: Vec<MappingRule>,
219    },
220    ProjectionDecl {
221        name: String,
222        target: TargetFormat,
223        overrides: Vec<ProjectionOverride>,
224    },
225}
226
227/// Parse source code into an AST
228pub fn parse_source(source: &str) -> ParseResult<Ast> {
229    let pairs = SeaParser::parse(Rule::program, source)?;
230    build_ast(pairs)
231}
232
233/// Build AST from pest pairs
234fn build_ast(pairs: Pairs<Rule>) -> ParseResult<Ast> {
235    let mut metadata = FileMetadata::default();
236    let mut declarations = Vec::new();
237
238    for pair in pairs {
239        match pair.as_rule() {
240            Rule::program => {
241                for inner in pair.into_inner() {
242                    match inner.as_rule() {
243                        Rule::file_header => {
244                            metadata = parse_file_header(inner)?;
245                        }
246                        Rule::declaration => {
247                            for decl in inner.into_inner() {
248                                let node = parse_declaration(decl)?;
249                                declarations.push(node);
250                            }
251                        }
252                        Rule::EOI => {}
253                        _ => {}
254                    }
255                }
256            }
257            Rule::EOI => {}
258            _ => {}
259        }
260    }
261
262    Ok(Ast {
263        metadata,
264        declarations,
265    })
266}
267
268/// Parse file header annotations
269fn parse_file_header(pair: Pair<Rule>) -> ParseResult<FileMetadata> {
270    let mut metadata = FileMetadata::default();
271
272    for annotation in pair.into_inner() {
273        match annotation.as_rule() {
274            Rule::annotation => {
275                let mut inner = annotation.into_inner();
276                let name = inner.next().ok_or_else(|| {
277                    ParseError::GrammarError("Expected annotation name".to_string())
278                })?;
279                let value = inner.next().ok_or_else(|| {
280                    ParseError::GrammarError("Expected annotation value".to_string())
281                })?;
282
283                let name_str = name.as_str().to_lowercase();
284                let value_str = parse_string_literal(value)?;
285
286                match name_str.as_str() {
287                    "namespace" => metadata.namespace = Some(value_str),
288                    "version" => metadata.version = Some(value_str),
289                    "owner" => metadata.owner = Some(value_str),
290                    "profile" => metadata.profile = Some(value_str),
291                    _ => {
292                        return Err(ParseError::GrammarError(format!(
293                            "Unknown annotation: {}",
294                            name_str
295                        )))
296                    }
297                }
298            }
299            Rule::import_decl => {
300                metadata.imports.push(parse_import_decl(annotation)?);
301            }
302            _ => {}
303        }
304    }
305
306    Ok(metadata)
307}
308
309/// Parse a single declaration
310fn parse_declaration(pair: Pair<Rule>) -> ParseResult<AstNode> {
311    match pair.as_rule() {
312        Rule::export_decl => {
313            let mut inner = pair.into_inner();
314            let wrapped = inner.next().ok_or_else(|| {
315                ParseError::GrammarError("Expected declaration after export".to_string())
316            })?;
317            let node = parse_declaration(wrapped)?;
318            Ok(AstNode::Export(Box::new(node)))
319        }
320        Rule::declaration_inner => {
321            let inner = pair
322                .into_inner()
323                .next()
324                .ok_or_else(|| ParseError::GrammarError("Empty declaration".to_string()))?;
325            parse_declaration(inner)
326        }
327        Rule::dimension_decl => parse_dimension(pair),
328        Rule::unit_decl => parse_unit_declaration(pair),
329        Rule::entity_decl => parse_entity(pair),
330        Rule::resource_decl => parse_resource(pair),
331        Rule::flow_decl => parse_flow(pair),
332        Rule::pattern_decl => parse_pattern(pair),
333        Rule::role_decl => parse_role(pair),
334        Rule::relation_decl => parse_relation(pair),
335        Rule::instance_decl => parse_instance(pair),
336        Rule::policy_decl => parse_policy(pair),
337        Rule::concept_change_decl => parse_concept_change(pair),
338        Rule::metric_decl => parse_metric(pair),
339        Rule::mapping_decl => parse_mapping(pair),
340        Rule::projection_decl => parse_projection(pair),
341        _ => Err(ParseError::GrammarError(format!(
342            "Unexpected rule: {:?}",
343            pair.as_rule()
344        ))),
345    }
346}
347
348fn parse_import_decl(pair: Pair<Rule>) -> ParseResult<ImportDecl> {
349    let mut inner = pair.into_inner();
350    let specifier_pair = inner
351        .next()
352        .ok_or_else(|| ParseError::GrammarError("Missing import specifier".to_string()))?;
353    let from_pair = inner
354        .next()
355        .ok_or_else(|| ParseError::GrammarError("Missing import source".to_string()))?;
356
357    let specifier = match specifier_pair.as_rule() {
358        Rule::import_specifier | Rule::import_named | Rule::import_wildcard => {
359            parse_import_specifier(specifier_pair)?
360        }
361        _ => {
362            return Err(ParseError::GrammarError(format!(
363                "Unexpected import specifier: {:?}",
364                specifier_pair.as_rule()
365            )))
366        }
367    };
368
369    Ok(ImportDecl {
370        specifier,
371        from_module: parse_string_literal(from_pair)?,
372    })
373}
374
375fn parse_import_specifier(pair: Pair<Rule>) -> ParseResult<ImportSpecifier> {
376    match pair.as_rule() {
377        Rule::import_wildcard => {
378            let mut inner = pair.into_inner();
379            let alias = parse_identifier(inner.next().ok_or_else(|| {
380                ParseError::GrammarError("Expected alias for wildcard import".to_string())
381            })?)?;
382            Ok(ImportSpecifier::Wildcard(alias))
383        }
384        Rule::import_specifier | Rule::import_named => {
385            let mut items = Vec::new();
386            for item in pair.into_inner() {
387                if item.as_rule() == Rule::import_item {
388                    items.push(parse_import_item(item)?);
389                }
390            }
391            Ok(ImportSpecifier::Named(items))
392        }
393        _ => Err(ParseError::GrammarError(
394            "Invalid import specifier".to_string(),
395        )),
396    }
397}
398
399fn parse_import_item(pair: Pair<Rule>) -> ParseResult<ImportItem> {
400    let mut inner = pair.into_inner();
401    let name_pair = inner
402        .next()
403        .ok_or_else(|| ParseError::GrammarError("Expected import item name".to_string()))?;
404    let alias = inner.next().map(parse_identifier).transpose()?;
405
406    Ok(ImportItem {
407        name: parse_identifier(name_pair)?,
408        alias,
409    })
410}
411
412/// Parse dimension declaration
413fn parse_dimension(pair: Pair<Rule>) -> ParseResult<AstNode> {
414    let mut inner = pair.into_inner();
415    let name = parse_string_literal(
416        inner
417            .next()
418            .ok_or_else(|| ParseError::GrammarError("Expected dimension name".to_string()))?,
419    )?;
420
421    Ok(AstNode::Dimension { name })
422}
423
424/// Parse unit declaration
425fn parse_unit_declaration(pair: Pair<Rule>) -> ParseResult<AstNode> {
426    let mut inner = pair.into_inner();
427
428    let symbol = parse_string_literal(
429        inner
430            .next()
431            .ok_or_else(|| ParseError::GrammarError("Expected unit symbol".to_string()))?,
432    )?;
433
434    let dimension = parse_string_literal(
435        inner
436            .next()
437            .ok_or_else(|| ParseError::GrammarError("Expected dimension name".to_string()))?,
438    )?;
439
440    let factor_pair = inner
441        .next()
442        .ok_or_else(|| ParseError::GrammarError("Expected factor".to_string()))?;
443    let factor = parse_decimal(factor_pair)?;
444
445    let base_unit = parse_string_literal(
446        inner
447            .next()
448            .ok_or_else(|| ParseError::GrammarError("Expected base unit".to_string()))?,
449    )?;
450
451    Ok(AstNode::UnitDeclaration {
452        symbol,
453        dimension,
454        factor,
455        base_unit,
456    })
457}
458
459/// Parse entity declaration
460fn parse_entity(pair: Pair<Rule>) -> ParseResult<AstNode> {
461    let mut inner = pair.into_inner();
462
463    let name = parse_name(
464        inner
465            .next()
466            .ok_or_else(|| ParseError::GrammarError("Expected entity name".to_string()))?,
467    )?;
468
469    let mut version = None;
470    let mut annotations = HashMap::new();
471    let mut domain = None;
472
473    for part in inner {
474        match part.as_rule() {
475            Rule::version => {
476                version = Some(part.as_str().to_string());
477            }
478            Rule::entity_annotation => {
479                let mut annotation_inner = part.into_inner();
480                let key_pair = annotation_inner
481                    .next()
482                    .ok_or_else(|| ParseError::GrammarError("Empty annotation".to_string()))?;
483
484                match key_pair.as_rule() {
485                    Rule::ea_replaces => {
486                        let target_name =
487                            parse_name(annotation_inner.next().ok_or_else(|| {
488                                ParseError::GrammarError("Expected name in replaces".to_string())
489                            })?)?;
490                        // Check for optional version
491                        let mut target_version = None;
492                        if let Some(next) = annotation_inner.next() {
493                            if next.as_rule() == Rule::version {
494                                target_version = Some(next.as_str().to_string());
495                            }
496                        }
497
498                        let value = if let Some(v) = target_version {
499                            format!("{} v{}", target_name, v)
500                        } else {
501                            target_name
502                        };
503                        annotations.insert("replaces".to_string(), JsonValue::String(value));
504                    }
505                    Rule::ea_changes => {
506                        let array_pair = annotation_inner.next().ok_or_else(|| {
507                            ParseError::GrammarError("Expected string array in changes".to_string())
508                        })?;
509                        let mut changes = Vec::new();
510                        for item in array_pair.into_inner() {
511                            changes.push(parse_string_literal(item)?);
512                        }
513                        annotations.insert(
514                            "changes".to_string(),
515                            JsonValue::Array(changes.into_iter().map(JsonValue::String).collect()),
516                        );
517                    }
518                    _ => {}
519                }
520            }
521            Rule::in_keyword => {
522                // Skip "in"
523            }
524            Rule::identifier => {
525                // This must be the domain
526                domain = Some(parse_identifier(part)?);
527            }
528            _ => {}
529        }
530    }
531
532    Ok(AstNode::Entity {
533        name,
534        version,
535        annotations,
536        domain,
537    })
538}
539
540/// Parse concept change declaration
541fn parse_concept_change(pair: Pair<Rule>) -> ParseResult<AstNode> {
542    let mut inner = pair.into_inner();
543
544    let name =
545        parse_name(inner.next().ok_or_else(|| {
546            ParseError::GrammarError("Expected concept change name".to_string())
547        })?)?;
548
549    let mut from_version = String::new();
550    let mut to_version = String::new();
551    let mut migration_policy = String::new();
552    let mut breaking_change = false;
553
554    for part in inner {
555        if part.as_rule() == Rule::concept_change_annotation {
556            let mut annotation_inner = part.into_inner();
557
558            let key_pair = annotation_inner
559                .next()
560                .ok_or_else(|| ParseError::GrammarError("Expected annotation key".to_string()))?;
561            let value_pair = annotation_inner
562                .next()
563                .ok_or_else(|| ParseError::GrammarError("Expected annotation value".to_string()))?;
564
565            match key_pair.as_rule() {
566                Rule::cc_from_version => from_version = parse_version(value_pair)?,
567                Rule::cc_to_version => to_version = parse_version(value_pair)?,
568                Rule::cc_migration_policy => migration_policy = parse_identifier(value_pair)?,
569                Rule::cc_breaking_change => {
570                    breaking_change = value_pair.as_str() == "true";
571                }
572                _ => {}
573            }
574        }
575    }
576
577    if from_version.is_empty() {
578        return Err(ParseError::GrammarError(
579            "Missing cc_from_version annotation".to_string(),
580        ));
581    }
582
583    if to_version.is_empty() {
584        return Err(ParseError::GrammarError(
585            "Missing cc_to_version annotation".to_string(),
586        ));
587    }
588
589    if migration_policy.is_empty() {
590        return Err(ParseError::GrammarError(
591            "Missing cc_migration_policy annotation".to_string(),
592        ));
593    }
594
595    Ok(AstNode::ConceptChange {
596        name,
597        from_version,
598        to_version,
599        migration_policy,
600        breaking_change,
601    })
602}
603
604/// Parse resource declaration
605fn parse_resource(pair: Pair<Rule>) -> ParseResult<AstNode> {
606    let mut inner = pair.into_inner();
607
608    let name = parse_name(
609        inner
610            .next()
611            .ok_or_else(|| ParseError::GrammarError("Expected resource name".to_string()))?,
612    )?;
613
614    let mut unit_name = None;
615    let mut domain = None;
616
617    // The grammar produces these patterns (with in_keyword as a separate token):
618    // 1. string_literal + identifier + in_keyword + identifier = unit + domain
619    // 2. string_literal + in_keyword + identifier = domain only
620    // 3. string_literal + identifier = unit only
621    // 4. string_literal only = nothing
622
623    if let Some(first) = inner.next() {
624        match first.as_rule() {
625            Rule::in_keyword => {
626                // Case 2: in_keyword + identifier (domain only)
627                domain = Some(parse_identifier(inner.next().ok_or_else(|| {
628                    ParseError::GrammarError("Expected domain after 'in'".to_string())
629                })?)?);
630            }
631            Rule::identifier => {
632                // Case 1 or 3: starts with identifier
633                unit_name = Some(parse_identifier(first)?);
634
635                // Check if followed by in_keyword + identifier
636                if let Some(second) = inner.next() {
637                    if second.as_rule() == Rule::in_keyword {
638                        // Case 1: identifier + in_keyword + identifier
639                        domain = Some(parse_identifier(inner.next().ok_or_else(|| {
640                            ParseError::GrammarError("Expected domain after 'in'".to_string())
641                        })?)?);
642                    }
643                    // If second is not in_keyword, it's unexpected (grammar shouldn't allow this)
644                }
645                // If no second token, it's case 3 (unit only)
646            }
647            _ => {
648                return Err(ParseError::GrammarError(
649                    "Unexpected token in resource declaration".to_string(),
650                ));
651            }
652        }
653    }
654
655    Ok(AstNode::Resource {
656        name,
657        unit_name,
658        domain,
659    })
660}
661
662/// Parse flow declaration
663fn parse_flow(pair: Pair<Rule>) -> ParseResult<AstNode> {
664    let mut inner = pair.into_inner();
665
666    let resource_name = parse_string_literal(
667        inner
668            .next()
669            .ok_or_else(|| ParseError::GrammarError("Expected resource name".to_string()))?,
670    )?;
671
672    let from_entity = parse_string_literal(
673        inner
674            .next()
675            .ok_or_else(|| ParseError::GrammarError("Expected from entity".to_string()))?,
676    )?;
677
678    let to_entity = parse_string_literal(
679        inner
680            .next()
681            .ok_or_else(|| ParseError::GrammarError("Expected to entity".to_string()))?,
682    )?;
683
684    let quantity = if let Some(qty_pair) = inner.next() {
685        Some(parse_number(qty_pair)?)
686    } else {
687        None
688    };
689
690    Ok(AstNode::Flow {
691        resource_name,
692        from_entity,
693        to_entity,
694        quantity,
695    })
696}
697
698/// Parse pattern declaration
699fn parse_pattern(pair: Pair<Rule>) -> ParseResult<AstNode> {
700    let mut inner = pair.into_inner();
701
702    let name = parse_name(
703        inner
704            .next()
705            .ok_or_else(|| ParseError::GrammarError("Expected pattern name".to_string()))?,
706    )?;
707
708    let regex_literal = inner
709        .next()
710        .ok_or_else(|| ParseError::GrammarError("Expected regex for pattern".to_string()))?;
711    let regex = parse_string_literal(regex_literal)?;
712
713    Ok(AstNode::Pattern { name, regex })
714}
715
716/// Parse role declaration
717fn parse_role(pair: Pair<Rule>) -> ParseResult<AstNode> {
718    let mut inner = pair.into_inner();
719
720    let name = parse_name(
721        inner
722            .next()
723            .ok_or_else(|| ParseError::GrammarError("Expected role name".to_string()))?,
724    )?;
725
726    let domain = if let Some(domain_pair) = inner.next() {
727        Some(parse_identifier(domain_pair)?)
728    } else {
729        None
730    };
731
732    Ok(AstNode::Role { name, domain })
733}
734
735/// Parse relation declaration
736fn parse_relation(pair: Pair<Rule>) -> ParseResult<AstNode> {
737    let mut inner = pair.into_inner();
738
739    let name = parse_name(
740        inner
741            .next()
742            .ok_or_else(|| ParseError::GrammarError("Expected relation name".to_string()))?,
743    )?;
744
745    let subject_literal = inner
746        .next()
747        .ok_or_else(|| ParseError::GrammarError("Expected subject role in relation".to_string()))?;
748    let subject_role = parse_string_literal(subject_literal)?;
749
750    let predicate_literal = inner
751        .next()
752        .ok_or_else(|| ParseError::GrammarError("Expected predicate in relation".to_string()))?;
753    let predicate = parse_string_literal(predicate_literal)?;
754
755    let object_literal = inner
756        .next()
757        .ok_or_else(|| ParseError::GrammarError("Expected object role in relation".to_string()))?;
758    let object_role = parse_string_literal(object_literal)?;
759
760    let via_flow = if let Some(via_pair) = inner.next() {
761        match via_pair.as_rule() {
762            Rule::string_literal => Some(parse_string_literal(via_pair)?),
763            _ => {
764                let mut via_inner = via_pair.into_inner();
765                let flow_literal = via_inner.next().ok_or_else(|| {
766                    ParseError::GrammarError("Expected flow name after via".to_string())
767                })?;
768                Some(parse_string_literal(flow_literal)?)
769            }
770        }
771    } else {
772        None
773    };
774
775    Ok(AstNode::Relation {
776        name,
777        subject_role,
778        predicate,
779        object_role,
780        via_flow,
781    })
782}
783
784/// Parse instance declaration
785fn parse_instance(pair: Pair<Rule>) -> ParseResult<AstNode> {
786    let mut inner = pair.into_inner();
787
788    let name = parse_identifier(
789        inner
790            .next()
791            .ok_or_else(|| ParseError::GrammarError("Expected instance name".to_string()))?,
792    )?;
793
794    let entity_type = parse_string_literal(
795        inner
796            .next()
797            .ok_or_else(|| ParseError::GrammarError("Expected entity type".to_string()))?,
798    )?;
799
800    let mut fields = HashMap::new();
801
802    // Parse optional instance body
803    if let Some(body_pair) = inner.next() {
804        if body_pair.as_rule() == Rule::instance_body {
805            for field_pair in body_pair.into_inner() {
806                if field_pair.as_rule() == Rule::instance_field {
807                    let span = field_pair.as_span();
808                    let mut field_inner = field_pair.into_inner();
809
810                    let field_name = parse_identifier(field_inner.next().ok_or_else(|| {
811                        ParseError::GrammarError("Expected field name".to_string())
812                    })?)?;
813
814                    if fields.contains_key(&field_name) {
815                        let (line, column) = span.start_pos().line_col();
816                        return Err(ParseError::GrammarError(format!(
817                            "Duplicate field name '{}' at line {}, column {}",
818                            field_name, line, column
819                        )));
820                    }
821
822                    let field_value = parse_expression(field_inner.next().ok_or_else(|| {
823                        ParseError::GrammarError("Expected field value".to_string())
824                    })?)?;
825
826                    fields.insert(field_name, field_value);
827                }
828            }
829        }
830    }
831
832    Ok(AstNode::Instance {
833        name,
834        entity_type,
835        fields,
836    })
837}
838
839/// Parse policy declaration
840fn parse_policy(pair: Pair<Rule>) -> ParseResult<AstNode> {
841    let mut inner = pair.into_inner();
842
843    let name = parse_identifier(
844        inner
845            .next()
846            .ok_or_else(|| ParseError::GrammarError("Expected policy name".to_string()))?,
847    )?;
848
849    let mut metadata = PolicyMetadata {
850        kind: None,
851        modality: None,
852        priority: None,
853        rationale: None,
854        tags: Vec::new(),
855    };
856    let mut version: Option<String> = None;
857
858    for next_pair in inner {
859        match next_pair.as_rule() {
860            Rule::policy_kind => {
861                metadata.kind = Some(match next_pair.as_str().to_lowercase().as_str() {
862                    "constraint" => PolicyKind::Constraint,
863                    "derivation" => PolicyKind::Derivation,
864                    "obligation" => PolicyKind::Obligation,
865                    _ => {
866                        return Err(ParseError::GrammarError(format!(
867                            "Unknown policy kind: {}",
868                            next_pair.as_str()
869                        )))
870                    }
871                });
872            }
873            Rule::policy_modality => {
874                metadata.modality = Some(match next_pair.as_str().to_lowercase().as_str() {
875                    "obligation" => PolicyModality::Obligation,
876                    "prohibition" => PolicyModality::Prohibition,
877                    "permission" => PolicyModality::Permission,
878                    _ => {
879                        return Err(ParseError::GrammarError(format!(
880                            "Unknown policy modality: {}",
881                            next_pair.as_str()
882                        )))
883                    }
884                });
885            }
886            Rule::number => {
887                metadata.priority = Some(parse_number(next_pair)?);
888            }
889            Rule::policy_annotation => {
890                parse_policy_annotation(next_pair, &mut metadata)?;
891            }
892            Rule::version => {
893                version = Some(next_pair.as_str().to_string());
894            }
895            Rule::expression => {
896                let expression = parse_expression(next_pair)?;
897                return Ok(AstNode::Policy {
898                    name,
899                    version,
900                    metadata,
901                    expression,
902                });
903            }
904            _ => {}
905        }
906    }
907
908    Err(ParseError::GrammarError(
909        "Policy missing expression".to_string(),
910    ))
911}
912
913fn parse_policy_annotation(pair: Pair<Rule>, metadata: &mut PolicyMetadata) -> ParseResult<()> {
914    let mut inner = pair.into_inner();
915
916    let name = inner
917        .next()
918        .ok_or_else(|| ParseError::GrammarError("Expected annotation name".to_string()))?;
919    let value = inner
920        .next()
921        .ok_or_else(|| ParseError::GrammarError("Expected annotation value".to_string()))?;
922
923    let name_str = name.as_str().to_lowercase();
924
925    match name_str.as_str() {
926        "rationale" => {
927            metadata.rationale = Some(parse_string_literal(value)?);
928        }
929        "tags" => {
930            if value.as_rule() == Rule::string_array {
931                for tag_pair in value.into_inner() {
932                    if tag_pair.as_rule() == Rule::string_literal {
933                        metadata.tags.push(parse_string_literal(tag_pair)?);
934                    }
935                }
936            } else {
937                metadata.tags.push(parse_string_literal(value)?);
938            }
939        }
940        _ => {
941            return Err(ParseError::GrammarError(format!(
942                "Unknown policy annotation: {}",
943                name_str
944            )))
945        }
946    }
947
948    Ok(())
949}
950
951/// Parse expression
952fn parse_expression(pair: Pair<Rule>) -> ParseResult<Expression> {
953    match pair.as_rule() {
954        Rule::expression => {
955            let inner = pair
956                .into_inner()
957                .next()
958                .ok_or_else(|| ParseError::GrammarError("Empty expression".to_string()))?;
959            parse_expression(inner)
960        }
961        Rule::or_expr => parse_or_expr(pair),
962        Rule::and_expr => parse_and_expr(pair),
963        Rule::not_expr => parse_not_expr(pair),
964        Rule::comparison_expr => parse_comparison_expr(pair),
965        Rule::additive_expr => parse_additive_expr(pair),
966        Rule::multiplicative_expr => parse_multiplicative_expr(pair),
967        Rule::unary_expr => parse_unary_expr(pair),
968        Rule::cast_expr => parse_cast_expr(pair),
969        Rule::primary_expr => parse_primary_expr(pair),
970        _ => Err(ParseError::InvalidExpression(format!(
971            "Unexpected expression rule: {:?}",
972            pair.as_rule()
973        ))),
974    }
975}
976
977/// Parse a single expression string into an Expression AST node.
978pub fn parse_expression_from_str(source: &str) -> ParseResult<Expression> {
979    let pairs = SeaParser::parse(Rule::expression, source)
980        .map_err(|e| ParseError::GrammarError(format!("Parse error: {}", e)))?;
981    let parsed_pairs: Vec<_> = pairs.collect();
982
983    if parsed_pairs.is_empty() {
984        return Err(ParseError::GrammarError("Empty expression".to_string()));
985    }
986    if parsed_pairs.len() > 1 {
987        return Err(ParseError::GrammarError(
988            "Trailing input detected after expression".to_string(),
989        ));
990    }
991
992    let pair = parsed_pairs.into_iter().next().unwrap();
993    parse_expression(pair)
994}
995
996/// Parse OR expression
997fn parse_or_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
998    let mut inner = pair.into_inner();
999    let mut left =
1000        parse_expression(inner.next().ok_or_else(|| {
1001            ParseError::GrammarError("Expected left expression in OR".to_string())
1002        })?)?;
1003
1004    for right_pair in inner {
1005        let right = parse_expression(right_pair)?;
1006        left = Expression::Binary {
1007            left: Box::new(left),
1008            op: BinaryOp::Or,
1009            right: Box::new(right),
1010        };
1011    }
1012
1013    Ok(left)
1014}
1015
1016/// Parse AND expression
1017fn parse_and_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1018    let mut inner = pair.into_inner();
1019    let mut left =
1020        parse_expression(inner.next().ok_or_else(|| {
1021            ParseError::GrammarError("Expected left expression in AND".to_string())
1022        })?)?;
1023
1024    for right_pair in inner {
1025        let right = parse_expression(right_pair)?;
1026        left = Expression::Binary {
1027            left: Box::new(left),
1028            op: BinaryOp::And,
1029            right: Box::new(right),
1030        };
1031    }
1032
1033    Ok(left)
1034}
1035
1036/// Parse NOT expression
1037fn parse_not_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1038    let mut inner = pair.into_inner();
1039    let first = inner
1040        .next()
1041        .ok_or_else(|| ParseError::GrammarError("Expected expression in NOT".to_string()))?;
1042
1043    // Check if this is actually a NOT expression or just a comparison_expr
1044    if first.as_rule() == Rule::not_expr {
1045        // This is a recursive NOT, parse it
1046        let expr = parse_expression(first)?;
1047        Ok(Expression::Unary {
1048            op: UnaryOp::Not,
1049            operand: Box::new(expr),
1050        })
1051    } else {
1052        // This is just a comparison_expr, parse it directly
1053        parse_expression(first)
1054    }
1055}
1056
1057/// Parse comparison expression
1058fn parse_comparison_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1059    let mut inner = pair.into_inner();
1060    let mut left = parse_expression(inner.next().ok_or_else(|| {
1061        ParseError::GrammarError("Expected left expression in comparison".to_string())
1062    })?)?;
1063
1064    if let Some(op_pair) = inner.next() {
1065        let op = parse_comparison_op(op_pair)?;
1066        let right = parse_expression(inner.next().ok_or_else(|| {
1067            ParseError::GrammarError("Expected right expression in comparison".to_string())
1068        })?)?;
1069        left = Expression::Binary {
1070            left: Box::new(left),
1071            op,
1072            right: Box::new(right),
1073        };
1074    }
1075
1076    Ok(left)
1077}
1078
1079/// Parse comparison operator
1080fn parse_comparison_op(pair: Pair<Rule>) -> ParseResult<BinaryOp> {
1081    let op_str = pair.as_str();
1082    match op_str {
1083        "=" => Ok(BinaryOp::Equal),
1084        "!=" => Ok(BinaryOp::NotEqual),
1085        ">" => Ok(BinaryOp::GreaterThan),
1086        "<" => Ok(BinaryOp::LessThan),
1087        ">=" => Ok(BinaryOp::GreaterThanOrEqual),
1088        "<=" => Ok(BinaryOp::LessThanOrEqual),
1089        _ if op_str.eq_ignore_ascii_case("contains") => Ok(BinaryOp::Contains),
1090        _ if op_str.eq_ignore_ascii_case("startswith") => Ok(BinaryOp::StartsWith),
1091        _ if op_str.eq_ignore_ascii_case("endswith") => Ok(BinaryOp::EndsWith),
1092        _ if op_str.eq_ignore_ascii_case("matches") => Ok(BinaryOp::Matches),
1093        _ if op_str.eq_ignore_ascii_case("before") => Ok(BinaryOp::Before),
1094        _ if op_str.eq_ignore_ascii_case("after") => Ok(BinaryOp::After),
1095        _ if op_str.eq_ignore_ascii_case("during") => Ok(BinaryOp::During),
1096        _ if op_str.eq_ignore_ascii_case("has_role") => Ok(BinaryOp::HasRole),
1097        _ => Err(ParseError::InvalidExpression(format!(
1098            "Unknown comparison operator: {}",
1099            op_str
1100        ))),
1101    }
1102}
1103
1104/// Parse additive expression
1105fn parse_additive_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1106    let mut inner = pair.into_inner();
1107    let mut left = parse_expression(inner.next().ok_or_else(|| {
1108        ParseError::GrammarError("Expected left expression in additive".to_string())
1109    })?)?;
1110
1111    while let Some(op_pair) = inner.next() {
1112        let op = match op_pair.as_str() {
1113            "+" => BinaryOp::Plus,
1114            "-" => BinaryOp::Minus,
1115            _ => {
1116                return Err(ParseError::InvalidExpression(
1117                    "Invalid additive operator".to_string(),
1118                ))
1119            }
1120        };
1121        let right = parse_expression(inner.next().ok_or_else(|| {
1122            ParseError::GrammarError("Expected right expression in additive".to_string())
1123        })?)?;
1124        left = Expression::Binary {
1125            left: Box::new(left),
1126            op,
1127            right: Box::new(right),
1128        };
1129    }
1130
1131    Ok(left)
1132}
1133
1134/// Parse multiplicative expression
1135fn parse_multiplicative_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1136    let mut inner = pair.into_inner();
1137    let mut left = parse_expression(inner.next().ok_or_else(|| {
1138        ParseError::GrammarError("Expected left expression in multiplicative".to_string())
1139    })?)?;
1140
1141    while let Some(op_pair) = inner.next() {
1142        let op = match op_pair.as_str() {
1143            "*" => BinaryOp::Multiply,
1144            "/" => BinaryOp::Divide,
1145            _ => {
1146                return Err(ParseError::InvalidExpression(
1147                    "Invalid multiplicative operator".to_string(),
1148                ))
1149            }
1150        };
1151        let right = parse_expression(inner.next().ok_or_else(|| {
1152            ParseError::GrammarError("Expected right expression in multiplicative".to_string())
1153        })?)?;
1154        left = Expression::Binary {
1155            left: Box::new(left),
1156            op,
1157            right: Box::new(right),
1158        };
1159    }
1160
1161    Ok(left)
1162}
1163
1164/// Parse cast expression
1165fn parse_cast_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1166    let mut inner = pair.into_inner();
1167    let primary = parse_expression(inner.next().ok_or_else(|| {
1168        ParseError::GrammarError("Expected primary expression in cast".to_string())
1169    })?)?;
1170
1171    if let Some(as_pair) = inner.next() {
1172        let target_type = parse_string_literal(as_pair)?;
1173        Ok(Expression::cast(primary, target_type))
1174    } else {
1175        Ok(primary)
1176    }
1177}
1178
1179/// Parse unary expression
1180fn parse_unary_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1181    let mut inner = pair.into_inner();
1182    let first = inner
1183        .next()
1184        .ok_or_else(|| ParseError::GrammarError("Expected expression in unary".to_string()))?;
1185
1186    if first.as_str() == "-" {
1187        // Unary minus
1188        let expr = parse_expression(inner.next().ok_or_else(|| {
1189            ParseError::GrammarError("Expected expression after unary minus".to_string())
1190        })?)?;
1191        Ok(Expression::Unary {
1192            op: UnaryOp::Negate,
1193            operand: Box::new(expr),
1194        })
1195    } else {
1196        parse_expression(first)
1197    }
1198}
1199
1200/// Parse primary expression
1201fn parse_primary_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1202    let inner = pair.into_inner().next().ok_or_else(|| {
1203        ParseError::GrammarError("Expected inner expression in primary".to_string())
1204    })?;
1205
1206    match inner.as_rule() {
1207        Rule::expression => parse_expression(inner),
1208        Rule::group_by_expr => parse_group_by_expr(inner),
1209        Rule::aggregation_expr => parse_aggregation_expr(inner),
1210        Rule::quantified_expr => parse_quantified_expr(inner),
1211        Rule::member_access => parse_member_access(inner),
1212        Rule::literal => parse_literal_expr(inner),
1213        Rule::identifier => {
1214            let name = parse_identifier(inner)?;
1215            Ok(Expression::Variable(name))
1216        }
1217        _ => Err(ParseError::InvalidExpression(format!(
1218            "Unexpected primary expression: {:?}",
1219            inner.as_rule()
1220        ))),
1221    }
1222}
1223
1224/// Parse aggregation expression
1225fn parse_aggregation_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1226    let mut inner = pair.into_inner();
1227
1228    let function_pair = inner.next().ok_or_else(|| {
1229        ParseError::GrammarError(
1230            "Expected aggregate function in aggregation expression".to_string(),
1231        )
1232    })?;
1233    let function = parse_aggregate_fn(function_pair)?;
1234
1235    let collection_pair = inner.next().ok_or_else(|| {
1236        ParseError::GrammarError("Expected collection in aggregation expression".to_string())
1237    })?;
1238
1239    // Aggregation can be a simple form (e.g., sum(flows), sum(flows.quantity))
1240    // or the comprehension form (e.g., sum(f in flows where f.resource = "Money": f.quantity as "USD")).
1241    if collection_pair.as_rule() == Rule::aggregation_comprehension {
1242        // Parse aggregation comprehension
1243        let mut comp_inner = collection_pair.into_inner();
1244        let variable_pair = comp_inner.next().ok_or_else(|| {
1245            ParseError::GrammarError("Expected variable in aggregation comprehension".to_string())
1246        })?;
1247        let variable = parse_identifier(variable_pair)?;
1248        // Next token should be collection
1249        let collection_token = comp_inner.next().ok_or_else(|| {
1250            ParseError::GrammarError("Expected collection in aggregation comprehension".to_string())
1251        })?;
1252        let collection_name = parse_collection(collection_token)?;
1253        let collection = Box::new(Expression::Variable(collection_name));
1254
1255        let mut next_pair = comp_inner.next().ok_or_else(|| {
1256            ParseError::GrammarError(
1257                "Expected predicate expression, projection, or window in aggregation comprehension"
1258                    .to_string(),
1259            )
1260        })?;
1261
1262        let mut window = None;
1263        if next_pair.as_rule() == Rule::window_clause {
1264            window = Some(parse_window_clause(next_pair)?);
1265            next_pair = comp_inner.next().ok_or_else(|| {
1266                ParseError::GrammarError(
1267                    "Expected predicate or projection expression in aggregation comprehension"
1268                        .to_string(),
1269                )
1270            })?;
1271        }
1272
1273        let remaining_pairs: Vec<Pair<Rule>> =
1274            std::iter::once(next_pair).chain(comp_inner).collect();
1275
1276        let mut expr_pairs: Vec<Pair<Rule>> = Vec::new();
1277        let mut target_unit: Option<String> = None;
1278        for pair in remaining_pairs {
1279            match pair.as_rule() {
1280                Rule::expression => expr_pairs.push(pair),
1281                Rule::string_literal => {
1282                    target_unit = Some(parse_string_literal(pair)?);
1283                }
1284                Rule::identifier if pair.as_str().eq_ignore_ascii_case("as") => {
1285                    // skip explicit AS token
1286                }
1287                other => {
1288                    return Err(ParseError::GrammarError(format!(
1289                        "Unexpected token {:?} in aggregation comprehension",
1290                        other
1291                    )))
1292                }
1293            }
1294        }
1295
1296        let (predicate, projection) = match expr_pairs.len() {
1297            2 => {
1298                let mut expr_iter = expr_pairs.into_iter();
1299                let predicate_expr = parse_expression(expr_iter.next().ok_or_else(|| {
1300                    ParseError::GrammarError(
1301                        "Expected predicate expression in aggregation comprehension".to_string(),
1302                    )
1303                })?)?;
1304                let projection_expr = parse_expression(expr_iter.next().ok_or_else(|| {
1305                    ParseError::GrammarError(
1306                        "Expected projection expression in aggregation comprehension".to_string(),
1307                    )
1308                })?)?;
1309                (predicate_expr, projection_expr)
1310            }
1311            1 => {
1312                let projection_expr =
1313                    parse_expression(expr_pairs.into_iter().next().ok_or_else(|| {
1314                        ParseError::GrammarError(
1315                            "Expected projection expression in aggregation comprehension"
1316                                .to_string(),
1317                        )
1318                    })?)?;
1319                (Expression::Literal(JsonValue::Bool(true)), projection_expr)
1320            }
1321            other => {
1322                return Err(ParseError::GrammarError(format!(
1323                    "Unexpected number of expressions in aggregation comprehension: {}",
1324                    other
1325                )))
1326            }
1327        };
1328
1329        return Ok(Expression::AggregationComprehension {
1330            function,
1331            variable,
1332            collection,
1333            window,
1334            predicate: Box::new(predicate),
1335            projection: Box::new(projection),
1336            target_unit,
1337        });
1338    }
1339
1340    // Parse aggregation_simple
1341    let mut simple_inner = collection_pair.into_inner();
1342
1343    // First item is either collection or identifier
1344    let first_pair = simple_inner.next().ok_or_else(|| {
1345        ParseError::GrammarError(
1346            "Expected collection or identifier in aggregation_simple".to_string(),
1347        )
1348    })?;
1349
1350    let collection = match first_pair.as_rule() {
1351        Rule::collection => parse_collection(first_pair)?,
1352        Rule::identifier => parse_identifier(first_pair)?,
1353        _ => {
1354            return Err(ParseError::GrammarError(format!(
1355                "Expected collection or identifier, got {:?}",
1356                first_pair.as_rule()
1357            )))
1358        }
1359    };
1360
1361    let mut field: Option<String> = None;
1362    let mut filter: Option<Expression> = None;
1363
1364    // Parse optional field and filter
1365    for item in simple_inner {
1366        match item.as_rule() {
1367            Rule::identifier => {
1368                field = Some(parse_identifier(item)?);
1369            }
1370            Rule::expression => {
1371                filter = Some(parse_expression(item)?);
1372            }
1373            _ => {}
1374        }
1375    }
1376
1377    Ok(Expression::aggregation(
1378        function,
1379        Expression::Variable(collection),
1380        field,
1381        filter,
1382    ))
1383}
1384
1385/// Parse aggregate function
1386fn parse_aggregate_fn(pair: Pair<Rule>) -> ParseResult<AggregateFunction> {
1387    let fn_str = pair.as_str();
1388    match fn_str.to_lowercase().as_str() {
1389        "count" => Ok(AggregateFunction::Count),
1390        "sum" => Ok(AggregateFunction::Sum),
1391        "min" => Ok(AggregateFunction::Min),
1392        "max" => Ok(AggregateFunction::Max),
1393        "avg" => Ok(AggregateFunction::Avg),
1394        _ => Err(ParseError::InvalidExpression(format!(
1395            "Unknown aggregate function: {}",
1396            fn_str
1397        ))),
1398    }
1399}
1400
1401/// Parse quantified expression
1402fn parse_quantified_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1403    let mut inner = pair.into_inner();
1404
1405    let quantifier = parse_quantifier(inner.next().ok_or_else(|| {
1406        ParseError::GrammarError("Expected quantifier in quantified expression".to_string())
1407    })?)?;
1408    let variable = parse_identifier(inner.next().ok_or_else(|| {
1409        ParseError::GrammarError(
1410            "Expected variable identifier in quantified expression".to_string(),
1411        )
1412    })?)?;
1413    let collection = parse_collection(inner.next().ok_or_else(|| {
1414        ParseError::GrammarError(
1415            "Expected collection identifier in quantified expression".to_string(),
1416        )
1417    })?)?;
1418    let condition = parse_expression(inner.next().ok_or_else(|| {
1419        ParseError::GrammarError("Expected quantified condition expression".to_string())
1420    })?)?;
1421
1422    Ok(Expression::Quantifier {
1423        quantifier,
1424        variable,
1425        collection: Box::new(Expression::Variable(collection)),
1426        condition: Box::new(condition),
1427    })
1428}
1429
1430/// Parse quantifier
1431fn parse_quantifier(pair: Pair<Rule>) -> ParseResult<PolicyQuantifier> {
1432    let q_str = pair.as_str();
1433    match q_str.to_lowercase().as_str() {
1434        "forall" => Ok(PolicyQuantifier::ForAll),
1435        "exists" => Ok(PolicyQuantifier::Exists),
1436        "exists_unique" => Ok(PolicyQuantifier::ExistsUnique),
1437        _ => Err(ParseError::InvalidExpression(format!(
1438            "Unknown quantifier: {}",
1439            q_str
1440        ))),
1441    }
1442}
1443
1444/// Parse collection type
1445fn parse_collection(pair: Pair<Rule>) -> ParseResult<String> {
1446    Ok(pair.as_str().to_lowercase())
1447}
1448
1449/// Parse member access
1450fn parse_member_access(pair: Pair<Rule>) -> ParseResult<Expression> {
1451    let mut inner = pair.into_inner();
1452    let object = parse_identifier(inner.next().ok_or_else(|| {
1453        ParseError::GrammarError("Expected object identifier in member access".to_string())
1454    })?)?;
1455    let member = parse_identifier(inner.next().ok_or_else(|| {
1456        ParseError::GrammarError("Expected member identifier in member access".to_string())
1457    })?)?;
1458
1459    Ok(Expression::MemberAccess { object, member })
1460}
1461
1462/// Parse literal expression
1463fn parse_literal_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1464    let inner = pair
1465        .into_inner()
1466        .next()
1467        .ok_or_else(|| ParseError::GrammarError("Expected literal content".to_string()))?;
1468
1469    match inner.as_rule() {
1470        Rule::string_literal => {
1471            let s = parse_string_literal(inner)?;
1472            Ok(Expression::Literal(JsonValue::String(s)))
1473        }
1474        Rule::multiline_string => {
1475            let s = parse_multiline_string(inner)?;
1476            Ok(Expression::Literal(JsonValue::String(s)))
1477        }
1478        Rule::quantity_literal => {
1479            let mut parts = inner.into_inner();
1480            let number_part = parts.next().ok_or_else(|| {
1481                ParseError::GrammarError("Expected number in quantity literal".to_string())
1482            })?;
1483            let unit_part = parts.next().ok_or_else(|| {
1484                ParseError::GrammarError("Expected unit string in quantity literal".to_string())
1485            })?;
1486            let value = parse_decimal(number_part)?;
1487            let unit = parse_string_literal(unit_part)?;
1488            Ok(Expression::QuantityLiteral { value, unit })
1489        }
1490        Rule::time_literal => {
1491            // Parse ISO 8601 timestamp (already includes quotes in grammar)
1492            let timestamp = inner.as_str();
1493            // Remove surrounding quotes
1494            let timestamp = timestamp.trim_start_matches('"').trim_end_matches('"');
1495            Ok(Expression::TimeLiteral(timestamp.to_string()))
1496        }
1497        Rule::interval_literal => {
1498            // Parse interval("start", "end")
1499            let mut parts = inner.into_inner();
1500            let start_part = parts.next().ok_or_else(|| {
1501                ParseError::GrammarError("Expected start time in interval literal".to_string())
1502            })?;
1503            let end_part = parts.next().ok_or_else(|| {
1504                ParseError::GrammarError("Expected end time in interval literal".to_string())
1505            })?;
1506            let start = parse_string_literal(start_part)?;
1507            let end = parse_string_literal(end_part)?;
1508            Ok(Expression::IntervalLiteral { start, end })
1509        }
1510        Rule::number => {
1511            let n = parse_decimal(inner)?;
1512            // Convert Decimal to f64 for JSON Number representation
1513            let f = n.to_f64().ok_or_else(|| {
1514                ParseError::InvalidQuantity(format!(
1515                    "Decimal value {} cannot be represented as f64",
1516                    n
1517                ))
1518            })?;
1519            // Ensure the value is finite
1520            if !f.is_finite() {
1521                return Err(ParseError::InvalidQuantity(format!(
1522                    "Decimal value {} converts to non-finite f64: {}",
1523                    n, f
1524                )));
1525            }
1526            let num = serde_json::Number::from_f64(f).ok_or_else(|| {
1527                ParseError::InvalidQuantity(format!(
1528                    "Cannot create JSON Number from f64 value: {}",
1529                    f
1530                ))
1531            })?;
1532            Ok(Expression::Literal(JsonValue::Number(num)))
1533        }
1534        Rule::boolean => {
1535            let b = inner.as_str().eq_ignore_ascii_case("true");
1536            Ok(Expression::Literal(JsonValue::Bool(b)))
1537        }
1538        _ => Err(ParseError::InvalidExpression(format!(
1539            "Unknown literal type: {:?}",
1540            inner.as_rule()
1541        ))),
1542    }
1543}
1544
1545/// Parse name (handles both string_literal and multiline_string)
1546fn parse_name(pair: Pair<Rule>) -> ParseResult<String> {
1547    let inner = pair.into_inner().next().ok_or_else(|| {
1548        ParseError::GrammarError("Expected inner token for name but got empty pair".to_string())
1549    })?;
1550    match inner.as_rule() {
1551        Rule::string_literal => parse_string_literal(inner),
1552        Rule::multiline_string => parse_multiline_string(inner),
1553        _ => Err(ParseError::GrammarError(format!(
1554            "Expected string or multiline string for name, got {:?}",
1555            inner.as_rule()
1556        ))),
1557    }
1558}
1559
1560/// Parse string literal (handles escape sequences)
1561fn parse_string_literal(pair: Pair<Rule>) -> ParseResult<String> {
1562    let s = pair.as_str();
1563    if s.len() < 2 || !s.starts_with('"') || !s.ends_with('"') {
1564        return Err(ParseError::GrammarError(format!(
1565            "Invalid string literal: {}",
1566            s
1567        )));
1568    }
1569
1570    // Use serde_json to properly parse and unescape the string
1571    // The string already has quotes, so pass it directly
1572    match serde_json::from_str(s) {
1573        Ok(unescaped) => Ok(unescaped),
1574        Err(e) => Err(ParseError::GrammarError(format!(
1575            "Invalid string literal escape sequences: {} - {}",
1576            s, e
1577        ))),
1578    }
1579}
1580
1581/// Parse multiline string (removes triple quotes and handles escape sequences)
1582fn parse_multiline_string(pair: Pair<Rule>) -> ParseResult<String> {
1583    let s = pair.as_str();
1584    if s.len() < 6 || !s.starts_with("\"\"\"") || !s.ends_with("\"\"\"") {
1585        return Err(ParseError::GrammarError(format!(
1586            "Invalid multiline string: {}",
1587            s
1588        )));
1589    }
1590
1591    let content = &s[3..s.len() - 3];
1592
1593    // Escape special characters for JSON compatibility
1594    let escaped = content
1595        .replace('\\', "\\\\") // Backslash must be first
1596        .replace('"', "\\\"") // Double quotes
1597        .replace('\n', "\\n") // Newlines
1598        .replace('\r', "\\r") // Carriage returns
1599        .replace('\t', "\\t"); // Tabs
1600
1601    // Create a JSON string and parse it to handle escape sequences
1602    let json_string = format!("\"{}\"", escaped);
1603    match serde_json::from_str(&json_string) {
1604        Ok(unescaped) => Ok(unescaped),
1605        Err(e) => Err(ParseError::GrammarError(format!(
1606            "Invalid multiline string escape sequences in '{}': {}",
1607            s, e
1608        ))),
1609    }
1610}
1611
1612/// Parse identifier
1613fn parse_identifier(pair: Pair<Rule>) -> ParseResult<String> {
1614    Ok(pair.as_str().to_string())
1615}
1616
1617/// Parse semantic version (validated by grammar)
1618fn parse_version(pair: Pair<Rule>) -> ParseResult<String> {
1619    Ok(pair.as_str().to_string())
1620}
1621
1622/// Parse number as i32
1623fn parse_number(pair: Pair<Rule>) -> ParseResult<i32> {
1624    pair.as_str()
1625        .parse()
1626        .map_err(|_| ParseError::InvalidQuantity(format!("Invalid number: {}", pair.as_str())))
1627}
1628
1629/// Parse number as Decimal
1630fn parse_decimal(pair: Pair<Rule>) -> ParseResult<Decimal> {
1631    pair.as_str()
1632        .parse()
1633        .map_err(|_| ParseError::InvalidQuantity(format!("Invalid decimal: {}", pair.as_str())))
1634}
1635
1636/// Parse group_by expression
1637fn parse_group_by_expr(pair: Pair<Rule>) -> ParseResult<Expression> {
1638    let mut inner = pair.into_inner();
1639
1640    let variable_pair = inner
1641        .next()
1642        .ok_or_else(|| ParseError::GrammarError("Expected variable in group_by".to_string()))?;
1643    let variable = parse_identifier(variable_pair)?;
1644
1645    let collection_pair = inner
1646        .next()
1647        .ok_or_else(|| ParseError::GrammarError("Expected collection in group_by".to_string()))?;
1648    let collection_name = parse_collection(collection_pair)?;
1649    let collection = Box::new(Expression::Variable(collection_name));
1650
1651    let next_pair = inner.next().ok_or_else(|| {
1652        ParseError::GrammarError("Expected key or where clause in group_by".to_string())
1653    })?;
1654
1655    // Collect remaining pairs to determine structure without cloning
1656    let remaining: Vec<Pair<Rule>> = std::iter::once(next_pair).chain(inner).collect();
1657
1658    let (filter_expr, key_expr, condition_expr) = match remaining.len() {
1659        3 => {
1660            let mut iter = remaining.into_iter();
1661            let filter = parse_expression(iter.next().ok_or_else(|| {
1662                ParseError::GrammarError("Expected filter expression in group_by".to_string())
1663            })?)?;
1664            let key = parse_expression(iter.next().ok_or_else(|| {
1665                ParseError::GrammarError("Expected key expression in group_by".to_string())
1666            })?)?;
1667            let condition = parse_expression(iter.next().ok_or_else(|| {
1668                ParseError::GrammarError("Expected condition expression in group_by".to_string())
1669            })?)?;
1670            (Some(filter), key, condition)
1671        }
1672        2 => {
1673            let mut iter = remaining.into_iter();
1674            let key = parse_expression(iter.next().ok_or_else(|| {
1675                ParseError::GrammarError("Expected key expression in group_by".to_string())
1676            })?)?;
1677            let condition = parse_expression(iter.next().ok_or_else(|| {
1678                ParseError::GrammarError("Expected condition expression in group_by".to_string())
1679            })?)?;
1680            (None, key, condition)
1681        }
1682        other => {
1683            return Err(ParseError::GrammarError(format!(
1684                "Unexpected number of expressions in group_by: {}",
1685                other
1686            )))
1687        }
1688    };
1689
1690    Ok(Expression::GroupBy {
1691        variable,
1692        collection,
1693        filter: filter_expr.map(Box::new),
1694        key: Box::new(key_expr),
1695        condition: Box::new(condition_expr),
1696    })
1697}
1698
1699/// Parse window clause
1700fn parse_window_clause(pair: Pair<Rule>) -> ParseResult<WindowSpec> {
1701    let mut inner = pair.into_inner();
1702
1703    let duration_pair = inner.next().ok_or_else(|| {
1704        ParseError::GrammarError("Expected duration in window clause".to_string())
1705    })?;
1706    let duration_i32 = parse_number(duration_pair)?;
1707    if duration_i32 < 0 {
1708        return Err(ParseError::InvalidQuantity(
1709            "Window duration must be non-negative".to_string(),
1710        ));
1711    }
1712    let duration = duration_i32 as u64;
1713
1714    let unit_pair = inner
1715        .next()
1716        .ok_or_else(|| ParseError::GrammarError("Expected unit in window clause".to_string()))?;
1717    let unit = parse_string_literal(unit_pair)?;
1718
1719    Ok(WindowSpec { duration, unit })
1720}
1721
1722fn expression_kind(expr: &Expression) -> &'static str {
1723    match expr {
1724        Expression::Literal(_) => "literal",
1725        Expression::QuantityLiteral { .. } => "quantity_literal",
1726        Expression::TimeLiteral(_) => "time_literal",
1727        Expression::IntervalLiteral { .. } => "interval_literal",
1728        Expression::Variable(_) => "variable",
1729        Expression::GroupBy { .. } => "group_by",
1730        Expression::Binary { .. } => "binary",
1731        Expression::Unary { .. } => "unary",
1732        Expression::Cast { .. } => "cast",
1733        Expression::Quantifier { .. } => "quantifier",
1734        Expression::MemberAccess { .. } => "member_access",
1735        Expression::Aggregation { .. } => "aggregation",
1736        Expression::AggregationComprehension { .. } => "aggregation_comprehension",
1737    }
1738}
1739
1740/// Convert an Expression to a JSON Value for instance fields
1741fn expression_to_json(expr: &Expression) -> ParseResult<JsonValue> {
1742    match expr {
1743        Expression::Literal(v) => Ok(v.clone()),
1744        Expression::Variable(name) => Ok(JsonValue::String(name.clone())),
1745        Expression::QuantityLiteral { value, unit } => Ok(json!({
1746            "value": value.to_string(),
1747            "unit": unit
1748        })),
1749        Expression::TimeLiteral(timestamp) => Ok(JsonValue::String(timestamp.clone())),
1750        _ => Err(ParseError::UnsupportedExpression {
1751            kind: expression_kind(expr).to_string(),
1752            span: None,
1753        }),
1754    }
1755}
1756
1757/// Parse mapping declaration
1758fn parse_mapping(pair: Pair<Rule>) -> ParseResult<AstNode> {
1759    let mut inner = pair.into_inner();
1760
1761    let name = parse_string_literal(
1762        inner
1763            .next()
1764            .ok_or_else(|| ParseError::GrammarError("Expected mapping name".to_string()))?,
1765    )?;
1766
1767    let target_pair = inner
1768        .next()
1769        .ok_or_else(|| ParseError::GrammarError("Expected target format".to_string()))?;
1770    let target = parse_target_format(target_pair)?;
1771
1772    let mut rules = Vec::new();
1773
1774    for rule_pair in inner {
1775        if rule_pair.as_rule() == Rule::mapping_rule {
1776            rules.push(parse_mapping_rule(rule_pair)?);
1777        }
1778    }
1779
1780    Ok(AstNode::MappingDecl {
1781        name,
1782        target,
1783        rules,
1784    })
1785}
1786
1787fn parse_target_format(pair: Pair<Rule>) -> ParseResult<TargetFormat> {
1788    match pair.as_str().to_lowercase().as_str() {
1789        "calm" => Ok(TargetFormat::Calm),
1790        "kg" => Ok(TargetFormat::Kg),
1791        "sbvr" => Ok(TargetFormat::Sbvr),
1792        "protobuf" | "proto" => Ok(TargetFormat::Protobuf),
1793        _ => Err(ParseError::GrammarError(format!(
1794            "Unknown target format: {}",
1795            pair.as_str()
1796        ))),
1797    }
1798}
1799
1800fn parse_mapping_rule(pair: Pair<Rule>) -> ParseResult<MappingRule> {
1801    let mut inner = pair.into_inner();
1802
1803    let primitive_type = inner
1804        .next()
1805        .ok_or_else(|| ParseError::GrammarError("Expected primitive type".to_string()))?
1806        .as_str()
1807        .to_string();
1808
1809    let primitive_name = parse_string_literal(
1810        inner
1811            .next()
1812            .ok_or_else(|| ParseError::GrammarError("Expected primitive name".to_string()))?,
1813    )?;
1814
1815    let target_structure = inner
1816        .next()
1817        .ok_or_else(|| ParseError::GrammarError("Expected target structure".to_string()))?;
1818
1819    let mut target_inner = target_structure.into_inner();
1820    let target_type = parse_identifier(
1821        target_inner
1822            .next()
1823            .ok_or_else(|| ParseError::GrammarError("Expected target type".to_string()))?,
1824    )?;
1825
1826    let mut fields = HashMap::new();
1827    for field_pair in target_inner {
1828        if field_pair.as_rule() == Rule::mapping_field {
1829            let mut field_inner = field_pair.into_inner();
1830            let key = parse_identifier(
1831                field_inner
1832                    .next()
1833                    .ok_or_else(|| ParseError::GrammarError("Expected field key".to_string()))?,
1834            )?;
1835            let value_pair = field_inner
1836                .next()
1837                .ok_or_else(|| ParseError::GrammarError("Expected field value".to_string()))?;
1838
1839            let value = match value_pair.as_rule() {
1840                Rule::string_literal => JsonValue::String(parse_string_literal(value_pair)?),
1841                Rule::boolean => JsonValue::Bool(value_pair.as_str().eq_ignore_ascii_case("true")),
1842                Rule::object_literal => parse_object_literal(value_pair)?,
1843                _ => {
1844                    return Err(ParseError::GrammarError(
1845                        "Unexpected mapping field value".to_string(),
1846                    ))
1847                }
1848            };
1849            fields.insert(key, value);
1850        }
1851    }
1852
1853    Ok(MappingRule {
1854        primitive_type,
1855        primitive_name,
1856        target_type,
1857        fields,
1858    })
1859}
1860
1861fn parse_object_literal(pair: Pair<Rule>) -> ParseResult<JsonValue> {
1862    let mut map = serde_json::Map::new();
1863    let mut inner = pair.into_inner();
1864    while let Some(key_pair) = inner.next() {
1865        let key = parse_string_literal(key_pair)?;
1866        let value_pair = inner.next().ok_or_else(|| {
1867            ParseError::GrammarError("Expected value in object literal".to_string())
1868        })?;
1869        let value = match value_pair.as_rule() {
1870            Rule::string_literal => JsonValue::String(parse_string_literal(value_pair)?),
1871            Rule::boolean => JsonValue::Bool(value_pair.as_str().eq_ignore_ascii_case("true")),
1872            Rule::number => {
1873                let d = parse_decimal(value_pair)?;
1874                // Parse the decimal string as f64 to create a JSON Number
1875                let f = d.to_f64().ok_or_else(|| {
1876                    ParseError::InvalidQuantity(format!(
1877                        "Decimal value {} cannot be represented as f64",
1878                        d
1879                    ))
1880                })?;
1881                if !f.is_finite() {
1882                    return Err(ParseError::InvalidQuantity(format!(
1883                        "Decimal value {} converts to non-finite f64",
1884                        d
1885                    )));
1886                }
1887                let num = serde_json::Number::from_f64(f).ok_or_else(|| {
1888                    ParseError::InvalidQuantity(format!(
1889                        "Cannot create JSON Number from decimal {}",
1890                        d
1891                    ))
1892                })?;
1893                JsonValue::Number(num)
1894            }
1895            _ => {
1896                return Err(ParseError::GrammarError(
1897                    "Unexpected object field value".to_string(),
1898                ))
1899            }
1900        };
1901        map.insert(key, value);
1902    }
1903    Ok(JsonValue::Object(map))
1904}
1905
1906/// Parse projection declaration
1907fn parse_projection(pair: Pair<Rule>) -> ParseResult<AstNode> {
1908    let mut inner = pair.into_inner();
1909
1910    let name = parse_string_literal(
1911        inner
1912            .next()
1913            .ok_or_else(|| ParseError::GrammarError("Expected projection name".to_string()))?,
1914    )?;
1915
1916    let target_pair = inner
1917        .next()
1918        .ok_or_else(|| ParseError::GrammarError("Expected target format".to_string()))?;
1919    let target = parse_target_format(target_pair)?;
1920
1921    let mut overrides = Vec::new();
1922
1923    for rule_pair in inner {
1924        if rule_pair.as_rule() == Rule::projection_rule {
1925            overrides.push(parse_projection_rule(rule_pair)?);
1926        }
1927    }
1928
1929    Ok(AstNode::ProjectionDecl {
1930        name,
1931        target,
1932        overrides,
1933    })
1934}
1935
1936fn parse_projection_rule(pair: Pair<Rule>) -> ParseResult<ProjectionOverride> {
1937    let mut inner = pair.into_inner();
1938
1939    let primitive_type = inner
1940        .next()
1941        .ok_or_else(|| ParseError::GrammarError("Expected primitive type".to_string()))?
1942        .as_str()
1943        .to_string();
1944
1945    let primitive_name = parse_string_literal(
1946        inner
1947            .next()
1948            .ok_or_else(|| ParseError::GrammarError("Expected primitive name".to_string()))?,
1949    )?;
1950
1951    let mut fields = HashMap::new();
1952    for field_pair in inner {
1953        if field_pair.as_rule() == Rule::projection_field {
1954            let mut field_inner = field_pair.into_inner();
1955            let key = parse_identifier(
1956                field_inner
1957                    .next()
1958                    .ok_or_else(|| ParseError::GrammarError("Expected field key".to_string()))?,
1959            )?;
1960            let value_pair = field_inner
1961                .next()
1962                .ok_or_else(|| ParseError::GrammarError("Expected field value".to_string()))?;
1963
1964            let value = match value_pair.as_rule() {
1965                Rule::string_literal => JsonValue::String(parse_string_literal(value_pair)?),
1966                Rule::property_mapping => parse_property_mapping(value_pair)?,
1967                _ => {
1968                    return Err(ParseError::GrammarError(
1969                        "Unexpected projection field value".to_string(),
1970                    ))
1971                }
1972            };
1973            fields.insert(key, value);
1974        }
1975    }
1976
1977    Ok(ProjectionOverride {
1978        primitive_type,
1979        primitive_name,
1980        fields,
1981    })
1982}
1983
1984fn parse_property_mapping(pair: Pair<Rule>) -> ParseResult<JsonValue> {
1985    let mut map = serde_json::Map::new();
1986    let mut inner = pair.into_inner();
1987    while let Some(key_pair) = inner.next() {
1988        let key = parse_string_literal(key_pair)?;
1989        let value_pair = inner.next().ok_or_else(|| {
1990            ParseError::GrammarError("Expected value in property mapping".to_string())
1991        })?;
1992        let value = parse_string_literal(value_pair)?;
1993        map.insert(key, JsonValue::String(value));
1994    }
1995    Ok(JsonValue::Object(map))
1996}
1997
1998fn unwrap_export(node: &AstNode) -> &AstNode {
1999    match node {
2000        AstNode::Export(inner) => inner.as_ref(),
2001        other => other,
2002    }
2003}
2004
2005/// Convert AST to Graph
2006pub fn ast_to_graph(ast: Ast) -> ParseResult<Graph> {
2007    ast_to_graph_with_options(ast, &ParseOptions::default())
2008}
2009
2010pub fn ast_to_graph_with_options(mut ast: Ast, options: &ParseOptions) -> ParseResult<Graph> {
2011    use crate::parser::profiles::ProfileRegistry;
2012    let registry = ProfileRegistry::global();
2013    let active_profile = ast
2014        .metadata
2015        .profile
2016        .clone()
2017        .or_else(|| options.active_profile.clone())
2018        .unwrap_or_else(|| "default".to_string());
2019    ast.metadata.profile.get_or_insert(active_profile.clone());
2020
2021    if registry.get(&active_profile).is_none() {
2022        let available = registry.list_names().join(", ");
2023        let message = format!(
2024            "Unknown profile: '{}'. Available profiles: {}",
2025            active_profile, available
2026        );
2027        if options.tolerate_profile_warnings {
2028            log::warn!("{}", message);
2029        } else {
2030            return Err(ParseError::Validation(message));
2031        }
2032    }
2033
2034    let mut graph = Graph::new();
2035    let mut entity_map = HashMap::new();
2036    let mut role_map = HashMap::new();
2037    let mut resource_map = HashMap::new();
2038    let mut relation_map = HashMap::new();
2039
2040    let default_namespace = ast
2041        .metadata
2042        .namespace
2043        .clone()
2044        .or_else(|| options.default_namespace.clone())
2045        .unwrap_or_else(|| "default".to_string());
2046
2047    // First pass: Register dimensions and units
2048    {
2049        use crate::units::{Dimension, Unit, UnitError, UnitRegistry};
2050        let registry = UnitRegistry::global();
2051        let mut registry = registry.write().map_err(|e| {
2052            ParseError::GrammarError(format!("Failed to lock unit registry: {}", e))
2053        })?;
2054
2055        for node in &ast.declarations {
2056            let node = unwrap_export(node);
2057            match node {
2058                AstNode::Dimension { name } => {
2059                    let dim = Dimension::parse(name);
2060                    registry.register_dimension(dim);
2061                }
2062                AstNode::UnitDeclaration {
2063                    symbol,
2064                    dimension,
2065                    factor,
2066                    base_unit,
2067                } => {
2068                    let dim = Dimension::parse(dimension);
2069                    let unit = Unit::new(
2070                        symbol.clone(),
2071                        symbol.clone(),
2072                        dim,
2073                        *factor,
2074                        base_unit.clone(),
2075                    );
2076                    match registry.get_unit(symbol) {
2077                        Ok(existing) => {
2078                            if existing != &unit {
2079                                return Err(ParseError::GrammarError(format!(
2080                                    "Conflicting unit '{}' already registered (existing: dimension={}, base_factor={}, base_unit={}; new: dimension={}, base_factor={}, base_unit={})",
2081                                    symbol,
2082                                    existing.dimension(),
2083                                    existing.base_factor(),
2084                                    existing.base_unit(),
2085                                    unit.dimension(),
2086                                    unit.base_factor(),
2087                                    unit.base_unit(),
2088                                )));
2089                            }
2090                        }
2091                        Err(UnitError::UnitNotFound(_)) => {
2092                            registry.register(unit).map_err(|e| {
2093                                ParseError::GrammarError(format!("Failed to register unit: {}", e))
2094                            })?;
2095                        }
2096                        Err(err) => {
2097                            return Err(ParseError::GrammarError(format!(
2098                                "Failed to inspect unit '{}': {}",
2099                                symbol, err
2100                            )));
2101                        }
2102                    }
2103                }
2104                _ => {}
2105            }
2106        }
2107    }
2108
2109    // Register patterns with eager regex validation
2110    for node in &ast.declarations {
2111        let node = unwrap_export(node);
2112        if let AstNode::Pattern { name, regex } = node {
2113            let namespace = default_namespace.clone();
2114            let pattern = Pattern::new(name.clone(), namespace, regex.clone())
2115                .map_err(ParseError::GrammarError)?;
2116
2117            graph
2118                .add_pattern(pattern)
2119                .map_err(ParseError::GrammarError)?;
2120        }
2121    }
2122
2123    // Register concept changes
2124    for node in &ast.declarations {
2125        let node = unwrap_export(node);
2126        if let AstNode::ConceptChange {
2127            name,
2128            from_version,
2129            to_version,
2130            migration_policy,
2131            breaking_change,
2132        } = node
2133        {
2134            let change = ConceptChange::new(
2135                name.clone(),
2136                from_version.clone(),
2137                to_version.clone(),
2138                migration_policy.clone(),
2139                *breaking_change,
2140            );
2141            graph.add_concept_change(change).map_err(|e| {
2142                ParseError::GrammarError(format!("Failed to add concept change: {}", e))
2143            })?;
2144        }
2145    }
2146
2147    // Second pass: Add roles, entities, and resources
2148    for node in &ast.declarations {
2149        let node = unwrap_export(node);
2150        match node {
2151            AstNode::Role { name, domain } => {
2152                if role_map.contains_key(name) {
2153                    return Err(ParseError::duplicate_declaration(format!(
2154                        "Role '{}' already declared",
2155                        name
2156                    )));
2157                }
2158
2159                let namespace = domain.as_ref().unwrap_or(&default_namespace).clone();
2160                let role = Role::new_with_namespace(name.clone(), namespace);
2161                let role_id = role.id().clone();
2162                graph
2163                    .add_role(role)
2164                    .map_err(|e| ParseError::GrammarError(format!("Failed to add role: {}", e)))?;
2165                role_map.insert(name.clone(), role_id);
2166            }
2167            AstNode::Entity {
2168                name,
2169                domain,
2170                version,
2171                annotations,
2172            } => {
2173                if entity_map.contains_key(name) {
2174                    return Err(ParseError::duplicate_declaration(format!(
2175                        "Entity '{}' already declared",
2176                        name
2177                    )));
2178                }
2179
2180                let namespace = domain.as_ref().unwrap_or(&default_namespace).clone();
2181                let mut entity = Entity::new_with_namespace(name.clone(), namespace);
2182
2183                if let Some(v_str) = version {
2184                    let sem_ver = SemanticVersion::parse(v_str).map_err(|e| {
2185                        ParseError::GrammarError(format!(
2186                            "Invalid entity version '{}': {}",
2187                            v_str, e
2188                        ))
2189                    })?;
2190                    entity = entity.with_version(sem_ver);
2191                }
2192
2193                if let Some(replaces_val) = annotations.get("replaces") {
2194                    if let Some(replaces_str) = replaces_val.as_str() {
2195                        entity = entity.with_replaces(replaces_str.to_string());
2196                    }
2197                }
2198
2199                if let Some(changes_val) = annotations.get("changes") {
2200                    if let Some(changes_arr) = changes_val.as_array() {
2201                        let changes: Vec<String> = changes_arr
2202                            .iter()
2203                            .filter_map(|v| v.as_str().map(|s| s.to_string()))
2204                            .collect();
2205                        entity = entity.with_changes(changes);
2206                    }
2207                }
2208
2209                let entity_id = entity.id().clone();
2210                graph.add_entity(entity).map_err(|e| {
2211                    ParseError::GrammarError(format!("Failed to add entity: {}", e))
2212                })?;
2213                entity_map.insert(name.clone(), entity_id);
2214            }
2215            AstNode::Resource {
2216                name,
2217                unit_name,
2218                domain,
2219            } => {
2220                if resource_map.contains_key(name) {
2221                    return Err(ParseError::duplicate_declaration(format!(
2222                        "Resource '{}' already declared",
2223                        name
2224                    )));
2225                }
2226
2227                let namespace = domain.as_ref().unwrap_or(&default_namespace).clone();
2228                let unit = unit_from_string(unit_name.as_deref().unwrap_or("units"));
2229                let resource = Resource::new_with_namespace(name.clone(), unit, namespace);
2230                let resource_id = resource.id().clone();
2231                graph.add_resource(resource).map_err(|e| {
2232                    ParseError::GrammarError(format!("Failed to add resource: {}", e))
2233                })?;
2234                resource_map.insert(name.clone(), resource_id);
2235            }
2236            _ => {}
2237        }
2238    }
2239
2240    // Third pass: Add flows
2241    for node in &ast.declarations {
2242        let node = unwrap_export(node);
2243        if let AstNode::Flow {
2244            resource_name,
2245            from_entity,
2246            to_entity,
2247            quantity,
2248        } = node
2249        {
2250            let from_id = entity_map
2251                .get(from_entity)
2252                .ok_or_else(|| ParseError::undefined_entity(from_entity))?;
2253
2254            let to_id = entity_map
2255                .get(to_entity)
2256                .ok_or_else(|| ParseError::undefined_entity(to_entity))?;
2257
2258            let resource_id = resource_map
2259                .get(resource_name)
2260                .ok_or_else(|| ParseError::undefined_resource(resource_name))?;
2261
2262            let qty = quantity.map(Decimal::from).unwrap_or(Decimal::ZERO);
2263            let flow = Flow::new(resource_id.clone(), from_id.clone(), to_id.clone(), qty);
2264
2265            graph
2266                .add_flow(flow)
2267                .map_err(|e| ParseError::GrammarError(format!("Failed to add flow: {}", e)))?;
2268        }
2269    }
2270
2271    // Fourth pass: Add relations
2272    for node in &ast.declarations {
2273        let node = unwrap_export(node);
2274        if let AstNode::Relation {
2275            name,
2276            subject_role,
2277            predicate,
2278            object_role,
2279            via_flow,
2280        } = node
2281        {
2282            if relation_map.contains_key(name) {
2283                return Err(ParseError::duplicate_declaration(format!(
2284                    "Relation '{}' already declared",
2285                    name
2286                )));
2287            }
2288
2289            let subject_id = role_map.get(subject_role).ok_or_else(|| {
2290                ParseError::GrammarError(format!("Undefined subject role '{}'", subject_role))
2291            })?;
2292
2293            let object_id = role_map.get(object_role).ok_or_else(|| {
2294                ParseError::GrammarError(format!("Undefined object role '{}'", object_role))
2295            })?;
2296
2297            let via_flow_id = if let Some(flow_name) = via_flow {
2298                Some(
2299                    resource_map
2300                        .get(flow_name)
2301                        .cloned()
2302                        .ok_or_else(|| ParseError::undefined_resource(flow_name))?,
2303                )
2304            } else {
2305                None
2306            };
2307
2308            let relation = RelationType::new(
2309                name.clone(),
2310                default_namespace.clone(),
2311                subject_id.clone(),
2312                predicate.clone(),
2313                object_id.clone(),
2314                via_flow_id,
2315            );
2316
2317            let relation_id = relation.id().clone();
2318            graph.add_relation_type(relation).map_err(|e| {
2319                ParseError::GrammarError(format!("Failed to add relation '{}': {}", name, e))
2320            })?;
2321            relation_map.insert(name.clone(), relation_id);
2322        }
2323    }
2324
2325    // Instance pass: Add instances (after entities are created)
2326    for node in &ast.declarations {
2327        let node = unwrap_export(node);
2328        if let AstNode::Instance {
2329            name,
2330            entity_type,
2331            fields,
2332        } = node
2333        {
2334            let namespace = default_namespace.clone();
2335            let mut instance = crate::primitives::Instance::new_with_namespace(
2336                name.clone(),
2337                entity_type.clone(),
2338                namespace,
2339            );
2340
2341            // Evaluate and set fields
2342            for (field_name, field_expr) in fields {
2343                let value = expression_to_json(field_expr)?;
2344                instance.set_field(field_name.clone(), value);
2345            }
2346
2347            graph.add_entity_instance(instance).map_err(|e| {
2348                ParseError::GrammarError(format!("Failed to add entity instance '{}': {}", name, e))
2349            })?;
2350        }
2351    }
2352
2353    // Fifth pass: Add policies
2354    for node in &ast.declarations {
2355        let node = unwrap_export(node);
2356        if let AstNode::Policy {
2357            name,
2358            version,
2359            metadata,
2360            expression,
2361        } = node
2362        {
2363            let namespace = ast
2364                .metadata
2365                .namespace
2366                .as_ref()
2367                .cloned()
2368                .or_else(|| options.default_namespace.clone())
2369                .unwrap_or_else(|| "default".to_string());
2370
2371            let kind = metadata.kind.as_ref().map(|kind| match kind {
2372                PolicyKind::Constraint => CorePolicyKind::Constraint,
2373                PolicyKind::Derivation => CorePolicyKind::Derivation,
2374                PolicyKind::Obligation => CorePolicyKind::Obligation,
2375            });
2376
2377            let modality = metadata.modality.as_ref().map(|modality| match modality {
2378                PolicyModality::Obligation => CorePolicyModality::Obligation,
2379                PolicyModality::Prohibition => CorePolicyModality::Prohibition,
2380                PolicyModality::Permission => CorePolicyModality::Permission,
2381            });
2382
2383            let mut policy =
2384                Policy::new_with_namespace(name.clone(), namespace, expression.clone())
2385                    .with_metadata(
2386                        kind,
2387                        modality,
2388                        metadata.priority,
2389                        metadata.rationale.clone(),
2390                        metadata.tags.clone(),
2391                    );
2392
2393            let version_to_apply = version
2394                .as_ref()
2395                .cloned()
2396                .or_else(|| ast.metadata.version.clone());
2397
2398            if let Some(version_str) = version_to_apply {
2399                let semantic_version = SemanticVersion::parse(&version_str).map_err(|err| {
2400                    ParseError::GrammarError(format!(
2401                        "Invalid policy version '{}': {}",
2402                        version_str, err
2403                    ))
2404                })?;
2405                policy = policy.with_version(semantic_version);
2406            }
2407
2408            graph.add_policy(policy).map_err(|e| {
2409                ParseError::GrammarError(format!("Failed to add policy '{}': {}", name, e))
2410            })?;
2411        }
2412    }
2413
2414    // Sixth pass: Add metrics
2415    for node in &ast.declarations {
2416        let node = unwrap_export(node);
2417        if let AstNode::Metric {
2418            name,
2419            expression,
2420            metadata,
2421        } = node
2422        {
2423            let namespace = ast
2424                .metadata
2425                .namespace
2426                .as_ref()
2427                .cloned()
2428                .or_else(|| options.default_namespace.clone())
2429                .unwrap_or_else(|| "default".to_string());
2430
2431            let mut metric =
2432                crate::primitives::Metric::new(name.clone(), namespace, expression.clone());
2433
2434            if let Some(duration) = metadata.refresh_interval {
2435                metric = metric.with_refresh_interval(duration);
2436            }
2437
2438            if let Some(unit) = &metadata.unit {
2439                metric = metric.with_unit(unit.clone());
2440            }
2441
2442            if let Some(threshold) = metadata.threshold {
2443                metric = metric.with_threshold(threshold);
2444            }
2445
2446            if let Some(severity) = metadata.severity.clone() {
2447                metric = metric.with_severity(severity);
2448            }
2449
2450            if let Some(target) = metadata.target {
2451                metric = metric.with_target(target);
2452            }
2453
2454            if let Some(duration) = metadata.window {
2455                metric = metric.with_window(duration);
2456            }
2457
2458            graph.add_metric(metric).map_err(|e| {
2459                ParseError::GrammarError(format!("Failed to add metric '{}': {}", name, e))
2460            })?;
2461        }
2462    }
2463
2464    // Seventh pass: Add mappings
2465    for node in &ast.declarations {
2466        let node = unwrap_export(node);
2467        if let AstNode::MappingDecl {
2468            name,
2469            target,
2470            rules,
2471        } = node
2472        {
2473            let namespace = ast
2474                .metadata
2475                .namespace
2476                .clone()
2477                .or_else(|| options.default_namespace.clone())
2478                .unwrap_or_else(|| "default".to_string());
2479            let mapping = crate::primitives::MappingContract::new(
2480                crate::ConceptId::from_concept(&namespace, name),
2481                name.clone(),
2482                namespace,
2483                target.clone(),
2484                rules.clone(),
2485            );
2486            graph
2487                .add_mapping(mapping)
2488                .map_err(|e| ParseError::GrammarError(format!("Failed to add mapping: {}", e)))?;
2489        }
2490    }
2491
2492    // Eighth pass: Add projections
2493    for node in &ast.declarations {
2494        let node = unwrap_export(node);
2495        if let AstNode::ProjectionDecl {
2496            name,
2497            target,
2498            overrides,
2499        } = node
2500        {
2501            let namespace = ast
2502                .metadata
2503                .namespace
2504                .clone()
2505                .or_else(|| options.default_namespace.clone())
2506                .unwrap_or_else(|| "default".to_string());
2507            let projection = crate::primitives::ProjectionContract::new(
2508                crate::ConceptId::from_concept(&namespace, name),
2509                name.clone(),
2510                namespace,
2511                target.clone(),
2512                overrides.clone(),
2513            );
2514            graph.add_projection(projection).map_err(|e| {
2515                ParseError::GrammarError(format!("Failed to add projection: {}", e))
2516            })?;
2517        }
2518    }
2519
2520    Ok(graph)
2521}
2522
2523/// Parse metric declaration
2524fn parse_metric(pair: Pair<Rule>) -> ParseResult<AstNode> {
2525    let mut inner = pair.into_inner();
2526
2527    let name = parse_name(
2528        inner
2529            .next()
2530            .ok_or_else(|| ParseError::GrammarError("Expected metric name".to_string()))?,
2531    )?;
2532
2533    let mut metadata = MetricMetadata {
2534        refresh_interval: None,
2535        unit: None,
2536        threshold: None,
2537        severity: None,
2538        target: None,
2539        window: None,
2540    };
2541
2542    let mut expression_pair = None;
2543
2544    for part in inner {
2545        match part.as_rule() {
2546            Rule::metric_annotation => {
2547                let mut annotation_inner = part.into_inner();
2548                let key_pair = annotation_inner.next().ok_or_else(|| {
2549                    ParseError::GrammarError("Expected annotation key".to_string())
2550                })?;
2551
2552                match key_pair.as_rule() {
2553                    Rule::ma_refresh_interval => {
2554                        let value_pair = annotation_inner.next().ok_or_else(|| {
2555                            ParseError::GrammarError("Expected refresh interval value".to_string())
2556                        })?;
2557                        let value = parse_number_i64(value_pair)?;
2558                        let unit_pair = annotation_inner.next().ok_or_else(|| {
2559                            ParseError::GrammarError("Expected refresh interval unit".to_string())
2560                        })?;
2561                        let unit = parse_string_literal(unit_pair.clone())?;
2562                        let duration = parse_duration_with_unit(value, &unit, unit_pair.as_span())?;
2563                        metadata.refresh_interval = Some(duration);
2564                    }
2565                    Rule::ma_unit => {
2566                        let unit_pair = annotation_inner
2567                            .next()
2568                            .ok_or_else(|| ParseError::GrammarError("Expected unit".to_string()))?;
2569                        metadata.unit = Some(parse_string_literal(unit_pair)?);
2570                    }
2571                    Rule::ma_threshold => {
2572                        let value_pair = annotation_inner.next().ok_or_else(|| {
2573                            ParseError::GrammarError("Expected threshold value".to_string())
2574                        })?;
2575                        metadata.threshold = Some(parse_decimal(value_pair)?);
2576                    }
2577                    Rule::ma_severity => {
2578                        let severity_pair = annotation_inner.next().ok_or_else(|| {
2579                            ParseError::GrammarError("Expected severity".to_string())
2580                        })?;
2581                        let severity_str = parse_string_literal(severity_pair.clone())?;
2582                        let severity =
2583                            parse_severity_value(&severity_str, severity_pair.as_span())?;
2584                        metadata.severity = Some(severity);
2585                    }
2586                    Rule::ma_target => {
2587                        let value_pair = annotation_inner.next().ok_or_else(|| {
2588                            ParseError::GrammarError("Expected target value".to_string())
2589                        })?;
2590                        metadata.target = Some(parse_decimal(value_pair)?);
2591                    }
2592                    Rule::ma_window => {
2593                        let value_pair = annotation_inner.next().ok_or_else(|| {
2594                            ParseError::GrammarError("Expected window value".to_string())
2595                        })?;
2596                        let value = parse_number_i64(value_pair)?;
2597                        let unit_pair = annotation_inner.next().ok_or_else(|| {
2598                            ParseError::GrammarError("Expected window unit".to_string())
2599                        })?;
2600                        let unit = parse_string_literal(unit_pair.clone())?;
2601                        let duration = parse_duration_with_unit(value, &unit, unit_pair.as_span())?;
2602                        metadata.window = Some(duration);
2603                    }
2604                    _ => {
2605                        let (line, column) = key_pair.as_span().start_pos().line_col();
2606                        return Err(ParseError::GrammarError(format!(
2607                            "Unknown metric annotation '{}' at {}:{}",
2608                            key_pair.as_str(),
2609                            line,
2610                            column
2611                        )));
2612                    }
2613                }
2614            }
2615            Rule::expression => {
2616                expression_pair = Some(part);
2617            }
2618            _ => {}
2619        }
2620    }
2621
2622    let expression = parse_expression(
2623        expression_pair
2624            .ok_or_else(|| ParseError::GrammarError("Expected metric expression".to_string()))?,
2625    )?;
2626
2627    Ok(AstNode::Metric {
2628        name,
2629        expression,
2630        metadata,
2631    })
2632}
2633
2634fn parse_duration_with_unit(value: i64, unit: &str, span: Span<'_>) -> ParseResult<Duration> {
2635    let normalized_unit = unit.to_ascii_lowercase();
2636    let multiplier = match normalized_unit.as_str() {
2637        "second" => Some(1),
2638        "seconds" | "s" => Some(1),
2639        "minute" => Some(60),
2640        "minutes" | "m" => Some(60),
2641        "hour" => Some(60 * 60),
2642        "hours" | "h" => Some(60 * 60),
2643        "day" => Some(60 * 60 * 24),
2644        "days" | "d" => Some(60 * 60 * 24),
2645        _ => None,
2646    }
2647    .ok_or_else(|| {
2648        let (line, column) = span.start_pos().line_col();
2649        ParseError::GrammarError(format!(
2650            "Invalid duration unit '{}' at {}:{} (allowed: second(s)/s, minute(s)/m, hour(s)/h, day(s)/d)",
2651            unit, line, column
2652        ))
2653    })?;
2654
2655    let total_seconds = value.checked_mul(multiplier).ok_or_else(|| {
2656        let (line, column) = span.start_pos().line_col();
2657        ParseError::GrammarError(format!(
2658            "Duration overflow for value {} {} at {}:{}",
2659            value, unit, line, column
2660        ))
2661    })?;
2662
2663    Ok(Duration::seconds(total_seconds))
2664}
2665
2666fn parse_severity_value(value: &str, span: Span<'_>) -> ParseResult<Severity> {
2667    let normalized = value.to_ascii_lowercase();
2668    match normalized.as_str() {
2669        "info" => Ok(Severity::Info),
2670        "warning" => Ok(Severity::Warning),
2671        "error" => Ok(Severity::Error),
2672        "critical" => Ok(Severity::Critical),
2673        _ => {
2674            let (line, column) = span.start_pos().line_col();
2675            Err(ParseError::GrammarError(format!(
2676                "Unknown severity '{}' at {}:{} (expected one of: info, warning, error, critical)",
2677                value, line, column
2678            )))
2679        }
2680    }
2681}
2682
2683fn parse_number_i64(pair: Pair<Rule>) -> ParseResult<i64> {
2684    let s = pair.as_str();
2685    s.parse::<i64>()
2686        .map_err(|_| ParseError::GrammarError(format!("Invalid integer: {}", s)))
2687}