use super::{parser_functions, ASTContext, Node, SyntaxError};
use crate::{ast_node::TokenSlice, tokens::lexer};
use anyhow::{anyhow, Result};
use std::rc::Rc;
pub fn tokenize_str_no_context(input: &str) -> Result<(ASTContext, TokenSlice), anyhow::Error> {
let tokens = match lexer(input) {
Ok(t) => t,
Err(e) => return Err(e),
};
let mut context = ASTContext::new();
let num_tokens = tokens.len();
context.set_tokens(tokens);
let slice = TokenSlice::new(0, num_tokens, num_tokens);
Ok((context, slice))
}
pub fn parse_str(input: &str, context: &mut ASTContext) -> Result<Rc<Node>, anyhow::Error> {
let tokens = match lexer(input) {
Ok(t) => t,
Err(e) => {
println!("Error in lexer:\n {:?}", e);
return Err(e);
}
};
let result = match parser_functions::parse_line(tokens, context) {
Ok(n) => n,
Err(e) => {
println!("Error in parser:\n {:?}", e);
return Err(e);
}
};
let tree_ok = verify_types_tree(&result);
if let Err(e) = tree_ok {
println!("Error veryfing tree:\n {:?}", e);
}
println!("Node: {:?}", result);
Ok(result)
}
pub fn parse_str_no_context(input: &str) -> Result<(Rc<Node>, ASTContext)> {
let mut context = ASTContext::new();
let node = match parse_str(input, &mut context) {
Ok(node) => node,
Err(e) => {
println!("Error: {:?}", e);
return Err(e);
}
};
Ok((node, context))
}
pub fn is_specific_syntax_error(error: &anyhow::Error, expected_error: &SyntaxError) -> bool {
if let Some(actual_error) = error.downcast_ref::<SyntaxError>() {
actual_error == expected_error
} else {
false
}
}
pub fn verify_types_tree(node: &Node) -> Result<(), anyhow::Error> {
if node.operands.is_empty() {
return Ok(());
}
if node.operands.len() != node.input_types.len() {
return Err(anyhow!("Operands and input types length mismatch"));
}
for (operand, input_type) in node.operands.iter().zip(node.input_types.iter()) {
if operand.output_type != *input_type {
return Err(anyhow!(
"Operand and input type mismatch:\n\
Node: {:?}\n\
Operand: {:?}\n\
Operand output type: {:?}\n\
Expected input type: {:?}",
node,
operand,
operand.output_type,
input_type
));
}
}
node.operands.iter().try_for_each(|n| verify_types_tree(n))
}
pub fn create_context_with_tokens_from_str(input: &str) -> Result<ASTContext, anyhow::Error> {
let tokens = match lexer(input) {
Ok(t) => t,
Err(e) => return Err(e),
};
let mut context = ASTContext::new();
context.set_tokens(tokens);
Ok(context)
}