use super::diagnostics::find_line_and_col_from_source;
use crate::parser::lexer::{Token, TokenType};
use colored::*;
use std::{collections::HashSet, fmt::Debug, vec};
use unicode_width::UnicodeWidthStr;
#[derive(Debug, Clone)]
pub enum ParserError {
UnexpectedToken(Token), UnmatchedParenthesis(Token, Token), InvalidSyntax(Token),
NotFullyMatched(Token, Token),
InvalidVariableName(Token),
UnsupportedStructure(Token),
MissingStructure(Token, String), ErrorStructure(Token, String), }
impl ParserError {
pub fn format(&self) -> String {
match self {
Self::UnexpectedToken(token) => Self::format_single_token_report(
"Parse Error",
&format!("Unexpected token '{}'", token.token().yellow()),
token,
"Check the syntax rules for this location.",
),
Self::InvalidSyntax(token) => Self::format_single_token_report(
"Syntax Error",
"The syntax here is invalid.",
token,
"Please correct the statement according to the language grammar.",
),
Self::InvalidVariableName(token) => Self::format_single_token_report(
"Naming Error",
&format!("'{}' is not a valid variable name.", token.token().yellow()),
token,
"Variable names must start with a letter or underscore.",
),
Self::UnsupportedStructure(token) => Self::format_single_token_report(
"Parse Error",
"This language construct is not supported in the current context.",
token,
"Try breaking down complex expressions or using a different structure.",
),
Self::MissingStructure(token, expected) => Self::format_single_token_report(
"Syntax Error",
&format!("Missing expected structure: {}", expected.yellow()),
token,
"An expected element is missing after this token.",
),
Self::ErrorStructure(token, details) => Self::format_single_token_report(
"Syntax Error",
&format!("There is an error in this structure: {}", details.yellow()),
token,
"Please review the structure of this expression.",
),
Self::UnmatchedParenthesis(opening, closing) => {
let opening_report = Self::format_single_token_report(
"Error",
"This opening parenthesis...",
opening,
"",
);
let closing_report = Self::format_single_token_report(
"...is not matched by this closing parenthesis",
"",
closing,
"",
);
format!(
"{}\n\n{}\n\n{}: {}",
"Unmatched Parenthesis".bright_red().bold(),
opening_report,
closing_report,
"Ensure every '(', '[', or '{' has a matching closing one.".bright_green()
)
}
Self::NotFullyMatched(start, end) => {
let title = "Parse Error".bright_red().bold();
let message = "Input was not fully parsed. Unprocessed tokens remain.";
let source_str = start.source_code_str();
let (start_char_idx, _) = start.origin_token_span();
let (end_char_idx, _) = end.origin_token_span();
let (start_line_idx, start_col_char) =
find_line_and_col_from_source(start_char_idx, &source_str);
let (end_line_idx, end_col_char) =
find_line_and_col_from_source(end_char_idx, &source_str);
let lines: Vec<&str> = source_str.lines().collect();
let mut report = String::new();
report.push_str(&format!(
"{}: {}\n --> {}:{}\n",
title,
message,
(start_line_idx + 1).to_string().bright_cyan(),
(start_col_char + 1).to_string().bright_cyan()
));
for i in start_line_idx..=end_line_idx {
let line_text = lines.get(i).unwrap_or(&"");
report.push_str(&format!(
" |\n{:4} | {}\n | ",
(i + 1).to_string().bright_cyan(),
line_text.white()
));
if i == start_line_idx && i == end_line_idx {
let display_offset = line_text
.chars()
.take(start_col_char)
.collect::<String>()
.width();
let underline_width = line_text
.chars()
.skip(start_col_char)
.take(end_col_char - start_col_char)
.collect::<String>()
.width();
report.push_str(&format!(
"{}{}",
" ".repeat(display_offset),
"~".repeat(underline_width.max(1)).bright_red().bold()
));
} else if i == start_line_idx {
let display_offset = line_text
.chars()
.take(start_col_char)
.collect::<String>()
.width();
let underline_width = line_text.width() - display_offset;
report.push_str(&format!(
"{}{}",
" ".repeat(display_offset),
"~".repeat(underline_width.max(1)).bright_red().bold()
));
} else if i == end_line_idx {
let underline_width = line_text
.chars()
.take(end_col_char)
.collect::<String>()
.width();
report.push_str(&format!(
"{}",
"~".repeat(underline_width.max(1)).bright_red().bold()
));
} else {
report.push_str(&format!(
"{}",
"~".repeat(line_text.width()).bright_red().bold()
));
}
report.push('\n');
}
report.push_str(&format!(
"\n{}: {}",
"Help".bright_green(),
"Check for missing semicolons or unclosed blocks in this region."
));
report
}
}
}
fn format_single_token_report(
title: &str,
message: &str,
token: &Token,
help_text: &str,
) -> String {
let source_str = token.source_code_str();
let (char_index, _) = token.origin_token_span();
let (line_idx, col_char) = find_line_and_col_from_source(char_index, &source_str);
let lines: Vec<&str> = source_str.lines().collect();
let line_text = lines.get(line_idx).unwrap_or(&"");
let display_offset = line_text.chars().take(col_char).collect::<String>().width();
let underline_display_width = token.origin_token().width();
let main_report = format!(
"{}: {}\n --> {}:{}\n |\n{:4} | {}\n | {}{}",
title.bright_red().bold(),
message,
(line_idx + 1).to_string().bright_cyan(),
(col_char + 1).to_string().bright_cyan(), (line_idx + 1).to_string().bright_cyan(),
line_text.white(),
" ".repeat(display_offset), "^".repeat(underline_display_width.max(1))
.bright_red()
.bold() );
if help_text.is_empty() {
main_report
} else {
format!(
"{}\n\n{}: {}",
main_report,
"Help".bright_green(),
help_text
)
}
}
}
pub type TokenStream = Vec<Token>;
pub type GatheredTokens<'t> = &'t [Token];
pub mod ast_token_stream {
pub fn from_stream<'t>(stream: &'t super::TokenStream) -> super::GatheredTokens<'t> {
stream.as_slice()
}
}
fn get_next_tokens(
tokens: GatheredTokens<'_>,
current: usize,
) -> Result<GatheredTokens<'_>, ParserError> {
let mut stack = Vec::<(Token, usize)>::new();
let mut next_tokens_end = 0usize;
let mut index = current;
if index >= (*tokens).len() {
return Ok(&[]);
}
loop {
if ["{", "[", "("].contains(&tokens[index].token().as_str())
&& tokens[index] == TokenType::SYMBOL
{
stack.push((tokens[index].clone(), index));
next_tokens_end += 1;
} else if ["}", "]", ")"].contains(&tokens[index].token().as_str())
&& tokens[index] == TokenType::SYMBOL
{
if stack.is_empty() {
break;
}
let (last, last_position) = stack.pop().unwrap();
if (last == "{" && tokens[index] != "}")
|| (last == "[" && tokens[index] != "]")
|| (last == "(" && tokens[index] != ")")
{
return Err(ParserError::UnmatchedParenthesis(
tokens[last_position].clone(),
tokens[index].clone(),
));
}
next_tokens_end += 1;
} else {
next_tokens_end += 1;
}
index += 1;
if index >= (tokens).len() || stack.is_empty() {
break;
}
}
if !stack.is_empty() {
let (_, last_position) = stack.pop().unwrap();
return Err(ParserError::UnmatchedParenthesis(
tokens[last_position].clone(),
tokens[index - 1].clone(),
));
}
Ok(&tokens[current..current + next_tokens_end])
}
fn gather(tokens: GatheredTokens<'_>) -> Result<Vec<GatheredTokens<'_>>, ParserError> {
let mut current = 0;
let mut result = Vec::<GatheredTokens>::new();
while current < tokens.len() {
let next_tokens = get_next_tokens(tokens, current)?;
if next_tokens.is_empty() {
return Err(ParserError::UnsupportedStructure(tokens[current].clone()));
}
current += next_tokens.len();
result.push(next_tokens);
}
Ok(result)
}
#[derive(Debug, PartialEq, Clone)]
pub enum ASTNodeType {
Null, Undefined,
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), Set, Map, Is, Raise,
Dynamic, Static,
Comptime, }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ASTNodeOperation {
Add, Subtract, Multiply, Divide, Modulus, Power, And, Xor, Or, Not, Equal, NotEqual, Greater, Less, GreaterEqual, LessEqual, LeftShift, RightShift, Abs, Minus, }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ASTNodeModifier {
Mut, Const, KeyOf, ValueOf, Assert, Import, TypeOf, Await, LengthOf, Launch, Spawn, Async,
Sync,
Atomic,
}
#[derive(Debug, Clone)]
pub struct ASTNode {
pub node_type: ASTNodeType, pub start_token: Option<Token>, pub end_token: Option<Token>, pub children: Vec<ASTNode>, }
impl PartialEq for ASTNode {
fn eq(&self, other: &Self) -> bool {
self.node_type == other.node_type && self.children == other.children
}
}
impl ASTNode {
pub fn new(
node_type: ASTNodeType,
start_token: Option<Token>,
end_token: Option<Token>,
children: Option<Vec<ASTNode>>,
) -> ASTNode {
ASTNode {
node_type,
start_token,
end_token,
children: children.unwrap_or_default(),
}
}
pub fn undefined() -> ASTNode {
ASTNode::new(ASTNodeType::Undefined, None, None, None)
}
pub fn _formatted_print(&self, indent: usize) {
let indent_str = " ".repeat(indent);
let output = match &self.node_type {
node_type @ (ASTNodeType::Variable(v)
| ASTNodeType::Number(v)
| ASTNodeType::String(v)) => {
format!("{}{:?}: {:?}", indent_str, node_type, v)
}
node_type @ ASTNodeType::Boolean(v) => {
format!("{}{:?}: {:?}", indent_str, node_type, v)
}
node_type => format!("{}{:?}", indent_str, node_type),
};
println!("{}", output);
if !self.children.is_empty() {
for child in &self.children {
child._formatted_print(indent + 2);
}
}
}
}
type MatcherFn = fn(&Vec<GatheredTokens>, usize) -> Result<(Option<ASTNode>, usize), ParserError>;
struct NodeMatcher {
matchers: Vec<MatcherFn>,
}
impl NodeMatcher {
fn new() -> NodeMatcher {
NodeMatcher {
matchers: Vec::new(),
}
}
fn add_matcher(
&mut self,
matcher: fn(&Vec<GatheredTokens>, usize) -> Result<(Option<ASTNode>, usize), ParserError>,
) {
self.matchers.push(matcher);
}
#[stacksafe::stacksafe]
fn match_node(
&self,
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if tokens.is_empty() {
return Ok((
Some(ASTNode::new(ASTNodeType::Tuple, None, None, Some(vec![]))),
0,
));
}
let mut offset = 0;
let mut matched_nodes = Vec::<ASTNode>::new();
let mut current_pos = current;
while current_pos < tokens.len() {
let remaining_tokens = &tokens[current_pos..].to_vec();
let (node, next_offset) = self.match_longest_possible(&remaining_tokens, 0)?;
if node.is_none() {
break;
}
matched_nodes.push(node.unwrap());
offset += next_offset;
current_pos += next_offset;
}
if matched_nodes.is_empty() {
return Ok((None, 0));
}
if matched_nodes.len() == 1 {
return Ok((Some(matched_nodes.remove(0)), offset));
}
Ok((
Some(ASTNode::new(
ASTNodeType::Expressions,
tokens[current].first().cloned(),
tokens[current + offset - 1].last().cloned(),
Some(matched_nodes),
)),
offset,
))
}
#[allow(dead_code)]
#[deprecated]
fn try_match_node(
&self,
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if tokens.is_empty() {
return Ok((
Some(ASTNode::new(ASTNodeType::Tuple, None, None, Some(vec![]))),
0,
));
}
if current >= tokens.len() {
return Ok((None, 0));
}
let mut low = 0; let mut high = 2 * (tokens.len() - current - 1); let mut best_match: Option<(ASTNode, usize)> = None;
while low <= high {
let mid = low + (high - low) / 2;
let test_tokens = &tokens[current..current + mid + 1].to_vec();
let mut current_match: Option<(ASTNode, usize)> = None;
for matcher in &self.matchers {
match matcher(test_tokens, 0) {
Ok((Some(node), offset)) => {
if offset == test_tokens.len() {
current_match = Some((node, offset));
break;
}
}
_ => continue,
}
}
if let Some((node, offset)) = current_match {
best_match = Some((node, offset));
if low >= mid {
break;
}
if mid >= tokens.len() - 1 {
break;
}
low = mid;
} else {
if low >= mid {
break;
}
high = mid;
}
}
match best_match {
Some((node, offset)) => Ok((Some(node), offset)),
None => Ok((None, 0)),
}
}
pub fn match_longest_possible(
&self,
tokens: &Vec<GatheredTokens>, current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
let mut best_match: Option<(ASTNode, usize)> = None;
let remaining_tokens = &tokens[current..].to_vec();
for matcher in &self.matchers {
match matcher(remaining_tokens, 0) {
Ok((Some(node), consumed_count)) => {
best_match = Some((node, consumed_count));
break;
}
Ok((None, _)) => {
continue;
}
Err(e) => {
return Err(e);
}
}
}
match best_match {
Some((node, consumed)) => Ok((Some(node), consumed)),
None => Ok((None, 0)),
}
}
}
fn is_symbol(token: &GatheredTokens, symbol: &str) -> bool {
if token.len() != 1 {
return false;
}
let token = &token[0];
token == TokenType::SYMBOL && token == symbol
}
fn is_any_symbol(token: &GatheredTokens) -> bool {
if token.len() != 1 {
return false;
}
let token = &token[0];
token == TokenType::SYMBOL
}
fn is_identifier(token: &GatheredTokens, identifier: &str) -> bool {
if token.len() != 1 {
return false;
}
let token = &token[0];
token == TokenType::IDENTIFIER && token == identifier
}
fn unwrap_brace<'t>(token: &GatheredTokens<'t>) -> Result<GatheredTokens<'t>, ParserError> {
if token.len() < 2 {
return Err(ParserError::UnexpectedToken(token[0].clone()));
}
if token[0] == TokenType::SYMBOL
&& token[0] == "{"
&& token.last().unwrap() == TokenType::SYMBOL
&& token.last().unwrap() == "}"
{
return Ok(&token[1..token.len() - 1]);
}
if token[0] == TokenType::SYMBOL
&& token[0] == "["
&& token.last().unwrap() == TokenType::SYMBOL
&& token.last().unwrap() == "]"
{
return Ok(&token[1..token.len() - 1]);
}
if token[0] == TokenType::SYMBOL
&& token[0] == "("
&& token.last().unwrap() == TokenType::SYMBOL
&& token.last().unwrap() == ")"
{
return Ok(&token[1..token.len() - 1]);
}
Err(ParserError::UnexpectedToken(token[0].clone()))
}
fn is_bracket(token: &GatheredTokens) -> bool {
if token.len() < 2 {
return false;
}
token[0] == TokenType::SYMBOL
&& token[0] == "("
&& token.last().unwrap() == TokenType::SYMBOL
&& token.last().unwrap() == ")"
}
fn is_brace(token: &GatheredTokens) -> bool {
if token.len() < 2 {
return false;
}
token[0] == TokenType::SYMBOL
&& token[0] == "{"
&& token.last().unwrap() == TokenType::SYMBOL
&& token.last().unwrap() == "}"
}
fn is_square_bracket(token: &GatheredTokens) -> bool {
if token.len() < 2 {
return false;
}
token[0] == TokenType::SYMBOL
&& token[0] == "["
&& token.last().unwrap() == TokenType::SYMBOL
&& token.last().unwrap() == "]"
}
pub fn build_ast(tokens: GatheredTokens<'_>) -> Result<ASTNode, ParserError> {
let gathered = gather(tokens)?;
let (matched, offset) = match_all(&gathered, 0)?;
if matched.is_none() {
return Ok(ASTNode::new(ASTNodeType::Tuple, None, None, Some(vec![])));
}
let matched = matched.unwrap();
if offset != gathered.len() {
return Err(ParserError::NotFullyMatched(
gathered.first().unwrap().first().unwrap().clone(),
gathered.last().unwrap().last().unwrap().clone(),
));
}
Ok(matched)
}
fn match_all<'t>(
tokens: &Vec<GatheredTokens<'t>>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut node_matcher = NodeMatcher::new();
node_matcher.add_matcher(match_expressions);
node_matcher.add_matcher(match_dynamic_and_static);
node_matcher.add_matcher(match_return_emit_raise);
node_matcher.add_matcher(match_tuple);
node_matcher.add_matcher(match_comptime);
node_matcher.add_matcher(match_let);
node_matcher.add_matcher(match_assign);
node_matcher.add_matcher(match_map);
node_matcher.add_matcher(match_set_def);
node_matcher.add_matcher(match_quick_call);
node_matcher.add_matcher(match_lambda_def);
node_matcher.add_matcher(match_named_to);
node_matcher.add_matcher(match_pair);
node_matcher.add_matcher(match_while);
node_matcher.add_matcher(match_break_and_continue);
node_matcher.add_matcher(match_if);
node_matcher.add_matcher(match_or);
node_matcher.add_matcher(match_and);
node_matcher.add_matcher(match_xor);
node_matcher.add_matcher(match_not);
node_matcher.add_matcher(match_operation_compare);
node_matcher.add_matcher(match_operation_add_sub);
node_matcher.add_matcher(match_operation_mul_div_mod);
node_matcher.add_matcher(match_bitwise_shift);
node_matcher.add_matcher(match_unary);
node_matcher.add_matcher(match_power);
node_matcher.add_matcher(match_range);
node_matcher.add_matcher(match_in);
node_matcher.add_matcher(match_is);
node_matcher.add_matcher(match_as);
node_matcher.add_matcher(match_modifier);
node_matcher.add_matcher(match_quick_named_to);
node_matcher.add_matcher(match_assume_tuple);
node_matcher.add_matcher(match_alias);
node_matcher.add_matcher(match_member_access_and_apply);
node_matcher.add_matcher(match_variable);
node_matcher.match_node(tokens, current)
}
fn match_expressions(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut offset = 0usize;
let mut left_tokens = Vec::<GatheredTokens>::new();
let mut last_offset = 0usize;
let mut separated = Vec::<ASTNode>::new();
while current + offset < tokens.len() {
if is_symbol(&tokens[current + offset], ";") {
let (node, node_offset) = match_all(&left_tokens, 0)?;
if node.is_none() {
return Ok((None, 0));
}
if node_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
separated.push(node.unwrap());
left_tokens.clear();
offset += 1;
last_offset = offset;
} else {
left_tokens.push(tokens[current + offset]);
offset += 1;
}
}
if separated.is_empty() {
return Ok((None, 0));
}
let (node, node_offset) = match_all(&left_tokens, 0)?;
if node.is_none() {
return Ok((None, 0));
}
separated.push(node.unwrap());
Ok((
Some(ASTNode::new(
ASTNodeType::Expressions,
tokens[current].first().cloned(),
tokens[current + last_offset + node_offset - 1]
.last()
.cloned(),
Some(separated),
)),
last_offset + node_offset,
))
}
fn match_comptime(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
if !is_symbol(&tokens[current], "@") {
return Ok((None, 0));
}
let right_tokens = tokens[current + 1..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
let node = ASTNode::new(
ASTNodeType::Comptime,
tokens[current].first().cloned(),
tokens[current + right_offset].last().cloned(),
Some(vec![right]),
);
Ok((Some(node), right_offset + 1))
}
fn match_dynamic_and_static(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
if !is_symbol(&tokens[current], "dynamic") && !is_identifier(&tokens[current], "static") {
return Ok((None, 0));
}
let right_tokens = tokens[current + 1..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
let node = ASTNode::new(
if is_identifier(&tokens[current], "dynamic") {
ASTNodeType::Dynamic
} else {
ASTNodeType::Static
},
tokens[current].first().cloned(),
tokens[current + right_offset + 1].last().cloned(),
Some(vec![right]),
);
Ok((Some(node), right_offset + 1))
}
fn match_return_emit_raise(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
if !is_identifier(&tokens[current], "return") && !is_identifier(&tokens[current], "raise") {
return Ok((None, 0));
}
let right_tokens = tokens[current + 1..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
let node_type = match tokens[current].first().unwrap().token().as_str() {
"return" => ASTNodeType::Return,
"raise" => ASTNodeType::Raise,
_ => unreachable!(),
};
Ok((
Some(ASTNode::new(
node_type,
tokens[current].first().cloned(),
tokens[current + right_offset].last().cloned(),
Some(vec![right]),
)),
right_offset + 1,
))
}
fn match_tuple(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut offset = 0usize;
let mut left_tokens = Vec::<GatheredTokens>::new();
let mut last_offset = 0usize;
let mut separated = Vec::<ASTNode>::new();
while current + offset < tokens.len() {
if is_symbol(&tokens[current + offset], ",") {
if !left_tokens.is_empty() {
let (node, node_offset) = match_all(&left_tokens, 0)?;
if node.is_none() {
return Ok((None, 0));
}
if node_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
separated.push(node.unwrap());
left_tokens.clear();
}
offset += 1;
last_offset = offset;
} else {
left_tokens.push(tokens[current + offset]);
offset += 1;
}
}
if separated.is_empty() {
return Ok((None, 0));
}
if !left_tokens.is_empty() {
let (node, node_offset) = match_all(&left_tokens, 0)?;
if node.is_none() {
return Ok((None, 0));
}
separated.push(node.unwrap());
last_offset += node_offset;
}
Ok((
Some(ASTNode::new(
ASTNodeType::Tuple,
tokens[current].first().cloned(),
tokens[current + last_offset - 1].last().cloned(),
Some(separated),
)),
last_offset,
))
}
fn match_let(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_symbol(&tokens[current + 1], ":=") {
return Ok((None, 0));
}
let left_tokens = gather(tokens[current])?;
let right_tokens = tokens[current + 2..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
let (left, left_offset) = match_all(&left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let left = left.unwrap();
match left.node_type {
ASTNodeType::Variable(name) => Ok((
Some(ASTNode::new(
ASTNodeType::Let(name),
tokens[current].first().cloned(),
tokens[current + right_offset + 1].last().cloned(),
Some(vec![right]),
)),
right_offset + 2,
)),
ASTNodeType::String(name) => Ok((
Some(ASTNode::new(
ASTNodeType::Let(name),
tokens[current].first().cloned(),
tokens[current + right_offset + 1].last().cloned(),
Some(vec![right]),
)),
right_offset + 2,
)),
_ => Err(ParserError::InvalidVariableName(
tokens[current].first().unwrap().clone(),
)),
}
}
fn match_assign(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
let mut offset = 0;
let mut left_tokens = Vec::new();
while current + offset < tokens.len() {
if tokens[current + offset].len() == 1
&& tokens[current + offset][0] == TokenType::SYMBOL
&& tokens[current + offset][0] == "="
{
break;
}
left_tokens.push(tokens[current + offset]);
offset += 1;
}
if current + offset >= tokens.len() || !is_symbol(&tokens[current + offset], "=") {
return Ok((None, 0));
}
let (left, left_offset) = match_all(&left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let left = left.unwrap();
if current + offset + 1 >= tokens.len() {
return Ok((None, 0));
}
let right_tokens = tokens[current + offset + 1..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
return Ok((
Some(ASTNode::new(
ASTNodeType::Assign,
tokens[current].first().cloned(),
tokens[current + offset + right_offset].last().cloned(),
Some(vec![left, right]),
)),
offset + right_offset + 1, ));
}
fn match_named_to(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_symbol(&tokens[current + 1], "=>") {
return Ok((None, 0));
}
let left_tokens = gather(tokens[current])?;
let (left, left_offset) = match_all(&left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let mut left = left.unwrap();
if let ASTNodeType::Variable(name) = left.node_type {
left = ASTNode::new(
ASTNodeType::String(name),
left.start_token.clone(),
left.start_token.clone(),
Some(left.children),
);
}
let right_tokens = tokens[current + 2..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
Ok((
Some(ASTNode::new(
ASTNodeType::Pair,
tokens[current].first().cloned(),
tokens[current + right_offset + 1].last().cloned(),
Some(vec![left, right]),
)),
right_offset + 2,
))
}
fn match_pair(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_symbol(&tokens[current + 1], ":") {
return Ok((None, 0));
}
let left_tokens = gather(tokens[current])?;
let (left, left_offset) = match_all(&left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let left = left.unwrap();
let right_tokens = tokens[current + 2..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().cloned().unwrap(),
right_tokens.last().unwrap().last().cloned().unwrap(),
));
}
let right = right.unwrap();
Ok((
Some(ASTNode::new(
ASTNodeType::Pair,
tokens[current].first().cloned(),
tokens[current + right_offset + 1].last().cloned(),
Some(vec![left, right]),
)),
right_offset + 2,
))
}
fn match_while(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_identifier(&tokens[current], "while") {
return Ok((None, 0));
}
let condition_tokens = gather(tokens[current + 1])?;
let (condition, condition_offset) = match_all(&condition_tokens, 0)?;
if condition.is_none() {
return Ok((None, 0));
}
if condition_offset != condition_tokens.len() {
return Err(ParserError::NotFullyMatched(
condition_tokens.first().unwrap().first().unwrap().clone(),
condition_tokens.last().unwrap().last().unwrap().clone(),
));
}
let condition = condition.unwrap();
let body_tokens = tokens[current + 2..].to_vec();
let (body, body_offset) = match_all(&body_tokens, 0)?;
if body.is_none() {
return Ok((None, 0));
}
if body_offset != body_tokens.len() {
return Err(ParserError::NotFullyMatched(
body_tokens.first().unwrap().first().unwrap().clone(),
body_tokens.last().unwrap().last().unwrap().clone(),
));
}
let body = body.unwrap();
Ok((
Some(ASTNode::new(
ASTNodeType::While,
tokens[current].first().cloned(),
tokens[current + body_offset + 1].last().cloned(),
Some(vec![condition, body]),
)),
body_offset + 2,
))
}
fn match_if(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_identifier(&tokens[current], "if") {
return Ok((None, 0));
}
let condition_tokens = gather(tokens[current + 1])?;
let true_condition_tokens = gather(tokens[current + 2])?;
let (condition, condition_offset) = match_all(&condition_tokens, 0)?;
if condition.is_none() {
return Ok((None, 0));
}
if condition_offset != condition_tokens.len() {
return Err(ParserError::NotFullyMatched(
condition_tokens.first().unwrap().first().unwrap().clone(),
condition_tokens.last().unwrap().last().unwrap().clone(),
));
}
let condition = condition.unwrap();
let (true_condition, true_condition_offset) = match_all(&true_condition_tokens, 0)?;
if true_condition.is_none() {
return Ok((None, 0));
}
if true_condition_offset != true_condition_tokens.len() {
return Err(ParserError::NotFullyMatched(
true_condition_tokens
.first()
.unwrap()
.first()
.unwrap()
.clone(),
true_condition_tokens
.last()
.unwrap()
.last()
.unwrap()
.clone(),
));
}
let true_condition = true_condition.unwrap();
if current + 3 < tokens.len() && is_identifier(&tokens[current + 3], "else") {
let false_condition_tokens = tokens[current + 4..].to_vec();
let (false_condition, false_condition_offset) = match_all(&false_condition_tokens, 0)?;
if false_condition.is_none() {
return Ok((None, 0));
}
if false_condition_offset != false_condition_tokens.len() {
return Err(ParserError::NotFullyMatched(
false_condition_tokens
.first()
.unwrap()
.first()
.unwrap()
.clone(),
false_condition_tokens
.last()
.unwrap()
.last()
.unwrap()
.clone(),
));
}
let false_condition = false_condition.unwrap();
return Ok((
Some(ASTNode::new(
ASTNodeType::If,
tokens[current].first().cloned(),
tokens[current + false_condition_offset + 3].last().cloned(),
Some(vec![condition, true_condition, false_condition]),
)),
false_condition_offset + 4,
));
}
Ok((
Some(ASTNode::new(
ASTNodeType::If,
tokens[current].first().cloned(),
tokens[current + true_condition_offset + 1].last().cloned(),
Some(vec![condition, true_condition]),
)),
true_condition_offset + 2,
))
}
fn match_break_and_continue(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
if is_identifier(&tokens[current], "break") {
let right_tokens = tokens[current + 1..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
return Ok((
Some(ASTNode::new(
ASTNodeType::Break,
tokens[current].first().cloned(),
tokens[current + right_offset].last().cloned(),
Some(vec![right]),
)),
right_offset + 1,
));
} else if is_identifier(&tokens[current], "continue") {
let right_tokens = tokens[current + 1..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
return Ok((
Some(ASTNode::new(
ASTNodeType::Continue,
tokens[current].first().cloned(),
tokens[current + right_offset].last().cloned(),
Some(vec![right]),
)),
right_offset + 1,
));
}
Ok((None, 0))
}
fn match_or(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut offset: usize = tokens.len() - current - 1;
let mut operator = Option::<&str>::None;
let mut operator_pos: usize = 0;
while offset > 0 {
let pos = current + offset;
if is_identifier(&tokens[pos], "or") {
operator = Some("or");
operator_pos = pos;
break;
}
offset -= 1;
}
if operator.is_none() {
return Ok((None, 0));
}
let left_tokens = &tokens[current..operator_pos].to_vec();
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(ASTNodeOperation::Or),
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_and(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut offset: usize = tokens.len() - current - 1;
let mut operator = Option::<&str>::None;
let mut operator_pos: usize = 0;
while offset > 0 {
let pos = current + offset;
if is_identifier(&tokens[pos], "and") {
operator = Some("and");
operator_pos = pos;
break;
}
offset -= 1;
}
if operator.is_none() {
return Ok((None, 0));
}
let left_tokens = &tokens[current..operator_pos].to_vec();
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(ASTNodeOperation::And),
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_xor(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut offset: usize = tokens.len() - current - 1;
let mut operator = Option::<&str>::None;
let mut operator_pos: usize = 0;
while offset > 0 {
let pos = current + offset;
if is_identifier(&tokens[pos], "xor") {
operator = Some("xor");
operator_pos = pos;
break;
}
offset -= 1;
}
if operator.is_none() {
return Ok((None, 0));
}
let left_tokens = &tokens[current..operator_pos].to_vec();
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(ASTNodeOperation::Xor),
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_not(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
if is_identifier(&tokens[current], "not") {
if current + 1 >= tokens.len() {
return Ok((None, 0));
};
let not_expr = tokens[current + 1..].to_vec();
let (node, node_offset) = match_all(¬_expr, 0)?;
if node.is_none() {
return Ok((None, 0));
}
if node_offset != not_expr.len() {
return Err(ParserError::NotFullyMatched(
not_expr.first().unwrap().first().unwrap().clone(),
not_expr.last().unwrap().last().unwrap().clone(),
));
}
let node = node.unwrap();
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(ASTNodeOperation::Not),
tokens[current].first().cloned(),
tokens[current + node_offset].last().cloned(),
Some(vec![node]),
)),
node_offset + 1,
));
}
Ok((None, 0))
}
fn match_operation_compare(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut offset: usize = tokens.len() - current - 1;
let mut operator = None;
let mut operator_pos: usize = 0;
while offset > 0 {
let pos = current + offset;
if is_symbol(&tokens[pos], ">")
|| is_symbol(&tokens[pos], "<")
|| is_symbol(&tokens[pos], ">=")
|| is_symbol(&tokens[pos], "<=")
|| is_symbol(&tokens[pos], "==")
|| is_symbol(&tokens[pos], "!=")
{
operator = Some(tokens[pos][0].token());
operator_pos = pos;
break;
}
offset -= 1;
}
if operator.is_none() {
return Ok((None, 0));
}
let left_tokens = &tokens[current..operator_pos].to_vec();
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let operation = match operator.unwrap().as_str() {
">" => ASTNodeOperation::Greater,
"<" => ASTNodeOperation::Less,
">=" => ASTNodeOperation::GreaterEqual,
"<=" => ASTNodeOperation::LessEqual,
"==" => ASTNodeOperation::Equal,
"!=" => ASTNodeOperation::NotEqual,
_ => unreachable!(),
};
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(operation),
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_operation_add_sub(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut offset: usize = tokens.len().saturating_sub(current).saturating_sub(1);
let mut operator = None;
let mut operator_pos: usize = 0;
while offset > 0 {
let pos: usize = current + offset;
if is_symbol(&tokens[pos], "+") || is_symbol(&tokens[pos], "-") {
let op_token = tokens[pos][0].token();
let is_unary = if pos == current {
true } else {
let prev_pos = pos - 1;
is_any_symbol(&tokens[prev_pos])
};
if is_unary && pos > current {
offset -= 1;
continue;
}
operator = Some(op_token);
operator_pos = pos;
break;
}
offset -= 1;
}
if operator.is_none() {
return Ok((None, 0)); }
let op = operator.unwrap();
let left_tokens = &tokens[current..operator_pos].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let operation = if op == "+" {
ASTNodeOperation::Add
} else {
ASTNodeOperation::Subtract
};
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(operation),
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_operation_mul_div_mod(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut offset: usize = tokens.len().saturating_sub(current).saturating_sub(1);
let mut operator = None;
let mut operator_pos: usize = 0;
while offset > 0 {
let pos = current + offset;
if is_symbol(&tokens[pos], "*")
|| is_symbol(&tokens[pos], "/")
|| is_symbol(&tokens[pos], "%")
{
operator = Some(tokens[pos][0].token());
operator_pos = pos;
break;
}
offset -= 1;
}
if operator.is_none() {
return Ok((None, 0)); }
let left_tokens = &tokens[current..operator_pos].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let operation = match operator.unwrap().as_str() {
"*" => ASTNodeOperation::Multiply,
"/" => ASTNodeOperation::Divide,
"%" => ASTNodeOperation::Modulus,
_ => unreachable!(),
};
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(operation),
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_bitwise_shift(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
let mut offset: usize = tokens.len() - current - 1;
let mut operator = None;
let mut operator_pos: usize = 0;
while offset > 0 {
let pos = current + offset;
if is_symbol(&tokens[pos], "<<") || is_symbol(&tokens[pos], ">>") {
operator = Some(tokens[pos][0].token());
operator_pos = pos;
break;
}
offset -= 1;
}
if operator.is_none() {
return Ok((None, 0));
}
let left_tokens = &tokens[current..operator_pos].to_vec();
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(if operator.unwrap() == "<<" {
ASTNodeOperation::LeftShift
} else {
ASTNodeOperation::RightShift
}),
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_unary(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
if is_symbol(&tokens[current], "-") || is_symbol(&tokens[current], "+") {
if current + 1 >= tokens.len() {
return Ok((None, 0));
};
let unary_expr = tokens[current + 1..].to_vec();
let (node, node_offset) = match_all(&unary_expr, 0)?;
if node.is_none() {
return Ok((None, 0));
}
if node_offset != unary_expr.len() {
return Err(ParserError::NotFullyMatched(
unary_expr.first().unwrap().first().unwrap().clone(),
unary_expr.last().unwrap().last().unwrap().clone(),
));
}
let node = node.unwrap();
let operation = match tokens[current].first().unwrap().token().as_str() {
"-" => ASTNodeOperation::Minus,
"+" => ASTNodeOperation::Abs,
_ => unreachable!(),
};
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(operation),
tokens[current].first().cloned(),
tokens[current + node_offset].last().cloned(),
Some(vec![node]),
)),
node_offset + 1,
));
}
Ok((None, 0))
}
fn match_power(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
let find = tokens[current..]
.iter()
.position(|token| is_symbol(token, "**"));
if find.is_none() {
return Ok((None, 0));
}
let operator_pos = find.unwrap() + current;
if operator_pos + 1 >= tokens.len() {
return Ok((None, 0));
}
let left_tokens = &tokens[current..operator_pos].to_vec();
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
return Ok((
Some(ASTNode::new(
ASTNodeType::Operation(ASTNodeOperation::Power),
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_map(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
let mut offset: usize = tokens.len() - current - 1;
let mut operator_pos: usize = 0;
let mut found = false;
while offset > 0 {
let pos = current + offset;
if is_symbol(&tokens[pos], "|>") {
operator_pos = pos;
found = true;
break;
}
offset -= 1;
}
if !found {
return Ok((None, 0));
}
let left_tokens = &tokens[current..operator_pos].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
return Ok((
Some(ASTNode::new(
ASTNodeType::Map,
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_set_def(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
let mut offset: usize = tokens.len() - current - 1;
let mut operator_pos: usize = 0;
let mut found = false;
while offset > 0 {
let pos = current + offset;
if is_symbol(&tokens[pos], "|") {
operator_pos = pos;
found = true;
break;
}
offset -= 1;
}
if !found {
return Ok((None, 0));
}
let left_tokens = &tokens[current..operator_pos].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
return Ok((
Some(ASTNode::new(
ASTNodeType::Set,
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left, right]),
)),
tokens.len() - current, ));
}
fn match_lambda_def(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_symbol(&tokens[current + 1], "->") {
return Ok((None, 0));
}
let left_tokens = gather(tokens[current])?;
let (left, left_offset) = match_all(&left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let mut body_start_index = current + 2; let mut capture_vars = HashSet::new();
if is_symbol(&tokens[body_start_index], "&") {
body_start_index += 1; if body_start_index >= tokens.len() {
return Err(ParserError::MissingStructure(
tokens.last().unwrap().last().unwrap().clone(), "Lambda capture".to_string(),
));
}
let capture = gather(tokens[body_start_index])?;
let (capture_node, capture_offset) = match_all(&capture, 0)?;
if capture_node.is_none() {
return Err(ParserError::MissingStructure(
tokens[body_start_index].first().unwrap().clone(), "Lambda capture".to_string(),
));
}
if capture_offset != capture.len() {
return Err(ParserError::NotFullyMatched(
capture.first().unwrap().first().unwrap().clone(),
capture.last().unwrap().last().unwrap().clone(),
));
}
let capture = capture_node.unwrap();
match capture.node_type {
ASTNodeType::String(v) | ASTNodeType::Variable(v) => {
capture_vars.insert(v);
}
ASTNodeType::Tuple => {
for child in &capture.children {
if let ASTNodeType::String(v) | ASTNodeType::Variable(v) = &child.node_type {
capture_vars.insert(v.clone());
} else {
return Err(ParserError::ErrorStructure(
tokens[body_start_index].first().unwrap().clone(),
"Capture must be a variable or tuple of variables".to_string(),
));
}
}
}
_ => {
return Err(ParserError::ErrorStructure(
tokens[body_start_index].first().unwrap().clone(),
"Capture must be a variable or tuple of variables".to_string(),
));
}
}
body_start_index += 1;
}
let is_dyn = body_start_index < tokens.len() && is_identifier(&tokens[body_start_index], "dyn");
if is_dyn {
body_start_index += 1;
}
if body_start_index >= tokens.len() {
return Err(ParserError::MissingStructure(
tokens.last().unwrap().last().unwrap().clone(), "Lambda body".to_string(),
));
}
let body_tokens = &tokens[body_start_index..].to_vec();
let (right, right_offset) = match_all(body_tokens, 0)?;
if right.is_none() {
return Err(ParserError::MissingStructure(
tokens[body_start_index - 1].last().unwrap().clone(), "Lambda body expression".to_string(),
));
}
if right_offset != body_tokens.len() {
return Err(ParserError::NotFullyMatched(
body_tokens.first().unwrap().first().unwrap().clone(),
body_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
let total_offset = body_start_index - current + right_offset;
Ok((
Some(ASTNode::new(
ASTNodeType::LambdaDef(is_dyn, capture_vars),
tokens[current].first().cloned(), tokens[current + total_offset - 1].last().cloned(), Some(vec![left, right]),
)),
total_offset, ))
}
fn match_quick_call(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 1 >= tokens.len() {
return Ok((None, 0));
}
if is_symbol(&tokens[current], "#") {
let left_tokens = gather(tokens[current + 1])?;
let (left, left_offset) = match_all(&left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = tokens.get(current + 2..).unwrap_or(&[]).to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
return Ok((
Some(ASTNode::new(
ASTNodeType::Apply,
tokens[current].first().cloned(),
tokens[current + right_offset + 1].last().cloned(),
Some(vec![left, right]),
)),
right_offset + 2,
));
}
Ok((None, 0))
}
fn match_modifier(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 1 >= tokens.len() {
return Ok((None, 0));
}
if tokens[current].len() == 1
&& vec![
"mut", "const", "keyof", "valueof", "assert", "import", "typeof", "await", "lengthof",
"launch", "spawn", "async", "sync", "atomic",
]
.contains(&tokens[current].first().unwrap().token().as_str())
{
let modify_expr = tokens[current + 1..].to_vec();
let (node, node_offset) = match_all(&modify_expr, 0)?;
if node.is_none() {
return Ok((None, 0));
}
if node_offset != modify_expr.len() {
return Err(ParserError::NotFullyMatched(
modify_expr.first().unwrap().first().unwrap().clone(),
modify_expr.last().unwrap().last().unwrap().clone(),
));
}
let node = node.unwrap();
let modifier = match tokens[current].first().unwrap().token().as_str() {
"mut" => ASTNodeModifier::Mut,
"const" => ASTNodeModifier::Const,
"keyof" => ASTNodeModifier::KeyOf,
"valueof" => ASTNodeModifier::ValueOf,
"assert" => ASTNodeModifier::Assert,
"import" => ASTNodeModifier::Import,
"typeof" => ASTNodeModifier::TypeOf,
"await" => ASTNodeModifier::Await,
"lengthof" => ASTNodeModifier::LengthOf,
"launch" => ASTNodeModifier::Launch,
"spawn" => ASTNodeModifier::Spawn,
"async" => ASTNodeModifier::Async,
"sync" => ASTNodeModifier::Sync,
"atomic" => ASTNodeModifier::Atomic,
_ => return Ok((None, 0)),
};
return Ok((
Some(ASTNode::new(
ASTNodeType::Modifier(modifier),
tokens[current].first().cloned(),
tokens[current + node_offset].last().cloned(),
Some(vec![node]),
)),
node_offset + 1,
));
}
Ok((None, 0))
}
fn match_quick_named_to(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 1 >= tokens.len() {
return Ok((None, 0));
}
if is_symbol(&tokens[tokens.len() - 1], "?") {
let left_tokens = tokens[..tokens.len() - 1].to_vec();
let (node, node_offset) = match_all(&left_tokens, 0)?;
if node.is_none() {
return Ok((None, 0));
}
if node_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let mut node = node.unwrap();
if let ASTNodeType::Variable(name) = node.node_type {
node = ASTNode::new(
ASTNodeType::String(name),
node.start_token,
node.end_token,
Some(node.children),
);
}
return Ok((
Some(ASTNode::new(
ASTNodeType::Pair,
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![
node,
ASTNode::new(ASTNodeType::Boolean(true), None, None, None),
]),
)),
node_offset + 1,
));
}
Ok((None, 0))
}
fn match_assume_tuple(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 1 >= tokens.len() {
return Ok((None, 0));
}
if !is_symbol(&tokens[current], "...") {
return Ok((None, 0));
}
let left_tokens = &tokens[current + 1..].to_vec();
let (node, node_offset) = match_all(left_tokens, 0)?;
if node.is_none() {
return Ok((None, 0));
}
let node = node.unwrap();
if node_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
Ok((
Some(ASTNode::new(
ASTNodeType::AssumeTuple,
tokens[current].first().cloned(),
tokens[current + node_offset].last().cloned(),
Some(vec![node]),
)),
node_offset + 1,
))
}
fn match_alias(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_symbol(&tokens[current + 1], "::") {
return Ok((None, 0));
}
let type_tokens = gather(tokens[current])?;
let (type_node, type_offset) = match_all(&type_tokens, 0)?;
if type_node.is_none() {
return Ok((None, 0));
}
let type_node = type_node.unwrap();
if type_offset != type_tokens.len() {
return Err(ParserError::NotFullyMatched(
type_tokens.first().unwrap().first().unwrap().clone(),
type_tokens.last().unwrap().last().unwrap().clone(),
));
}
let type_name = match &type_node.node_type {
ASTNodeType::Variable(name) => name.clone(),
ASTNodeType::String(name) => name.clone(),
_ => {
return Err(ParserError::InvalidSyntax(
tokens[current].first().unwrap().clone(),
));
}
};
let right_tokens = &tokens[current + 2..].to_vec();
let (value_node, value_offset) = match_all(&right_tokens, 0)?;
if value_node.is_none() {
return Ok((None, 0));
}
if value_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let value_node = value_node.unwrap();
Ok((
Some(ASTNode::new(
ASTNodeType::Namespace(type_name),
tokens[current].first().cloned(),
tokens[current + value_offset + 1].last().cloned(),
Some(vec![value_node]),
)),
value_offset + 2,
))
}
fn match_member_access_and_apply(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 1 >= tokens.len() {
return Ok((None, 0));
}
let is_member_access = is_symbol(&tokens[tokens.len() - 2], ".");
let left = if is_member_access {
tokens[current..tokens.len() - 2].to_vec()
} else {
tokens[current..tokens.len() - 1].to_vec()
};
let (left_node, left_offset) = match_all(&left, 0)?;
if left_node.is_none() {
return Ok((None, 0));
}
let left_node = left_node.unwrap();
if left_offset != left.len() {
return Err(ParserError::NotFullyMatched(
left.first().unwrap().first().unwrap().clone(),
left.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = gather(&tokens.last().unwrap())?;
let (right_node, right_offset) = match_all(&right_tokens, 0)?;
if right_node.is_none() {
return Ok((None, 0));
}
let mut right_node = right_node.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
if let ASTNodeType::Variable(name) = &right_node.node_type
&& is_member_access
{
right_node = ASTNode {
node_type: ASTNodeType::String(name.clone()),
start_token: right_node.start_token,
end_token: right_node.end_token,
children: right_node.children,
};
}
return Ok((
Some(ASTNode::new(
if is_member_access {
ASTNodeType::GetAttr
} else {
ASTNodeType::Apply
},
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![left_node, right_node]),
)),
tokens.len() - current, ));
}
fn match_range(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_symbol(&tokens[current + 1], "..") {
return Ok((None, 0));
}
let left_tokens = gather(tokens[current])?;
let (left, left_offset) = match_all(&left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = &tokens[current + 2..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
Ok((
Some(ASTNode::new(
ASTNodeType::Range,
tokens[current].first().cloned(),
tokens[current + right_offset + 1].last().cloned(),
Some(vec![left, right]),
)),
right_offset + 2,
))
}
fn match_in(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_identifier(&tokens[current + 1], "in") {
return Ok((None, 0));
}
let left_tokens = gather(tokens[current])?;
let (left, left_offset) = match_all(&left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = &tokens[current + 2..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
Ok((
Some(ASTNode::new(
ASTNodeType::In,
tokens[current].first().cloned(),
tokens[current + right_offset + 1].last().cloned(),
Some(vec![left, right]),
)),
right_offset + 2,
))
}
fn match_is(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
if !is_identifier(&tokens[current + 1], "is") {
return Ok((None, 0));
}
let left_tokens = gather(tokens[current])?;
let (left, left_offset) = match_all(&left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = &tokens[current + 2..].to_vec();
let (right, right_offset) = match_all(&right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right = right.unwrap();
Ok((
Some(ASTNode::new(
ASTNodeType::Is,
tokens[current].first().cloned(),
tokens[current + right_offset + 1].last().cloned(),
Some(vec![left, right]),
)),
right_offset + 2,
))
}
fn match_as(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current + 2 >= tokens.len() {
return Ok((None, 0));
}
let mut offset: usize = tokens.len() - current - 1;
let mut operator_pos: usize = 0;
let mut found = false;
while offset > 0 {
let pos = current + offset;
if is_identifier(&tokens[pos], "as") {
operator_pos = pos;
found = true;
break;
}
offset -= 1;
}
if !found {
return Ok((None, 0));
}
let left_tokens = &tokens[current..operator_pos].to_vec();
let (left, left_offset) = match_all(left_tokens, 0)?;
if left.is_none() {
return Ok((None, 0));
}
let left = left.unwrap();
if left_offset != left_tokens.len() {
return Err(ParserError::NotFullyMatched(
left_tokens.first().unwrap().first().unwrap().clone(),
left_tokens.last().unwrap().last().unwrap().clone(),
));
}
let right_tokens = &tokens[operator_pos + 1..].to_vec();
let (right, right_offset) = match_all(right_tokens, 0)?;
if right.is_none() {
return Ok((None, 0));
}
let right = right.unwrap();
if right_offset != right_tokens.len() {
return Err(ParserError::NotFullyMatched(
right_tokens.first().unwrap().first().unwrap().clone(),
right_tokens.last().unwrap().last().unwrap().clone(),
));
}
let args_tuple = ASTNode::new(
ASTNodeType::Tuple,
left.start_token.clone(),
left.end_token.clone(),
Some(vec![left]),
);
let function_call = ASTNode::new(
ASTNodeType::Apply,
tokens[current].first().cloned(),
tokens.last().unwrap().last().cloned(),
Some(vec![right, args_tuple]),
);
Ok((
Some(function_call),
tokens.len() - current, ))
}
fn match_variable(
tokens: &Vec<GatheredTokens>,
current: usize,
) -> Result<(Option<ASTNode>, usize), ParserError> {
if current >= tokens.len() {
return Ok((None, 0));
}
if is_bracket(&tokens[current]) || is_square_bracket(&tokens[current]) {
let inner_tokens = unwrap_brace(&tokens[current])?;
let gathered_inner = gather(inner_tokens)?;
let (node, _) = match_all(&gathered_inner, 0)?;
if node.is_none() {
return Ok((None, 0));
}
return Ok((Some(node.unwrap()), 1));
}
if is_brace(&tokens[current]) {
let body_tokens = unwrap_brace(&tokens[current])?;
let gathered_body = gather(body_tokens)?;
let (body, _) = match_all(&gathered_body, 0)?;
return Ok((
Some(ASTNode::new(
ASTNodeType::Frame,
tokens[current].first().cloned(),
tokens[current].last().cloned(),
body.map(|b| vec![b]),
)),
1,
));
}
if tokens[current].len() == 1 && tokens[current].first().unwrap() == TokenType::STRING {
return Ok((
Some(ASTNode::new(
ASTNodeType::String(tokens[current].first().unwrap().token().clone()),
tokens[current].first().cloned(),
tokens[current].last().cloned(),
None,
)),
1,
));
}
if tokens[current].len() == 1 && tokens[current].first().unwrap() == TokenType::NUMBER {
return Ok((
Some(ASTNode::new(
ASTNodeType::Number(tokens[current].first().unwrap().token().clone()),
tokens[current].first().cloned(),
tokens[current].last().cloned(),
None,
)),
1,
));
}
if tokens[current].len() == 1 && tokens[current].first().unwrap() == TokenType::BASE64 {
return Ok((
Some(ASTNode::new(
ASTNodeType::Base64(tokens[current].first().unwrap().token().clone()),
tokens[current].first().cloned(),
tokens[current].last().cloned(),
None,
)),
1,
));
}
if is_identifier(&tokens[current], "true") {
return Ok((
Some(ASTNode::new(
ASTNodeType::Boolean(true),
tokens[current].first().cloned(),
tokens[current].last().cloned(),
None,
)),
1,
));
}
if is_identifier(&tokens[current], "false") {
return Ok((
Some(ASTNode::new(
ASTNodeType::Boolean(false),
tokens[current].first().cloned(),
tokens[current].last().cloned(),
None,
)),
1,
));
}
if is_identifier(&tokens[current], "null") {
return Ok((
Some(ASTNode::new(
ASTNodeType::Null,
tokens[current].first().cloned(),
tokens[current].last().cloned(),
None,
)),
1,
));
}
if is_identifier(&tokens[current], "undefined") {
return Ok((
Some(ASTNode::new(
ASTNodeType::Undefined,
tokens[current].first().cloned(),
tokens[current].last().cloned(),
None,
)),
1,
));
}
if tokens[current].len() == 1 && tokens[current].first().unwrap() == TokenType::IDENTIFIER {
return Ok((
Some(ASTNode::new(
ASTNodeType::Variable(tokens[current].first().unwrap().token().clone()),
tokens[current].first().cloned(),
tokens[current].last().cloned(),
None,
)),
1,
));
}
Ok((None, 0))
}