use error::{Error, MinusOneResult};
use ps::access::{AccessArray, AccessHashMap, AccessString};
use ps::array::{AddArray, ComputeArrayExpr, ParseArrayLiteral, ParseRange};
use ps::bool::{BoolAlgebra, Comparison, Not, ParseBool};
use ps::cast::{Cast, CastNull};
use ps::foreach::{ForEach, PSItemInferrator};
use ps::forward::Forward;
use ps::hash::ParseHash;
use ps::integer::{AddInt, MultInt, ParseInt};
use ps::join::{JoinComparison, JoinOperator, JoinStringMethod};
use ps::linter::RemoveComment;
use ps::method::{DecodeBase64, FromUTF, Length};
use ps::string::{
ConcatString, FormatString, ParseString, StringReplaceMethod, StringReplaceOp,
StringSplitMethod,
};
use ps::typing::ParseType;
use ps::var::{StaticVar, Var};
use std::collections::BTreeMap;
use tree::{HashMapStorage, Storage, Tree};
use tree_sitter_powershell::LANGUAGE as powershell_language;
pub mod access;
pub mod array;
pub mod bool;
pub mod cast;
pub mod foreach;
pub mod forward;
pub mod hash;
pub mod integer;
pub mod join;
pub mod linter;
pub mod method;
pub mod strategy;
pub mod string;
pub mod typing;
pub mod var;
mod tool;
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub enum Value {
Num(i64),
Str(String),
Bool(bool),
}
impl Value {
fn normalize(&self) -> Value {
match self {
Value::Str(x) => Value::Str(x.to_lowercase()),
x => x.clone(),
}
}
}
impl ToString for Value {
fn to_string(&self) -> String {
match self {
Value::Num(e) => e.to_string(),
Value::Str(s) => s.clone(),
Value::Bool(true) => "True".to_string(),
Value::Bool(false) => "False".to_string(),
}
}
}
impl Value {
fn to_i64(&self) -> Option<i64> {
match self {
Value::Str(s) => {
if let Ok(number) = s.parse::<i64>() {
Some(number)
} else if s.len() > 2 {
u32::from_str_radix(&s[2..], 16).map(|e| e as i64).ok()
} else {
None
}
}
Value::Num(i) => Some(*i),
Value::Bool(_) => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Powershell {
Raw(Value),
Array(Vec<Value>),
PSItem(Vec<Value>),
Null,
HashMap(BTreeMap<Value, Value>),
HashEntry(Value, Value),
Type(String), Unknown,
}
pub type RuleSet = (
Forward, ParseInt, AddInt, MultInt, ParseString, ConcatString, Cast, ParseArrayLiteral, ParseRange, AccessString, JoinComparison, JoinStringMethod, JoinOperator, PSItemInferrator, ForEach, StringReplaceMethod, ComputeArrayExpr, StringReplaceOp, StaticVar, CastNull, ParseHash, FormatString, ParseBool, Comparison, Not, ParseType, DecodeBase64, FromUTF, Length, BoolAlgebra, Var, AddArray, StringSplitMethod, AccessArray, AccessHashMap, );
pub fn remove_powershell_extra(source: &str) -> MinusOneResult<String> {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&powershell_language.into())
.expect("Error loading powershell grammar");
let source = source.trim();
let tree_sitter_remove_extra = parser.parse(source, None).unwrap();
let root = Tree::<HashMapStorage<Powershell>>::new(source.as_bytes(), tree_sitter_remove_extra);
let root_node = root.root().or(Err(Error::invalid_program()))?;
if root_node.kind() != "program" {
return Err(Error::invalid_program());
}
if root_node.start_abs() != 0 {
return Err(Error::invalid_program_index(root_node.start_abs()));
}
let mut source_without_extra = RemoveComment::new();
root.apply(&mut source_without_extra)?;
Ok(source_without_extra.output)
}
pub fn build_powershell_tree(source: &str) -> MinusOneResult<Tree<HashMapStorage<Powershell>>> {
build_powershell_tree_for_storage::<HashMapStorage<Powershell>>(source)
}
pub fn build_powershell_tree_for_storage<T: Storage + Default>(source: &str) -> MinusOneResult<Tree<T>> {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&powershell_language.into())
.expect("Error loading powershell grammar");
let tree_sitter = parser.parse(source, None).unwrap();
Ok(Tree::<T>::new(
source.as_bytes(),
tree_sitter,
))
}