devalang_core/core/parser/handler/
pattern.rs

1use devalang_types::Value;
2
3use crate::core::{
4    lexer::token::TokenKind,
5    parser::{
6        driver::parser::Parser,
7        statement::{Statement, StatementKind},
8    },
9    store::global::GlobalStore,
10};
11
12pub fn parse_pattern_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
13    // consume 'pattern'
14    parser.advance();
15
16    let Some(tok) = parser.previous_clone() else {
17        return Statement::unknown();
18    };
19
20    // Parse pattern name
21    let mut name = String::new();
22    if let Some(next) = parser.peek_clone() {
23        if next.kind == TokenKind::Identifier {
24            parser.advance();
25            name = next.lexeme.clone();
26        }
27    }
28
29    // optional 'with <target>' sequence
30    let mut target: Option<String> = None;
31    if parser.peek_is("with") {
32        parser.advance(); // consume 'with'
33        if let Some(tok2) = parser.peek_clone() {
34            // target can be identifier or dotted identifier
35            if tok2.kind == TokenKind::Identifier {
36                parser.advance();
37                let mut base = tok2.lexeme.clone();
38                if let Some(dot) = parser.peek_clone() {
39                    if dot.kind == TokenKind::Dot {
40                        parser.advance();
41                        if let Some(suf) = parser.peek_clone() {
42                            if suf.kind == TokenKind::Identifier || suf.kind == TokenKind::Number {
43                                parser.advance();
44                                base.push('.');
45                                base.push_str(&suf.lexeme);
46                            }
47                        }
48                    }
49                }
50                target = Some(base);
51            }
52        }
53    }
54
55    // optional inline options map like { swing: 0.08 }
56    let mut options: Option<Value> = None;
57    if parser.check_token(TokenKind::LBrace) {
58        options = parser.parse_map_value();
59    }
60
61    // optional '=' and pattern string
62    let mut value: Value = Value::Null;
63    if parser.peek_is("=") {
64        parser.advance();
65        if let Some(tok3) = parser.peek_clone() {
66            if tok3.kind == TokenKind::String {
67                parser.advance();
68                let pat_str = Value::String(tok3.lexeme.clone());
69                if let Some(opts) = options {
70                    // merge options map with pattern key
71                    if let Value::Map(mut m) = opts {
72                        m.insert("pattern".to_string(), pat_str);
73                        value = Value::Map(m);
74                    } else {
75                        // unexpected, wrap into a map
76                        let mut m = std::collections::HashMap::new();
77                        m.insert("pattern".to_string(), pat_str);
78                        value = Value::Map(m);
79                    }
80                } else {
81                    value = Value::String(tok3.lexeme.clone());
82                }
83            }
84        }
85    } else if let Some(opts) = options {
86        // only options were provided, store them as the value
87        value = opts;
88    }
89
90    Statement {
91        kind: StatementKind::Pattern { name, target },
92        value,
93        indent: tok.indent,
94        line: tok.line,
95        column: tok.column,
96    }
97}