devalang_core/core/parser/handler/
dot.rs1use devalang_types::{Duration, Value};
2
3use crate::core::{
4 lexer::token::TokenKind,
5 parser::{
6 driver::Parser,
7 statement::{Statement, StatementKind},
8 },
9};
10
11pub fn parse_dot_token(
12 parser: &mut Parser,
13 _global_store: &mut crate::core::store::global::GlobalStore,
14) -> Statement {
15 parser.advance(); let Some(dot_token) = parser.previous_clone() else {
18 return Statement::unknown();
19 };
20
21 let mut parts = Vec::new();
23 let current_line = dot_token.line;
24
25 while let Some(token) = parser.peek_clone() {
26 if token.line != current_line {
28 break;
29 }
30 match token.kind {
31 TokenKind::Identifier | TokenKind::Number => {
32 parts.push(token.lexeme.clone());
33 parser.advance();
34 if let Some(next) = parser.peek_clone() {
36 if next.line != current_line || next.kind != TokenKind::Dot {
37 break;
38 }
39 } else {
40 break;
41 }
42 }
43 TokenKind::Dot => {
44 parser.advance();
45 }
46 TokenKind::Newline | TokenKind::EOF | TokenKind::Indent | TokenKind::Dedent => {
47 break; }
49 _ => {
50 break;
51 }
52 }
53 }
54
55 let entity = if !parts.is_empty() {
57 parts.join(".") } else {
59 eprintln!("⚠️ Empty entity after '.' at line {}", dot_token.line);
60 String::new()
61 };
62
63 let mut duration = Duration::Auto;
65 let mut value = Value::Null;
66
67 if let Some(token) = parser.peek_clone() {
68 if token.line == current_line {
70 match token.kind {
71 TokenKind::Number => {
72 let numerator = token.lexeme.clone();
73 parser.advance();
74 if let Some(peek) = parser.peek_clone() {
75 if peek.line == current_line {
76 if let Some(TokenKind::Slash) = parser.peek_kind() {
77 parser.advance();
78 if let Some(denominator_token) = parser.peek_clone() {
79 if denominator_token.line == current_line
80 && denominator_token.kind == TokenKind::Number
81 {
82 let denominator = denominator_token.lexeme.clone();
83 parser.advance();
84 duration = Duration::Beat(format!(
85 "{}/{}",
86 numerator, denominator
87 ));
88 }
89 }
90 } else {
91 duration = parse_duration(numerator);
92 }
93 } else {
94 duration = parse_duration(numerator);
95 }
96 } else {
97 duration = parse_duration(numerator);
98 }
99 if let Some(next) = parser.peek_clone() {
100 if next.line == current_line && next.kind == TokenKind::LBrace {
101 value = parser.parse_map_value().unwrap_or(Value::Null);
102 }
103 }
104 }
105 TokenKind::Identifier => {
106 let id = token.lexeme.clone();
107 parser.advance();
108 duration = parse_duration(id);
109 if let Some(next) = parser.peek_clone() {
110 if next.line == current_line && next.kind == TokenKind::LBrace {
111 value = parser.parse_map_value().unwrap_or(Value::Null);
112 }
113 }
114 }
115 TokenKind::LBrace => {
116 value = parser.parse_map_value().unwrap_or(Value::Null);
117 }
118 _ => {}
119 }
120 }
121 }
122
123 Statement {
124 kind: StatementKind::Trigger {
125 entity,
126 duration,
127 effects: Some(value.clone()),
128 },
129 value: Value::Null,
130 indent: dot_token.indent,
131 line: dot_token.line,
132 column: dot_token.column,
133 }
134}
135
136fn parse_duration(s: String) -> Duration {
137 if s == "auto" {
138 Duration::Auto
139 } else if let Ok(num) = s.parse::<f32>() {
140 Duration::Number(num)
141 } else {
142 Duration::Identifier(s)
143 }
144}