devalang_core/core/parser/handler/identifier/
synth.rs

1use std::collections::HashMap;
2
3use devalang_types::Value;
4
5use crate::core::{
6    lexer::token::Token,
7    parser::{
8        driver::Parser,
9        handler::dot::parse_dot_token,
10        statement::{Statement, StatementKind},
11    },
12    store::global::GlobalStore,
13};
14
15pub fn parse_synth_token(
16    parser: &mut Parser,
17    _current_token: Token,
18    _global_store: &mut GlobalStore,
19) -> Statement {
20    parser.advance(); // consume 'synth'
21
22    let Some(synth_token) = parser.previous_clone() else {
23        return Statement::unknown();
24    };
25
26    // Expect a provider/waveform identifier (can be dotted: alias.synth)
27    // Also accept a dot-led entity by delegating to the dot parser (e.g. .module.export)
28    let synth_waveform = if let Some(first_token) = parser.peek_clone() {
29        use crate::core::lexer::token::TokenKind;
30
31        if first_token.kind == TokenKind::Dot {
32            // Parse dot-entity and extract its entity string
33            let dot_stmt = parse_dot_token(parser, _global_store);
34            // Extract entity if the parsed statement is a Trigger
35            match dot_stmt.kind {
36                StatementKind::Trigger { entity, .. } => entity,
37                _ => String::new(),
38            }
39        } else {
40            if first_token.kind != crate::core::lexer::token::TokenKind::Identifier
41                && first_token.kind != crate::core::lexer::token::TokenKind::Number
42                && first_token.kind != crate::core::lexer::token::TokenKind::Synth
43            {
44                return crate::core::parser::statement::error_from_token(
45                    first_token.clone(),
46                    "Expected identifier after 'synth'".to_string(),
47                );
48            }
49
50            // Collect dotted parts on the same line
51            let mut parts: Vec<String> = Vec::new();
52            let current_line = first_token.line;
53            loop {
54                let Some(tok) = parser.peek_clone() else {
55                    break;
56                };
57                if tok.line != current_line {
58                    break;
59                }
60                match tok.kind {
61                    crate::core::lexer::token::TokenKind::Identifier
62                    | crate::core::lexer::token::TokenKind::Number
63                    | crate::core::lexer::token::TokenKind::Synth => {
64                        parts.push(tok.lexeme.clone());
65                        parser.advance();
66                        // If next isn't a dot on same line, stop
67                        if let Some(next) = parser.peek_clone() {
68                            if !(next.line == current_line
69                                && next.kind == crate::core::lexer::token::TokenKind::Dot)
70                            {
71                                break;
72                            }
73                        } else {
74                            break;
75                        }
76                    }
77                    crate::core::lexer::token::TokenKind::Dot => {
78                        parser.advance();
79                    }
80                    _ => break,
81                }
82            }
83
84            parts.join(".")
85        }
86    } else {
87        return crate::core::parser::statement::error_from_token(
88            synth_token,
89            "Expected identifier after 'synth'".to_string(),
90        );
91    };
92
93    // Skip formatting before optional parameters map
94    while parser.check_token(crate::core::lexer::token::TokenKind::Newline)
95        || parser.check_token(crate::core::lexer::token::TokenKind::Indent)
96        || parser.check_token(crate::core::lexer::token::TokenKind::Dedent)
97        || parser.check_token(crate::core::lexer::token::TokenKind::Whitespace)
98    {
99        parser.advance();
100    }
101
102    // Expect synth optional parameters map
103    let parameters = if let Some(params) = parser.parse_map_value() {
104        // If parameters are provided, we expect a map
105        if let Value::Map(map) = params {
106            map
107        } else {
108            return crate::core::parser::statement::error_from_token(
109                synth_token,
110                "Expected a map for synth parameters".to_string(),
111            );
112        }
113    } else {
114        // If no parameters are provided, we can still create the statement with an empty map
115        HashMap::new()
116    };
117
118    Statement {
119        kind: StatementKind::Synth,
120        value: Value::Map(HashMap::from([
121            ("entity".to_string(), Value::String("synth".to_string())),
122            (
123                "value".to_string(),
124                Value::Map(HashMap::from([
125                    // Store waveform as identifier to allow resolution from variables/exports
126                    ("waveform".to_string(), Value::Identifier(synth_waveform)),
127                    ("parameters".to_string(), Value::Map(parameters)),
128                ])),
129            ),
130        ])),
131        indent: synth_token.indent,
132        line: synth_token.line,
133        column: synth_token.column,
134    }
135}