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