1use base64::Engine;
69use serde::{Deserialize, Serialize};
70
71use crate::{
72 diagnostics::{Diagnostic, SourceLocation, collector::DiagnosticCollector},
73 parser::lexer::{Token, TokenType},
74};
75use std::{
76 collections::HashSet,
77 fmt::{self, Debug, Display, Formatter},
78 vec,
79};
80
81#[derive(Debug, Clone)]
85pub enum ASTParseDiagnostic {
86 UnexpectedToken(Option<SourceLocation>),
88 UnmatchedParenthesis(Option<SourceLocation>),
90 InvalidVariableName(Option<SourceLocation>),
92 UnsupportedStructure(Option<SourceLocation>),
94 MissingStructure(Option<SourceLocation>, String),
96 InvalidSyntax(Option<SourceLocation>, String),
98}
99
100impl Diagnostic for ASTParseDiagnostic {
101 fn severity(&self) -> crate::diagnostics::ReportSeverity {
102 match self {
103 ASTParseDiagnostic::UnexpectedToken(_) => crate::diagnostics::ReportSeverity::Error,
104 ASTParseDiagnostic::UnmatchedParenthesis(_) => {
105 crate::diagnostics::ReportSeverity::Error
106 }
107 ASTParseDiagnostic::InvalidVariableName(_) => crate::diagnostics::ReportSeverity::Error,
108 ASTParseDiagnostic::UnsupportedStructure(_) => {
109 crate::diagnostics::ReportSeverity::Error
110 }
111 ASTParseDiagnostic::MissingStructure(_, _) => crate::diagnostics::ReportSeverity::Error,
112 ASTParseDiagnostic::InvalidSyntax(_, _) => crate::diagnostics::ReportSeverity::Error,
113 }
114 }
115
116 fn title(&self) -> String {
117 "AST Parse Error".into()
118 }
119
120 fn message(&self) -> String {
121 match self {
122 ASTParseDiagnostic::UnexpectedToken(_) => "Unexpected token found".into(),
123 ASTParseDiagnostic::UnmatchedParenthesis(_) => "Unmatched parenthesis found".into(),
124 ASTParseDiagnostic::InvalidVariableName(_) => "Invalid variable name".into(),
125 ASTParseDiagnostic::UnsupportedStructure(_) => "Unsupported structure".into(),
126 ASTParseDiagnostic::MissingStructure(_, expected) => {
127 format!("Missing structure: {}", expected)
128 }
129 ASTParseDiagnostic::InvalidSyntax(_, expected) => {
130 format!("Invalid syntax: {}", expected)
131 }
132 }
133 }
134
135 fn location(&self) -> Option<SourceLocation> {
136 match self {
137 ASTParseDiagnostic::UnexpectedToken(loc) => loc.clone(),
138 ASTParseDiagnostic::UnmatchedParenthesis(loc) => loc.clone(),
139 ASTParseDiagnostic::InvalidVariableName(loc) => loc.clone(),
140 ASTParseDiagnostic::UnsupportedStructure(loc) => loc.clone(),
141 ASTParseDiagnostic::MissingStructure(loc, _) => loc.clone(),
142 ASTParseDiagnostic::InvalidSyntax(loc, _) => loc.clone(),
143 }
144 }
145
146 fn help(&self) -> Option<String> {
147 match self {
148 ASTParseDiagnostic::UnexpectedToken(_) => Some("Check the syntax near the unexpected token.".into()),
149 ASTParseDiagnostic::UnmatchedParenthesis(_) => Some("Ensure all parentheses are properly matched.".into()),
150 ASTParseDiagnostic::InvalidVariableName(_) => Some("Variable names must start with a letter and can only contain letters, numbers, and underscores.".into()),
151 ASTParseDiagnostic::UnsupportedStructure(_) => None,
152 ASTParseDiagnostic::MissingStructure(_, _) => None,
153 ASTParseDiagnostic::InvalidSyntax(_, _) => None,
154 }
155 }
156
157 fn copy(&self) -> Box<dyn Diagnostic> {
158 Box::new(self.clone())
159 }
160}
161
162pub type TokenStream = Vec<Token>;
164pub type GatheredTokens<'t> = &'t [Token];
166
167pub mod ast_token_stream {
169 pub fn from_stream<'t>(stream: &'t super::TokenStream) -> super::GatheredTokens<'t> {
171 stream.as_slice()
172 }
173}
174
175fn get_next_tokens<'a, 'b>(
179 collector: &'a mut DiagnosticCollector,
180 tokens: GatheredTokens<'b>,
181 offset: usize,
182) -> Result<GatheredTokens<'b>, ()> {
183 let mut stack = Vec::<&Token>::new();
184 let mut next_tokens_end = 0usize;
185 let mut index = offset;
186 if index >= tokens.len() {
187 return Ok(&[]);
188 }
189 loop {
190 if ["{", "[", "("].contains(&tokens[index].token().as_str())
191 && tokens[index] == TokenType::SYMBOL
192 {
193 stack.push(&tokens[index]);
194 next_tokens_end += 1;
195 } else if ["}", "]", ")"].contains(&tokens[index].token().as_str())
196 && tokens[index] == TokenType::SYMBOL
197 {
198 if stack.is_empty() {
199 break;
200 }
201 let last = stack.pop().unwrap();
202 if (last == "{" && tokens[index] != "}")
203 || (last == "[" && tokens[index] != "]")
204 || (last == "(" && tokens[index] != ")")
205 {
206 return collector.fatal(ASTParseDiagnostic::UnmatchedParenthesis(
207 span_from_two_token(&last, &tokens[index]),
208 ));
209 }
210
211 next_tokens_end += 1;
212 } else {
213 next_tokens_end += 1;
214 }
215 index += 1;
216 if index >= tokens.len() || stack.is_empty() {
217 break;
218 }
219 }
220 if !stack.is_empty() {
221 let last = stack.pop().unwrap();
222 return collector.fatal(ASTParseDiagnostic::UnmatchedParenthesis(
223 span_from_two_token(&last, &tokens[offset + next_tokens_end - 1]),
224 ));
225 }
226 Ok(&tokens[offset..offset + next_tokens_end])
227}
228
229fn gather<'a, 'b>(
233 collector: &'a mut DiagnosticCollector,
234 tokens: GatheredTokens<'b>,
235) -> Result<Vec<GatheredTokens<'b>>, ()> {
236 let mut offset = 0;
237 let mut result = Vec::<GatheredTokens>::new();
238 while offset < tokens.len() {
239 let next_tokens = get_next_tokens(collector, tokens, offset)?;
240 if next_tokens.is_empty() {
241 return collector.fatal(ASTParseDiagnostic::UnsupportedStructure(
242 span_from_single_token(&tokens[offset]),
243 ));
244 }
245 offset += next_tokens.len();
246 result.push(next_tokens);
247 }
248 Ok(result)
249}
250
251#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
314pub enum ASTNodeType {
315 Null, Undefined,
317 String(String), Boolean(bool), Number(String), Base64(String), Variable(String), Required(String), Let(String), Frame, Assign, LambdaDef(bool, HashSet<String>), Expressions, Apply, Operation(ASTNodeOperation), Tuple, AssumeTuple, Pair, GetAttr, Return, If, While, Modifier(ASTNodeModifier), Break, Continue, Range, In, Namespace(String), LazySet, Map, Is, Raise, Dynamic, Static, Comptime, }
355
356impl Display for ASTNodeType {
357 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
358 write!(
359 f,
360 "{}",
361 match self {
362 ASTNodeType::Null => "Null",
363 ASTNodeType::Undefined => "Undefined",
364 ASTNodeType::String(_) => "String",
365 ASTNodeType::Boolean(_) => "Boolean",
366 ASTNodeType::Number(_) => "Number",
367 ASTNodeType::Base64(_) => "Base64",
368 ASTNodeType::Variable(_) => "Variable",
369 ASTNodeType::Required(_) => "Required",
370 ASTNodeType::Let(_) => "Let",
371 ASTNodeType::Frame => "Frame",
372 ASTNodeType::Assign => "Assign",
373 ASTNodeType::LambdaDef(_, _) => "LambdaDef",
374 ASTNodeType::Expressions => "Expressions",
375 ASTNodeType::Apply => "Apply",
376 ASTNodeType::Operation(_) => "Operation",
377 ASTNodeType::Tuple => "Tuple",
378 ASTNodeType::AssumeTuple => "AssumeTuple",
379 ASTNodeType::Pair => "Pair",
380 ASTNodeType::GetAttr => "GetAttr",
381 ASTNodeType::Return => "Return",
382 ASTNodeType::If => "If",
383 ASTNodeType::While => "While",
384 ASTNodeType::Modifier(_) => "Modifier",
385 ASTNodeType::Break => "Break",
386 ASTNodeType::Continue => "Continue",
387 ASTNodeType::Range => "Range",
388 ASTNodeType::In => "In",
389 ASTNodeType::Namespace(_) => "Namespace",
390 ASTNodeType::LazySet => "LazySet",
391 ASTNodeType::Map => "Map",
392 ASTNodeType::Is => "Is",
393 ASTNodeType::Raise => "Raise",
394 ASTNodeType::Dynamic => "Dynamic",
395 ASTNodeType::Static => "Static",
396 ASTNodeType::Comptime => "Comptime",
397 }
398 )
399 }
400}
401
402#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
436pub enum ASTNodeOperation {
437 Add, Subtract, Multiply, Divide, Modulus, Power, And, Xor, Or, Not, Equal, NotEqual, Greater, Less, GreaterEqual, LessEqual, LeftShift, RightShift, Abs, Minus, }
458
459#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
486pub enum ASTNodeModifier {
487 Mut, Const, KeyOf, ValueOf, Assert, Import, TypeOf, LengthOf, Launch, Spawn, Async, Sync, Atomic, }
501
502#[derive(Debug, Clone, Serialize, Deserialize)]
522pub struct ASTNode {
523 pub node_type: ASTNodeType, pub source_location: Option<SourceLocation>, pub children: Vec<ASTNode>, }
527
528impl PartialEq for ASTNode {
529 fn eq(&self, other: &Self) -> bool {
530 self.node_type == other.node_type && self.children == other.children
531 }
532}
533
534impl ASTNode {
535 pub fn new(
545 node_type: ASTNodeType,
546 source_location: Option<SourceLocation>,
547 children: Vec<ASTNode>,
548 ) -> ASTNode {
549 ASTNode {
550 node_type,
551 source_location,
552 children,
553 }
554 }
555
556 #[allow(unused)]
563 pub fn formatted_print(&self, indent: usize) {
564 let indent_str = " ".repeat(indent);
565 let output = match &self.node_type {
566 node_type @ (ASTNodeType::Variable(v)
567 | ASTNodeType::Number(v)
568 | ASTNodeType::String(v)) => {
569 format!("{}{:?}: {:?}", indent_str, node_type, v)
570 }
571 node_type @ ASTNodeType::Boolean(v) => {
572 format!("{}{:?}: {:?}", indent_str, node_type, v)
573 }
574 node_type => format!("{}{:?}", indent_str, node_type),
575 };
576
577 println!("{}", output);
578
579 if !self.children.is_empty() {
580 for child in &self.children {
581 child.formatted_print(indent + 2);
582 }
583 }
584 }
585}
586
587type MatcherFn = fn(&mut DiagnosticCollector, &[GatheredTokens]) -> Result<Option<ASTNode>, ()>;
600
601struct NodeMatcher {
605 matchers: Vec<MatcherFn>,
606}
607
608fn span_from_tokens(tokens: &[GatheredTokens]) -> Option<SourceLocation> {
618 if tokens.is_empty() {
619 return None;
620 }
621 let first_token = tokens.first().and_then(|t| t.first());
622 let last_token = tokens.last().and_then(|t| t.last());
623 if let (Some(start_loc), Some(end_loc)) = (first_token, last_token) {
624 if start_loc.source_code().eq(end_loc.source_code()) {
625 return Some(SourceLocation {
626 span: (
627 start_loc.origin_token_span().0,
628 end_loc.origin_token_span().1,
629 ),
630 source: start_loc.source_code().clone(),
631 });
632 }
633 }
634 None
635}
636
637fn span_from_two_token(start: &Token, end: &Token) -> Option<SourceLocation> {
648 if start.source_code().eq(end.source_code()) {
649 return Some(SourceLocation {
650 span: (start.origin_token_span().0, end.origin_token_span().1),
651 source: start.source_code().clone(),
652 });
653 }
654 None
655}
656
657fn span_from_single_token(token: &Token) -> Option<SourceLocation> {
667 Some(SourceLocation {
668 span: token.origin_token_span(),
669 source: token.source_code().clone(),
670 })
671}
672
673impl NodeMatcher {
674 fn new() -> NodeMatcher {
679 NodeMatcher {
680 matchers: Vec::new(),
681 }
682 }
683
684 fn add_matcher(
691 &mut self,
692 matcher: fn(&mut DiagnosticCollector, &[GatheredTokens]) -> Result<Option<ASTNode>, ()>,
693 ) {
694 self.matchers.push(matcher);
695 }
696
697 #[stacksafe::stacksafe]
709 fn match_node(
710 &self,
711 collector: &mut DiagnosticCollector,
712 tokens: &[GatheredTokens],
713 ) -> Result<Option<ASTNode>, ()> {
714 if tokens.is_empty() {
715 return Ok(Some(ASTNode::new(ASTNodeType::Tuple, None, vec![])));
716 }
717 let mut best_match: Option<ASTNode> = None;
718 for matcher in &self.matchers {
720 match matcher(collector, tokens) {
721 Ok(Some(node)) => {
722 best_match = Some(node);
724 break;
725 }
726 Ok(None) => {
727 continue;
729 }
730 Err(e) => {
731 return Err(e);
734 }
735 }
736 }
737
738 match best_match {
740 Some(node) => Ok(Some(node)),
741 None => {
742 return collector.fatal(ASTParseDiagnostic::UnsupportedStructure(
743 span_from_tokens(tokens),
744 ));
745 }
746 }
747 }
748}
749
750fn is_symbol(token: &GatheredTokens, symbol: &str) -> bool {
761 if token.len() != 1 {
762 return false;
763 }
764 let token = &token[0];
765 token == TokenType::SYMBOL && token == symbol
766}
767
768fn is_identifier(token: &GatheredTokens, identifier: &str) -> bool {
779 if token.len() != 1 {
780 return false;
781 }
782 let token = &token[0];
783 token == TokenType::IDENTIFIER && token == identifier
784}
785
786fn unwrap_brace<'t, 'a>(
788 collector: &'a mut DiagnosticCollector,
789 token: &GatheredTokens<'t>,
790) -> Result<GatheredTokens<'t>, ()> {
791 if token.len() < 2 {
792 return collector.fatal(ASTParseDiagnostic::UnexpectedToken(span_from_single_token(
793 &token[0],
794 )));
795 }
796 if token[0] == TokenType::SYMBOL
797 && token[0] == "{"
798 && token.last().unwrap() == TokenType::SYMBOL
799 && token.last().unwrap() == "}"
800 {
801 return Ok(&token[1..token.len() - 1]);
802 }
803 if token[0] == TokenType::SYMBOL
804 && token[0] == "["
805 && token.last().unwrap() == TokenType::SYMBOL
806 && token.last().unwrap() == "]"
807 {
808 return Ok(&token[1..token.len() - 1]);
809 }
810 if token[0] == TokenType::SYMBOL
811 && token[0] == "("
812 && token.last().unwrap() == TokenType::SYMBOL
813 && token.last().unwrap() == ")"
814 {
815 return Ok(&token[1..token.len() - 1]);
816 }
817 collector.fatal(ASTParseDiagnostic::UnexpectedToken(span_from_single_token(
818 &token[0],
819 )))
820}
821
822fn is_bracket(token: &GatheredTokens) -> bool {
832 if token.len() < 2 {
833 return false;
834 }
835 token[0] == TokenType::SYMBOL
836 && token[0] == "("
837 && token.last().unwrap() == TokenType::SYMBOL
838 && token.last().unwrap() == ")"
839}
840
841fn is_brace(token: &GatheredTokens) -> bool {
851 if token.len() < 2 {
852 return false;
853 }
854 token[0] == TokenType::SYMBOL
855 && token[0] == "{"
856 && token.last().unwrap() == TokenType::SYMBOL
857 && token.last().unwrap() == "}"
858}
859
860fn is_square_bracket(token: &GatheredTokens) -> bool {
870 if token.len() < 2 {
871 return false;
872 }
873 token[0] == TokenType::SYMBOL
874 && token[0] == "["
875 && token.last().unwrap() == TokenType::SYMBOL
876 && token.last().unwrap() == "]"
877}
878
879pub fn build_ast(
897 collector: &mut DiagnosticCollector,
898 tokens: GatheredTokens<'_>,
899) -> Result<ASTNode, ()> {
900 let gathered = gather(collector, tokens)?;
901 let matched = match_all(collector, &gathered)?;
902 if matched.is_none() {
903 return Ok(ASTNode::new(ASTNodeType::Tuple, None, vec![]));
904 }
905 Ok(matched.unwrap())
906}
907
908fn match_all<'t>(
945 collector: &mut DiagnosticCollector,
946 tokens: &[GatheredTokens<'t>],
947) -> Result<Option<ASTNode>, ()> {
948 let mut node_matcher = NodeMatcher::new();
949 node_matcher.add_matcher(match_expressions);
950 node_matcher.add_matcher(match_dynamic_and_static);
951 node_matcher.add_matcher(match_return_emit_raise);
952 node_matcher.add_matcher(match_tuple);
953 node_matcher.add_matcher(match_comptime);
954 node_matcher.add_matcher(match_serialize_to_base64);
955 node_matcher.add_matcher(match_let);
956 node_matcher.add_matcher(match_assign);
957 node_matcher.add_matcher(match_map);
958 node_matcher.add_matcher(match_set_def);
959 node_matcher.add_matcher(match_lambda_def);
960 node_matcher.add_matcher(match_named_to);
961 node_matcher.add_matcher(match_pair);
962 node_matcher.add_matcher(match_while);
963 node_matcher.add_matcher(match_break_and_continue);
964 node_matcher.add_matcher(match_if);
965 node_matcher.add_matcher(match_or);
966 node_matcher.add_matcher(match_and);
967 node_matcher.add_matcher(match_xor);
968 node_matcher.add_matcher(match_not);
969 node_matcher.add_matcher(match_operation_compare);
970 node_matcher.add_matcher(match_operation_add_sub);
971 node_matcher.add_matcher(match_operation_mul_div_mod);
972 node_matcher.add_matcher(match_bitwise_shift);
973 node_matcher.add_matcher(match_unary);
974 node_matcher.add_matcher(match_power);
975 node_matcher.add_matcher(match_range);
976 node_matcher.add_matcher(match_in);
977 node_matcher.add_matcher(match_is);
978 node_matcher.add_matcher(match_as);
979 node_matcher.add_matcher(match_modifier);
980 node_matcher.add_matcher(match_quick_named_to);
981 node_matcher.add_matcher(match_assume_tuple);
982 node_matcher.add_matcher(match_alias);
983 node_matcher.add_matcher(match_member_access_and_apply);
984 node_matcher.add_matcher(match_variable);
985 node_matcher.match_node(collector, tokens)
986}
987
988macro_rules! try_match_node {
991 ($collector:expr, $tokens:expr) => {
992 match match_all($collector, $tokens) {
993 Ok(Some(node)) => node,
994 Ok(None) => return Ok(None),
995 Err(e) => return Err(e),
996 }
997 };
998}
999fn match_expressions(
1000 collector: &mut DiagnosticCollector,
1001 tokens: &[GatheredTokens],
1002) -> Result<Option<ASTNode>, ()> {
1003 let mut offset = 0usize;
1004 let mut left_start = 0usize;
1005 let mut separated = Vec::<ASTNode>::new();
1006 while offset < tokens.len() {
1007 if is_symbol(&tokens[offset], ";") {
1008 let left_tokens = &tokens[left_start..offset];
1009 separated.push(try_match_node!(collector, left_tokens));
1010 left_start = offset + 1;
1011 }
1012 offset += 1;
1013 }
1014 if separated.is_empty() {
1015 return Ok(None);
1016 }
1017 let left_tokens = &tokens[left_start..offset];
1018 separated.push(try_match_node!(collector, left_tokens));
1019 Ok(Some(ASTNode::new(
1020 ASTNodeType::Expressions,
1021 span_from_tokens(tokens),
1022 separated,
1023 )))
1024}
1025
1026fn match_comptime(
1027 collector: &mut DiagnosticCollector,
1028 tokens: &[GatheredTokens],
1029) -> Result<Option<ASTNode>, ()> {
1030 if tokens.is_empty() || !is_symbol(&tokens[0], "@") {
1031 return Ok(None);
1032 }
1033 let right = try_match_node!(collector, &tokens[1..]);
1034 let node = ASTNode::new(
1035 ASTNodeType::Comptime,
1036 span_from_tokens(&tokens),
1037 vec![right],
1038 );
1039 Ok(Some(node))
1040}
1041
1042fn match_serialize_to_base64(
1043 collector: &mut DiagnosticCollector,
1044 tokens: &[GatheredTokens],
1045) -> Result<Option<ASTNode>, ()> {
1046 if tokens.is_empty() || !is_symbol(&tokens[0], "$") {
1047 return Ok(None);
1048 }
1049 let ast = try_match_node!(collector, &tokens[1..]);
1050
1051 let serialized = match bincode::serde::encode_to_vec(&ast, bincode::config::standard()) {
1052 Ok(data) => data,
1053 Err(err) => {
1054 return collector.fatal(ASTParseDiagnostic::InvalidSyntax(
1055 span_from_tokens(&tokens),
1056 format!("Failed to serialize AST: {}", err),
1057 ));
1058 }
1059 };
1060 let base64_encoded = base64::engine::general_purpose::STANDARD.encode(serialized);
1061
1062 let get_attr_node = ASTNode::new(
1066 ASTNodeType::GetAttr,
1067 None, vec![
1069 ASTNode::new(ASTNodeType::Variable("ast".to_string()), None, vec![]),
1070 ASTNode::new(ASTNodeType::String("deserialize".to_string()), None, vec![]),
1071 ],
1072 );
1073
1074 let arg_node = ASTNode::new(ASTNodeType::Base64(base64_encoded), None, vec![]);
1076
1077 let apply_node = ASTNode::new(
1079 ASTNodeType::Apply,
1080 span_from_tokens(&tokens), vec![get_attr_node, arg_node],
1082 );
1083
1084 Ok(Some(apply_node))
1085}
1086fn match_dynamic_and_static(
1087 collector: &mut DiagnosticCollector,
1088 tokens: &[GatheredTokens],
1089) -> Result<Option<ASTNode>, ()> {
1090 if tokens.len() == 0
1091 || !is_symbol(&tokens[0], "dynamic") && !is_identifier(&tokens[0], "static")
1092 {
1093 return Ok(None);
1094 }
1095 let right = try_match_node!(collector, &tokens[1..]);
1096 let node = ASTNode::new(
1097 if is_identifier(&tokens[0], "dynamic") {
1098 ASTNodeType::Dynamic
1099 } else {
1100 ASTNodeType::Static
1101 },
1102 span_from_tokens(&tokens),
1103 vec![right],
1104 );
1105 Ok(Some(node))
1106}
1107
1108fn match_return_emit_raise(
1109 collector: &mut DiagnosticCollector,
1110 tokens: &[GatheredTokens],
1111) -> Result<Option<ASTNode>, ()> {
1112 if tokens.len() == 0
1113 || !is_identifier(&tokens[0], "return") && !is_identifier(&tokens[0], "raise")
1114 {
1115 return Ok(None);
1116 }
1117 let right = try_match_node!(collector, &tokens[1..]);
1118 Ok(Some(ASTNode::new(
1119 if is_identifier(&tokens[0], "return") {
1120 ASTNodeType::Return
1121 } else {
1122 ASTNodeType::Raise
1123 },
1124 span_from_tokens(&tokens),
1125 vec![right],
1126 )))
1127}
1128
1129fn match_tuple(
1130 collector: &mut DiagnosticCollector,
1131 tokens: &[GatheredTokens],
1132) -> Result<Option<ASTNode>, ()> {
1133 let mut offset = 0usize;
1134 let mut left_tokens = Vec::<GatheredTokens>::new();
1135 let mut separated = Vec::<ASTNode>::new();
1136 while offset < tokens.len() {
1137 if is_symbol(&tokens[offset], ",") {
1138 if !left_tokens.is_empty() {
1139 separated.push(try_match_node!(collector, &left_tokens));
1140 left_tokens.clear();
1141 }
1142 } else {
1143 left_tokens.push(tokens[offset]);
1144 }
1145 offset += 1;
1146 }
1147 if separated.is_empty() {
1148 return Ok(None);
1149 }
1150 if !left_tokens.is_empty() {
1151 separated.push(try_match_node!(collector, &left_tokens));
1152 }
1153 Ok(Some(ASTNode::new(
1154 ASTNodeType::Tuple,
1155 span_from_tokens(&tokens),
1156 separated,
1157 )))
1158}
1159
1160fn match_let(
1161 collector: &mut DiagnosticCollector,
1162 tokens: &[GatheredTokens],
1163) -> Result<Option<ASTNode>, ()> {
1164 if tokens.len() <= 2 || !is_symbol(&tokens[1], ":=") {
1165 return Ok(None);
1166 }
1167 let left_tokens = gather(collector, tokens[0])?;
1168 let left = try_match_node!(collector, &left_tokens);
1169 let right = try_match_node!(collector, &tokens[2..]);
1170
1171 match left.node_type {
1172 ASTNodeType::Variable(name) | ASTNodeType::String(name) => Ok(Some(ASTNode::new(
1173 ASTNodeType::Let(name),
1174 span_from_tokens(&tokens),
1175 vec![right],
1176 ))),
1177 _ => {
1178 return collector.fatal(ASTParseDiagnostic::InvalidVariableName(span_from_tokens(
1179 &left_tokens,
1180 )));
1181 }
1182 }
1183}
1184
1185fn match_assign(
1186 collector: &mut DiagnosticCollector,
1187 tokens: &[GatheredTokens],
1188) -> Result<Option<ASTNode>, ()> {
1189 if tokens.len() == 0 {
1191 return Ok(None);
1192 }
1193
1194 let mut offset = 0;
1196 let mut left_tokens: Vec<&[Token]> = Vec::new();
1197
1198 while offset < tokens.len() {
1199 if is_symbol(&tokens[offset], "=") {
1201 break;
1202 }
1203 left_tokens.push(tokens[offset]);
1204 offset += 1;
1205 }
1206
1207 if offset >= tokens.len() {
1209 return Ok(None);
1210 }
1211
1212 let left = try_match_node!(collector, &left_tokens);
1213 let right = try_match_node!(collector, &tokens[offset + 1..]);
1214
1215 return Ok(Some(ASTNode::new(
1216 ASTNodeType::Assign,
1217 span_from_tokens(&tokens),
1218 vec![left, right],
1219 )));
1220}
1221
1222fn match_named_to(
1223 collector: &mut DiagnosticCollector,
1224 tokens: &[GatheredTokens],
1225) -> Result<Option<ASTNode>, ()> {
1226 if tokens.len() <= 2 || !is_symbol(&tokens[1], "=>") {
1227 return Ok(None);
1228 }
1229
1230 let left_tokens = gather(collector, tokens[0])?;
1231 let mut left = try_match_node!(collector, &left_tokens);
1232
1233 if let ASTNodeType::Variable(name) = left.node_type {
1234 left = ASTNode::new(
1235 ASTNodeType::String(name),
1236 left.source_location,
1237 left.children,
1238 );
1239 }
1240 let right = try_match_node!(collector, &tokens[2..]);
1241 Ok(Some(ASTNode::new(
1242 ASTNodeType::Pair,
1243 span_from_tokens(&tokens),
1244 vec![left, right],
1245 )))
1246}
1247
1248fn match_pair(
1249 collector: &mut DiagnosticCollector,
1250 tokens: &[GatheredTokens],
1251) -> Result<Option<ASTNode>, ()> {
1252 if tokens.len() <= 2 || !is_symbol(&tokens[1], ":") {
1253 return Ok(None);
1254 }
1255
1256 let left_tokens = gather(collector, tokens[0])?;
1257 let left = try_match_node!(collector, &left_tokens);
1258 let right = try_match_node!(collector, &tokens[2..]);
1259 Ok(Some(ASTNode::new(
1260 ASTNodeType::Pair,
1261 span_from_tokens(&tokens),
1262 vec![left, right],
1263 )))
1264}
1265
1266fn match_while(
1267 collector: &mut DiagnosticCollector,
1268 tokens: &[GatheredTokens],
1269) -> Result<Option<ASTNode>, ()> {
1270 if tokens.len() <= 2 || !is_identifier(&tokens[0], "while") {
1271 return Ok(None);
1272 }
1273 let condition_tokens = gather(collector, tokens[1])?;
1274 let condition = try_match_node!(collector, &condition_tokens);
1275 let body = try_match_node!(collector, &tokens[2..]);
1276 Ok(Some(ASTNode::new(
1277 ASTNodeType::While,
1278 span_from_tokens(&tokens),
1279 vec![condition, body],
1280 )))
1281}
1282
1283fn match_if(
1284 collector: &mut DiagnosticCollector,
1285 tokens: &[GatheredTokens],
1286) -> Result<Option<ASTNode>, ()> {
1287 if tokens.len() <= 2 || !is_identifier(&tokens[0], "if") {
1288 return Ok(None);
1289 }
1290
1291 let condition_tokens = gather(collector, tokens[1])?;
1292 let true_condition_tokens = gather(collector, tokens[2])?;
1293
1294 let condition = try_match_node!(collector, &condition_tokens);
1295 let true_condition = try_match_node!(collector, &true_condition_tokens);
1296
1297 if 3 < tokens.len() && is_identifier(&tokens[3], "else") {
1298 let false_condition = try_match_node!(collector, &tokens[4..]);
1299 return Ok(Some(ASTNode::new(
1300 ASTNodeType::If,
1301 span_from_tokens(&tokens),
1302 vec![condition, true_condition, false_condition],
1303 )));
1304 }
1305 Ok(Some(ASTNode::new(
1306 ASTNodeType::If,
1307 span_from_tokens(&tokens),
1308 vec![condition, true_condition],
1309 )))
1310}
1311
1312fn match_break_and_continue(
1313 collector: &mut DiagnosticCollector,
1314 tokens: &[GatheredTokens],
1315) -> Result<Option<ASTNode>, ()> {
1316 if tokens.len() == 0 {
1317 return Ok(None);
1318 }
1319 if is_identifier(&tokens[0], "break") {
1320 let right = try_match_node!(collector, &tokens[1..]);
1321 return Ok(Some(ASTNode::new(
1322 ASTNodeType::Break,
1323 span_from_tokens(&tokens),
1324 vec![right],
1325 )));
1326 } else if is_identifier(&tokens[0], "continue") {
1327 let right = try_match_node!(collector, &tokens[1..]);
1328 return Ok(Some(ASTNode::new(
1329 ASTNodeType::Continue,
1330 span_from_tokens(&tokens),
1331 vec![right],
1332 )));
1333 }
1334 Ok(None)
1335}
1336
1337fn match_or(
1338 collector: &mut DiagnosticCollector,
1339 tokens: &[GatheredTokens],
1340) -> Result<Option<ASTNode>, ()> {
1341 let mut offset: usize = tokens.len() - 1;
1342 let mut operator = Option::<&str>::None;
1343 let mut operator_pos: usize = 0;
1344 while offset > 0 {
1345 let pos = offset;
1346 if is_identifier(&tokens[pos], "or") {
1347 operator = Some("or");
1348 operator_pos = pos;
1349 break;
1350 }
1351 offset -= 1;
1352 }
1353 if operator.is_none() {
1354 return Ok(None);
1355 }
1356
1357 let left = try_match_node!(collector, &tokens[..operator_pos]);
1358 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1359
1360 return Ok(Some(ASTNode::new(
1361 ASTNodeType::Operation(ASTNodeOperation::Or),
1362 span_from_tokens(&tokens),
1363 vec![left, right],
1364 )));
1365}
1366
1367fn match_and(
1368 collector: &mut DiagnosticCollector,
1369 tokens: &[GatheredTokens],
1370) -> Result<Option<ASTNode>, ()> {
1371 let mut offset: usize = tokens.len() - 1;
1372 let mut operator = Option::<&str>::None;
1373 let mut operator_pos: usize = 0;
1374 while offset > 0 {
1375 let pos = offset;
1376 if is_identifier(&tokens[pos], "and") {
1377 operator = Some("and");
1378 operator_pos = pos;
1379 break;
1380 }
1381 offset -= 1;
1382 }
1383 if operator.is_none() {
1384 return Ok(None);
1385 }
1386
1387 let left = try_match_node!(collector, &tokens[..operator_pos]);
1388 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1389
1390 return Ok(Some(ASTNode::new(
1391 ASTNodeType::Operation(ASTNodeOperation::And),
1392 span_from_tokens(&tokens),
1393 vec![left, right],
1394 )));
1395}
1396
1397fn match_xor(
1398 collector: &mut DiagnosticCollector,
1399 tokens: &[GatheredTokens],
1400) -> Result<Option<ASTNode>, ()> {
1401 if tokens.len() == 0 {
1402 return Ok(None);
1403 }
1404 let mut offset: usize = tokens.len() - 1;
1405 let mut operator = Option::<&str>::None;
1406 let mut operator_pos: usize = 0;
1407 while offset > 0 {
1408 let pos = offset;
1409 if is_identifier(&tokens[pos], "xor") {
1410 operator = Some("xor");
1411 operator_pos = pos;
1412 break;
1413 }
1414 offset -= 1;
1415 }
1416 if operator.is_none() {
1417 return Ok(None);
1418 }
1419
1420 let left = try_match_node!(collector, &tokens[..operator_pos]);
1421 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1422
1423 return Ok(Some(ASTNode::new(
1424 ASTNodeType::Operation(ASTNodeOperation::Xor),
1425 span_from_tokens(&tokens),
1426 vec![left, right],
1427 )));
1428}
1429
1430fn match_not(
1431 collector: &mut DiagnosticCollector,
1432 tokens: &[GatheredTokens],
1433) -> Result<Option<ASTNode>, ()> {
1434 if tokens.len() <= 1 || !is_identifier(&tokens[0], "not") {
1435 return Ok(None);
1436 }
1437 let node = try_match_node!(collector, &tokens[1..]);
1438 return Ok(Some(ASTNode::new(
1439 ASTNodeType::Operation(ASTNodeOperation::Not),
1440 span_from_tokens(&tokens),
1441 vec![node],
1442 )));
1443}
1444
1445fn match_operation_compare(
1447 collector: &mut DiagnosticCollector,
1448 tokens: &[GatheredTokens],
1449) -> Result<Option<ASTNode>, ()> {
1450 if tokens.len() == 0 {
1451 return Ok(None);
1452 }
1453 let mut offset: usize = tokens.len() - 1;
1454 let mut operator = None;
1455 let mut operator_pos: usize = 0;
1456 while offset > 0 {
1457 let pos = offset;
1458 if is_symbol(&tokens[pos], ">")
1459 || is_symbol(&tokens[pos], "<")
1460 || is_symbol(&tokens[pos], ">=")
1461 || is_symbol(&tokens[pos], "<=")
1462 || is_symbol(&tokens[pos], "==")
1463 || is_symbol(&tokens[pos], "!=")
1464 {
1465 operator = Some(tokens[pos][0].token());
1466 operator_pos = pos;
1467 break;
1468 }
1469 offset -= 1;
1470 }
1471 if operator.is_none() {
1472 return Ok(None);
1473 }
1474
1475 let left = try_match_node!(collector, &tokens[..operator_pos]);
1476 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1477
1478 let operation = match operator.unwrap().as_str() {
1479 ">" => ASTNodeOperation::Greater,
1480 "<" => ASTNodeOperation::Less,
1481 ">=" => ASTNodeOperation::GreaterEqual,
1482 "<=" => ASTNodeOperation::LessEqual,
1483 "==" => ASTNodeOperation::Equal,
1484 "!=" => ASTNodeOperation::NotEqual,
1485 _ => unreachable!(),
1486 };
1487 return Ok(Some(ASTNode::new(
1488 ASTNodeType::Operation(operation),
1489 span_from_tokens(&tokens),
1490 vec![left, right],
1491 )));
1492}
1493
1494fn match_operation_add_sub(
1496 collector: &mut DiagnosticCollector,
1497 tokens: &[GatheredTokens],
1498) -> Result<Option<ASTNode>, ()> {
1499 if tokens.is_empty() {
1500 return Ok(None);
1501 }
1502 let mut offset: usize = tokens.len() - 1;
1503 let mut operator = None;
1504 let mut operator_pos: usize = 0;
1505 while offset > 0 {
1506 let pos = offset;
1507 if is_symbol(&tokens[pos], "+") || is_symbol(&tokens[pos], "-") {
1508 operator = Some(tokens[pos][0].token());
1509 operator_pos = pos;
1510 break;
1511 }
1512 offset -= 1;
1513 }
1514 if operator.is_none() {
1515 return Ok(None);
1516 }
1517 if operator_pos == 0 {
1518 return Ok(None);
1519 }
1520 let left = try_match_node!(collector, &tokens[..operator_pos]);
1521 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1522 let op = operator.unwrap();
1523 let operation = if op == "+" {
1524 ASTNodeOperation::Add
1525 } else {
1526 ASTNodeOperation::Subtract
1527 };
1528 return Ok(Some(ASTNode::new(
1529 ASTNodeType::Operation(operation),
1530 span_from_tokens(&tokens),
1531 vec![left, right],
1532 )));
1533}
1534
1535fn match_operation_mul_div_mod(
1536 collector: &mut DiagnosticCollector,
1537 tokens: &[GatheredTokens],
1538) -> Result<Option<ASTNode>, ()> {
1539 if tokens.is_empty() {
1540 return Ok(None);
1541 }
1542 let mut offset: usize = tokens.len() - 1;
1543 let mut operator = None;
1544 let mut operator_pos: usize = 0;
1545 while offset > 0 {
1546 let pos = offset;
1547 if is_symbol(&tokens[pos], "*")
1548 || is_symbol(&tokens[pos], "/")
1549 || is_symbol(&tokens[pos], "%")
1550 {
1551 operator = Some(tokens[pos][0].token());
1552 operator_pos = pos;
1553 break;
1554 }
1555 offset -= 1;
1556 }
1557 if operator.is_none() {
1558 return Ok(None);
1559 }
1560 let left = try_match_node!(collector, &tokens[..operator_pos]);
1561 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1562 let operation = match operator.unwrap().as_str() {
1563 "*" => ASTNodeOperation::Multiply,
1564 "/" => ASTNodeOperation::Divide,
1565 "%" => ASTNodeOperation::Modulus,
1566 _ => unreachable!(),
1567 };
1568 return Ok(Some(ASTNode::new(
1569 ASTNodeType::Operation(operation),
1570 span_from_tokens(&tokens),
1571 vec![left, right],
1572 )));
1573}
1574
1575fn match_bitwise_shift(
1576 collector: &mut DiagnosticCollector,
1577 tokens: &[GatheredTokens],
1578) -> Result<Option<ASTNode>, ()> {
1579 if tokens.is_empty() {
1580 return Ok(None);
1581 }
1582 let mut offset: usize = tokens.len() - 1;
1583 let mut operator = None;
1584 let mut operator_pos: usize = 0;
1585 while offset > 0 {
1586 let pos = offset;
1587 if is_symbol(&tokens[pos], "<<") || is_symbol(&tokens[pos], ">>") {
1588 operator = Some(tokens[pos][0].token());
1589 operator_pos = pos;
1590 break;
1591 }
1592 offset -= 1;
1593 }
1594 if operator.is_none() {
1595 return Ok(None);
1596 }
1597
1598 let left = try_match_node!(collector, &tokens[..operator_pos]);
1599 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1600
1601 return Ok(Some(ASTNode::new(
1602 ASTNodeType::Operation(if operator.unwrap() == "<<" {
1603 ASTNodeOperation::LeftShift
1604 } else {
1605 ASTNodeOperation::RightShift
1606 }),
1607 span_from_tokens(&tokens),
1608 vec![left, right],
1609 )));
1610}
1611
1612fn match_unary(
1613 collector: &mut DiagnosticCollector,
1614 tokens: &[GatheredTokens],
1615) -> Result<Option<ASTNode>, ()> {
1616 if tokens.is_empty() {
1617 return Ok(None);
1618 }
1619 if is_symbol(&tokens[0], "-") || is_symbol(&tokens[0], "+") {
1620 if tokens.len() <= 1 {
1621 return Ok(None);
1622 };
1623 let right = try_match_node!(collector, &tokens[1..]);
1624 let operation = match tokens[0][0].token().as_str() {
1625 "-" => ASTNodeOperation::Minus,
1626 "+" => ASTNodeOperation::Abs,
1627 _ => unreachable!(),
1628 };
1629 return Ok(Some(ASTNode::new(
1630 ASTNodeType::Operation(operation),
1631 span_from_tokens(&tokens),
1632 vec![right],
1633 )));
1634 }
1635 Ok(None)
1636}
1637
1638fn match_power(
1639 collector: &mut DiagnosticCollector,
1640 tokens: &[GatheredTokens],
1641) -> Result<Option<ASTNode>, ()> {
1642 if tokens.len() < 3 {
1643 return Ok(None);
1644 }
1645
1646 let find = tokens.iter().position(|token| is_symbol(token, "**"));
1648 if find.is_none() {
1649 return Ok(None);
1650 }
1651 let operator_pos = find.unwrap();
1652 if operator_pos + 1 >= tokens.len() {
1653 return Ok(None);
1654 }
1655 let left = try_match_node!(collector, &tokens[..operator_pos]);
1656 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1657
1658 return Ok(Some(ASTNode::new(
1659 ASTNodeType::Operation(ASTNodeOperation::Power),
1660 span_from_tokens(&tokens),
1661 vec![left, right],
1662 )));
1663}
1664fn match_map(
1665 collector: &mut DiagnosticCollector,
1666 tokens: &[GatheredTokens],
1667) -> Result<Option<ASTNode>, ()> {
1668 if tokens.is_empty() {
1669 return Ok(None);
1670 }
1671
1672 let mut offset: usize = tokens.len() - 1;
1674 let mut operator_pos: usize = 0;
1675 let mut found = false;
1676
1677 while offset > 0 {
1678 let pos = offset;
1679 if is_symbol(&tokens[pos], "|>") {
1680 operator_pos = pos;
1681 found = true;
1682 break;
1683 }
1684 offset -= 1;
1685 }
1686
1687 if !found {
1688 return Ok(None);
1689 }
1690
1691 let left = try_match_node!(collector, &tokens[..operator_pos]);
1692 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1693
1694 return Ok(Some(ASTNode::new(
1695 ASTNodeType::Map,
1696 span_from_tokens(&tokens),
1697 vec![left, right],
1698 )));
1699}
1700fn match_set_def(
1701 collector: &mut DiagnosticCollector,
1702 tokens: &[GatheredTokens],
1703) -> Result<Option<ASTNode>, ()> {
1704 if tokens.is_empty() {
1705 return Ok(None);
1706 }
1707
1708 let mut offset: usize = tokens.len() - 1;
1710 let mut operator_pos: usize = 0;
1711 let mut found = false;
1712
1713 while offset > 0 {
1714 let pos = offset;
1715 if is_symbol(&tokens[pos], "|") {
1716 operator_pos = pos;
1717 found = true;
1718 break;
1719 }
1720 offset -= 1;
1721 }
1722
1723 if !found {
1724 return Ok(None);
1725 }
1726
1727 let left = try_match_node!(collector, &tokens[..operator_pos]);
1728 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
1729
1730 return Ok(Some(ASTNode::new(
1731 ASTNodeType::LazySet,
1732 span_from_tokens(&tokens),
1733 vec![left, right],
1734 )));
1735}
1736
1737fn match_lambda_def(
1738 collector: &mut DiagnosticCollector,
1739 tokens: &[GatheredTokens],
1740) -> Result<Option<ASTNode>, ()> {
1741 if tokens.len() < 3 {
1743 return Ok(None);
1744 }
1745 if !is_symbol(&tokens[1], "->") {
1747 return Ok(None);
1748 }
1749
1750 let left_tokens = gather(collector, tokens[0])?;
1752 let left = try_match_node!(collector, &left_tokens);
1753
1754 let mut body_start_index = 2; let mut capture_vars = HashSet::new();
1756 if body_start_index < tokens.len() && is_symbol(&tokens[body_start_index], "&") {
1757 body_start_index += 1; if body_start_index >= tokens.len() {
1760 return collector.fatal(ASTParseDiagnostic::MissingStructure(
1761 span_from_single_token(tokens.last().unwrap().last().unwrap()), "Lambda capture".to_string(),
1763 ));
1764 }
1765 let capture = gather(collector, tokens[body_start_index])?;
1767 let capture_node = try_match_node!(collector, &capture);
1768 match capture_node.node_type {
1769 ASTNodeType::String(v) | ASTNodeType::Variable(v) => {
1770 capture_vars.insert(v);
1772 }
1773 ASTNodeType::Tuple => {
1774 for child in &capture_node.children {
1775 if let ASTNodeType::String(v) | ASTNodeType::Variable(v) = &child.node_type {
1776 capture_vars.insert(v.clone());
1777 } else {
1778 return collector.fatal(ASTParseDiagnostic::InvalidSyntax(
1779 span_from_single_token(tokens[body_start_index].first().unwrap()),
1780 "Capture must be a variable or tuple of variables".to_string(),
1781 ));
1782 }
1783 }
1784 }
1785 _ => {
1786 return collector.fatal(ASTParseDiagnostic::InvalidSyntax(
1787 span_from_single_token(tokens[body_start_index].first().unwrap()),
1788 "Capture must be a variable or tuple of variables".to_string(),
1789 ));
1790 }
1791 }
1792 body_start_index += 1;
1793 }
1794
1795 let is_dyn = body_start_index < tokens.len() && is_identifier(&tokens[body_start_index], "dyn");
1797 if is_dyn {
1798 body_start_index += 1;
1799 }
1800
1801 if body_start_index >= tokens.len() {
1803 return collector.fatal(ASTParseDiagnostic::MissingStructure(
1804 span_from_single_token(tokens.last().unwrap().last().unwrap()), "Lambda body".to_string(),
1806 ));
1807 }
1808
1809 let right = try_match_node!(collector, &tokens[body_start_index..]);
1811
1812 Ok(Some(ASTNode::new(
1813 ASTNodeType::LambdaDef(is_dyn, capture_vars),
1815 span_from_tokens(&tokens),
1816 vec![left, right],
1817 )))
1818}
1819
1820fn match_modifier(
1821 collector: &mut DiagnosticCollector,
1822 tokens: &[GatheredTokens],
1823) -> Result<Option<ASTNode>, ()> {
1824 if tokens.len() < 2 {
1825 return Ok(None);
1826 }
1827 if tokens[0].len() == 1
1828 && vec![
1829 "mut", "const", "keyof", "valueof", "assert", "import", "typeof", "lengthof", "launch",
1830 "spawn", "async", "sync", "atomic",
1831 ]
1832 .contains(&tokens[0].first().unwrap().token().as_str())
1833 {
1834 let right = try_match_node!(collector, &tokens[1..]);
1835 let modifier = match tokens[0].first().unwrap().token().as_str() {
1836 "mut" => ASTNodeModifier::Mut,
1837 "const" => ASTNodeModifier::Const,
1838 "keyof" => ASTNodeModifier::KeyOf,
1839 "valueof" => ASTNodeModifier::ValueOf,
1840 "assert" => ASTNodeModifier::Assert,
1841 "import" => ASTNodeModifier::Import,
1842 "typeof" => ASTNodeModifier::TypeOf,
1843 "lengthof" => ASTNodeModifier::LengthOf,
1844 "launch" => ASTNodeModifier::Launch,
1845 "spawn" => ASTNodeModifier::Spawn,
1846 "async" => ASTNodeModifier::Async,
1847 "sync" => ASTNodeModifier::Sync,
1848 "atomic" => ASTNodeModifier::Atomic,
1849 _ => return Ok(None),
1850 };
1851 return Ok(Some(ASTNode::new(
1852 ASTNodeType::Modifier(modifier),
1853 span_from_tokens(&tokens),
1854 vec![right],
1855 )));
1856 }
1857 Ok(None)
1858}
1859
1860fn match_quick_named_to(
1861 collector: &mut DiagnosticCollector,
1862 tokens: &[GatheredTokens],
1863) -> Result<Option<ASTNode>, ()> {
1864 if tokens.len() <= 1 {
1866 return Ok(None);
1867 }
1868 if is_symbol(&tokens[tokens.len() - 1], "?") {
1869 let left_tokens = tokens[..tokens.len() - 1].to_vec();
1870 let mut node = try_match_node!(collector, &left_tokens);
1871 if let ASTNodeType::Variable(name) = node.node_type {
1872 node = ASTNode::new(
1873 ASTNodeType::String(name),
1874 node.source_location,
1875 node.children,
1876 );
1877 }
1878 return Ok(Some(ASTNode::new(
1879 ASTNodeType::Pair,
1880 span_from_tokens(&tokens),
1881 vec![node, ASTNode::new(ASTNodeType::Boolean(true), None, vec![])],
1882 )));
1883 }
1884 Ok(None)
1885}
1886
1887fn match_assume_tuple(
1888 collector: &mut DiagnosticCollector,
1889 tokens: &[GatheredTokens],
1890) -> Result<Option<ASTNode>, ()> {
1891 if tokens.len() < 2 {
1892 return Ok(None);
1893 }
1894 if !is_symbol(&tokens[0], "...") {
1895 return Ok(None);
1896 }
1897 let right = try_match_node!(collector, &tokens[1..]);
1898 Ok(Some(ASTNode::new(
1899 ASTNodeType::AssumeTuple,
1900 span_from_tokens(&tokens),
1901 vec![right],
1902 )))
1903}
1904
1905fn match_alias(
1906 collector: &mut DiagnosticCollector,
1907 tokens: &[GatheredTokens],
1908) -> Result<Option<ASTNode>, ()> {
1909 if tokens.len() < 3 {
1910 return Ok(None);
1911 }
1912
1913 if !is_symbol(&tokens[1], "::") {
1914 return Ok(None);
1915 }
1916
1917 let type_tokens = gather(collector, tokens[0])?;
1918 let type_node = try_match_node!(collector, &type_tokens);
1919
1920 let type_name = match &type_node.node_type {
1921 ASTNodeType::Variable(name) => name.clone(),
1922 ASTNodeType::String(name) => name.clone(),
1923 _ => {
1924 return collector.fatal(ASTParseDiagnostic::InvalidSyntax(
1925 span_from_single_token(tokens[0].first().unwrap()),
1926 "Expected identifier".to_string(),
1927 ));
1928 }
1929 };
1930
1931 let right = try_match_node!(collector, &tokens[2..]);
1933
1934 Ok(Some(ASTNode::new(
1935 ASTNodeType::Namespace(type_name),
1936 span_from_tokens(&tokens),
1937 vec![right],
1938 )))
1939}
1940
1941fn match_member_access_and_apply(
1942 collector: &mut DiagnosticCollector,
1943 tokens: &[GatheredTokens],
1944) -> Result<Option<ASTNode>, ()> {
1945 if tokens.len() <= 1 {
1947 return Ok(None);
1948 }
1949
1950 let is_member_access = is_symbol(&tokens[tokens.len() - 2], ".");
1951 let left = if is_member_access {
1952 tokens[..tokens.len() - 2].to_vec()
1953 } else {
1954 tokens[..tokens.len() - 1].to_vec()
1955 };
1956 let left_node = try_match_node!(collector, &left);
1957 let right_tokens = gather(collector, &tokens.last().unwrap())?;
1958 let mut right_node = try_match_node!(collector, &right_tokens);
1959
1960 if let ASTNodeType::Variable(name) = &right_node.node_type {
1961 if is_member_access {
1962 right_node = ASTNode::new(
1964 ASTNodeType::String(name.clone()),
1965 right_node.source_location.clone(),
1966 right_node.children,
1967 );
1968 }
1969 }
1970
1971 return Ok(Some(ASTNode::new(
1972 if is_member_access {
1973 ASTNodeType::GetAttr
1974 } else {
1975 ASTNodeType::Apply
1976 },
1977 span_from_tokens(&tokens),
1978 vec![left_node, right_node],
1979 )));
1980}
1981
1982fn match_range(
1983 collector: &mut DiagnosticCollector,
1984 tokens: &[GatheredTokens],
1985) -> Result<Option<ASTNode>, ()> {
1986 if tokens.len() < 3 {
1987 return Ok(None);
1988 }
1989 if !is_symbol(&tokens[1], "..") {
1990 return Ok(None);
1992 }
1993
1994 let left_tokens = gather(collector, tokens[0])?;
1995 let left = try_match_node!(collector, &left_tokens);
1996 let right = try_match_node!(collector, &tokens[2..]);
1997
1998 Ok(Some(ASTNode::new(
1999 ASTNodeType::Range,
2000 span_from_tokens(&tokens),
2001 vec![left, right],
2002 )))
2003}
2004
2005fn match_in(
2006 collector: &mut DiagnosticCollector,
2007 tokens: &[GatheredTokens],
2008) -> Result<Option<ASTNode>, ()> {
2009 if 2 >= tokens.len() {
2010 return Ok(None);
2011 }
2012 if !is_identifier(&tokens[1], "in") {
2013 return Ok(None);
2014 }
2015
2016 let left_tokens = gather(collector, tokens[0])?;
2017 let left = try_match_node!(collector, &left_tokens);
2018 let right = try_match_node!(collector, &tokens[2..]);
2019
2020 Ok(Some(ASTNode::new(
2021 ASTNodeType::In,
2022 span_from_tokens(&tokens),
2023 vec![left, right],
2024 )))
2025}
2026
2027fn match_is(
2028 collector: &mut DiagnosticCollector,
2029 tokens: &[GatheredTokens],
2030) -> Result<Option<ASTNode>, ()> {
2031 if tokens.len() <= 2 {
2032 return Ok(None);
2033 }
2034 if !is_identifier(&tokens[1], "is") {
2035 return Ok(None);
2036 }
2037
2038 let left_tokens = gather(collector, tokens[0])?;
2039 let left = try_match_node!(collector, &left_tokens);
2040 let right = try_match_node!(collector, &tokens[2..]);
2041
2042 Ok(Some(ASTNode::new(
2043 ASTNodeType::Is,
2044 span_from_tokens(&tokens),
2045 vec![left, right],
2046 )))
2047}
2048
2049fn match_as(
2050 collector: &mut DiagnosticCollector,
2051 tokens: &[GatheredTokens],
2052) -> Result<Option<ASTNode>, ()> {
2053 if tokens.len() <= 2 {
2055 return Ok(None);
2056 }
2057
2058 let mut offset: usize = tokens.len() - 1;
2060 let mut operator_pos: usize = 0;
2061 let mut found = false;
2062
2063 while offset > 0 {
2064 let pos = offset;
2065 if is_identifier(&tokens[pos], "as") {
2066 operator_pos = pos;
2067 found = true;
2068 break;
2069 }
2070 offset -= 1;
2071 }
2072
2073 if !found {
2074 return Ok(None);
2075 }
2076
2077 let left = try_match_node!(collector, &tokens[..operator_pos]);
2079
2080 let right = try_match_node!(collector, &tokens[operator_pos + 1..]);
2082
2083 Ok(Some(ASTNode::new(
2084 ASTNodeType::Apply,
2085 span_from_tokens(&tokens),
2086 vec![right, left],
2087 )))
2088}
2089
2090fn match_variable(
2091 collector: &mut DiagnosticCollector,
2092 tokens: &[GatheredTokens],
2093) -> Result<Option<ASTNode>, ()> {
2094 if tokens.is_empty() {
2095 return Ok(None);
2096 }
2097 if is_bracket(&tokens[0]) || is_square_bracket(&tokens[0]) {
2099 let inner_tokens = unwrap_brace(collector, &tokens[0])?;
2100 let gathered_inner = gather(collector, inner_tokens)?;
2101 let node = try_match_node!(collector, &gathered_inner);
2102 return Ok(Some(node));
2103 }
2104
2105 if is_brace(&tokens[0]) {
2107 let body_tokens = unwrap_brace(collector, &tokens[0])?;
2108 let gathered_body = gather(collector, body_tokens)?;
2109 let body = try_match_node!(collector, &gathered_body);
2110
2111 return Ok(Some(ASTNode::new(
2112 ASTNodeType::Frame,
2113 span_from_tokens(&tokens),
2114 vec![body],
2115 )));
2116 }
2117
2118 if tokens[0].len() == 1 && tokens[0].first().unwrap() == TokenType::STRING {
2120 return Ok(Some(ASTNode::new(
2121 ASTNodeType::String(tokens[0].first().unwrap().token().clone()),
2122 span_from_tokens(&tokens),
2123 vec![],
2124 )));
2125 }
2126
2127 if tokens[0].len() == 1 && tokens[0].first().unwrap() == TokenType::NUMBER {
2129 return Ok(Some(ASTNode::new(
2130 ASTNodeType::Number(tokens[0].first().unwrap().token().clone()),
2131 span_from_tokens(&tokens),
2132 vec![],
2133 )));
2134 }
2135
2136 if tokens[0].len() == 1 && tokens[0].first().unwrap() == TokenType::BASE64 {
2138 return Ok(Some(ASTNode::new(
2139 ASTNodeType::Base64(tokens[0].first().unwrap().token().clone()),
2140 span_from_tokens(&tokens),
2141 vec![],
2142 )));
2143 }
2144
2145 if is_identifier(&tokens[0], "true") {
2147 return Ok(Some(ASTNode::new(
2148 ASTNodeType::Boolean(true),
2149 span_from_tokens(&tokens),
2150 vec![],
2151 )));
2152 }
2153
2154 if is_identifier(&tokens[0], "false") {
2156 return Ok(Some(ASTNode::new(
2157 ASTNodeType::Boolean(false),
2158 span_from_tokens(&tokens),
2159 vec![],
2160 )));
2161 }
2162
2163 if is_identifier(&tokens[0], "null") {
2165 return Ok(Some(ASTNode::new(
2166 ASTNodeType::Null,
2167 span_from_tokens(&tokens),
2168 vec![],
2169 )));
2170 }
2171
2172 if is_identifier(&tokens[0], "undefined") {
2174 return Ok(Some(ASTNode::new(
2175 ASTNodeType::Undefined,
2176 span_from_tokens(&tokens),
2177 vec![],
2178 )));
2179 }
2180
2181 if tokens[0].len() == 1 && tokens[0][0] == TokenType::IDENTIFIER {
2183 return Ok(Some(ASTNode::new(
2184 ASTNodeType::Variable(tokens[0][0].token().clone()),
2185 span_from_tokens(&tokens),
2186 vec![],
2187 )));
2188 }
2189 Ok(None)
2190}