use crate::tokens::Token;
use std::fmt;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct NodeId(pub usize);
impl fmt::Display for NodeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "NodeId({})", self.0)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TokenId(pub usize);
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Arena {
nodes: Vec<AstNode>,
tokens: Vec<Token>,
}
impl Arena {
pub fn new() -> Self {
Arena {
nodes: Vec::new(),
tokens: Vec::new(),
}
}
pub fn alloc_node(&mut self, node: AstNode) -> NodeId {
let id = NodeId(self.nodes.len());
self.nodes.push(node);
id
}
pub fn get_node(&self, id: NodeId) -> &AstNode {
&self.nodes[id.0]
}
pub fn get_node_mut(&mut self, id: NodeId) -> &mut AstNode {
&mut self.nodes[id.0]
}
pub fn alloc_token(&mut self, token: Token) -> TokenId {
let id = TokenId(self.tokens.len());
self.tokens.push(token);
id
}
pub fn get_token(&self, id: TokenId) -> &Token {
&self.tokens[id.0]
}
pub fn pretty_print(&self, root: NodeId, indent: usize, input: &str) -> String {
let mut result = format!("AST: \"{}\"\n", input);
self.pretty_print_impl(root, indent + 1, &mut result);
result
}
fn is_passthrough(&self, node_id: NodeId) -> bool {
match self.get_node(node_id) {
AstNode::JmsSelector(n) => n.children.len() == 1,
AstNode::OrExpression(n) => n.children.len() == 1,
AstNode::AndExpression(n) => n.children.len() == 1,
AstNode::EqualityExpression(n) => n.children.len() == 1 && n.operators.is_empty(),
AstNode::ComparisonExpression(n) => n.children.len() == 1 && n.operators.is_empty(),
AstNode::AddExpression(n) => n.children.len() == 1 && n.operators.is_empty(),
AstNode::MultExpr(n) => n.children.len() == 1 && n.operators.is_empty(),
AstNode::UnaryExpr(n) => n.children.len() == 1 && n.operator.is_none(),
AstNode::PrimaryExpr(_) => false,
AstNode::Literal(_) => false,
AstNode::StringLiteral(n) => n.children.len() == 1,
AstNode::Variable(n) => n.children.len() == 1,
}
}
fn first_child(&self, node_id: NodeId) -> Option<NodeId> {
match self.get_node(node_id) {
AstNode::JmsSelector(n) => n.children.first().copied(),
AstNode::OrExpression(n) => n.children.first().copied(),
AstNode::AndExpression(n) => n.children.first().copied(),
AstNode::EqualityExpression(n) => n.children.first().copied(),
AstNode::ComparisonExpression(n) => n.children.first().copied(),
AstNode::AddExpression(n) => n.children.first().copied(),
AstNode::MultExpr(n) => n.children.first().copied(),
AstNode::UnaryExpr(n) => n.children.first().copied(),
AstNode::PrimaryExpr(n) => n.children.first().copied(),
AstNode::Literal(n) => n.children.first().copied(),
AstNode::StringLiteral(n) => n.children.first().copied(),
AstNode::Variable(n) => n.children.first().copied(),
}
}
fn pretty_print_impl(&self, node_id: NodeId, indent: usize, result: &mut String) {
if self.is_passthrough(node_id) {
if let Some(child) = self.first_child(node_id) {
self.pretty_print_impl(child, indent, result);
}
return;
}
let indent_str = " ".repeat(indent);
match self.get_node(node_id) {
AstNode::JmsSelector(node) => {
if node.children.is_empty() {
let value = &self.get_token(node.begin_token).image;
result.push_str(&format!("{}JmsSelector(\"{}\")\n", indent_str, value));
} else {
result.push_str(&format!("{}JmsSelector\n", indent_str));
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
}
AstNode::OrExpression(node) => {
if node.children.len() > 1 {
result.push_str(&format!("{}OrExpression [OR x{}]\n", indent_str, node.children.len() - 1));
} else {
result.push_str(&format!("{}OrExpression\n", indent_str));
}
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
AstNode::AndExpression(node) => {
if node.children.len() > 1 {
result.push_str(&format!("{}AndExpression [AND x{}]\n", indent_str, node.children.len() - 1));
} else {
result.push_str(&format!("{}AndExpression\n", indent_str));
}
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
AstNode::EqualityExpression(node) => {
if !node.operators.is_empty() {
let ops: Vec<&str> = node.operators.iter()
.map(|op| match op {
EqualityOp::Equal => "=",
EqualityOp::NotEqual => "<>",
EqualityOp::IsNull => "IS NULL",
EqualityOp::IsNotNull => "IS NOT NULL",
})
.collect();
result.push_str(&format!("{}EqualityExpression [{}]\n", indent_str, ops.join(", ")));
} else if node.children.is_empty() {
let value = &self.get_token(node.begin_token).image;
result.push_str(&format!("{}EqualityExpression(\"{}\")\n", indent_str, value));
} else {
result.push_str(&format!("{}EqualityExpression\n", indent_str));
}
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
AstNode::ComparisonExpression(node) => {
if !node.operators.is_empty() {
let ops: Vec<&str> = node.operators.iter()
.map(|op| match op {
ComparisonOp::GreaterThan => ">",
ComparisonOp::GreaterThanEqual => ">=",
ComparisonOp::LessThan => "<",
ComparisonOp::LessThanEqual => "<=",
ComparisonOp::Like => "LIKE",
ComparisonOp::NotLike => "NOT LIKE",
ComparisonOp::LikeEscape => "LIKE ESCAPE",
ComparisonOp::NotLikeEscape => "NOT LIKE ESCAPE",
ComparisonOp::Between => "BETWEEN",
ComparisonOp::NotBetween => "NOT BETWEEN",
ComparisonOp::In => "IN",
ComparisonOp::NotIn => "NOT IN",
})
.collect();
result.push_str(&format!("{}ComparisonExpression [{}]\n", indent_str, ops.join(", ")));
} else if node.children.is_empty() {
let value = &self.get_token(node.begin_token).image;
result.push_str(&format!("{}ComparisonExpression(\"{}\")\n", indent_str, value));
} else {
result.push_str(&format!("{}ComparisonExpression\n", indent_str));
}
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
AstNode::AddExpression(node) => {
if !node.operators.is_empty() {
let ops: Vec<&str> = node.operators.iter()
.map(|op| match op {
AddOp::Plus => "+",
AddOp::Minus => "-",
})
.collect();
result.push_str(&format!("{}AddExpression [{}]\n", indent_str, ops.join(", ")));
} else {
result.push_str(&format!("{}AddExpression\n", indent_str));
}
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
AstNode::MultExpr(node) => {
if !node.operators.is_empty() {
let ops: Vec<&str> = node.operators.iter()
.map(|op| match op {
MultExprOp::Star => "*",
MultExprOp::Slash => "/",
MultExprOp::Percent => "%",
})
.collect();
result.push_str(&format!("{}MultExpr [{}]\n", indent_str, ops.join(", ")));
} else {
result.push_str(&format!("{}MultExpr\n", indent_str));
}
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
AstNode::UnaryExpr(node) => {
if let Some(op) = &node.operator {
let op_str = match op {
UnaryOp::Plus => "+",
UnaryOp::Negate => "-",
UnaryOp::Not => "NOT",
};
result.push_str(&format!("{}UnaryExpr [{}]\n", indent_str, op_str));
} else if node.children.is_empty() {
let value = &self.get_token(node.begin_token).image;
result.push_str(&format!("{}UnaryExpr(\"{}\")\n", indent_str, value));
} else {
result.push_str(&format!("{}UnaryExpr\n", indent_str));
}
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
AstNode::PrimaryExpr(node) => {
if node.children.is_empty() {
let token = self.get_token(node.begin_token);
result.push_str(&format!("{}PrimaryExpr(\"{}\")\n", indent_str, token.image));
} else {
result.push_str(&format!("{}PrimaryExpr\n", indent_str));
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
}
AstNode::Literal(node) => {
if node.children.is_empty() {
let token = self.get_token(node.begin_token);
result.push_str(&format!("{}Literal(\"{}\")\n", indent_str, token.image));
} else {
result.push_str(&format!("{}Literal\n", indent_str));
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
}
AstNode::StringLiteral(node) => {
if node.children.is_empty() {
let value = &self.get_token(node.begin_token).image;
result.push_str(&format!("{}StringLiteral(\"{}\")\n", indent_str, value));
} else {
result.push_str(&format!("{}StringLiteral\n", indent_str));
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
}
AstNode::Variable(node) => {
if node.children.is_empty() {
let value = &self.get_token(node.begin_token).image;
result.push_str(&format!("{}Variable(\"{}\")\n", indent_str, value));
} else {
result.push_str(&format!("{}Variable\n", indent_str));
for child in &node.children {
self.pretty_print_impl(*child, indent + 1, result);
}
}
}
}
}
}
impl Default for Arena {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum AstNode {
JmsSelector(JmsSelectorNode),
OrExpression(OrExpressionNode),
AndExpression(AndExpressionNode),
EqualityExpression(EqualityExpressionNode),
ComparisonExpression(ComparisonExpressionNode),
AddExpression(AddExpressionNode),
MultExpr(MultExprNode),
UnaryExpr(UnaryExprNode),
PrimaryExpr(PrimaryExprNode),
Literal(LiteralNode),
StringLiteral(StringLiteralNode),
Variable(VariableNode),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum AddOp {
Plus,
Minus,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum MultExprOp {
Star,
Slash,
Percent,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum EqualityOp {
Equal,
NotEqual,
IsNull,
IsNotNull,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ComparisonOp {
GreaterThan,
GreaterThanEqual,
LessThan,
LessThanEqual,
Like,
NotLike,
LikeEscape,
NotLikeEscape,
Between,
NotBetween,
In,
NotIn,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum UnaryOp {
Plus,
Negate,
Not,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct JmsSelectorNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl JmsSelectorNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
JmsSelectorNode {
parent: None,
children: Vec::new(),
begin_token,
end_token,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct OrExpressionNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl OrExpressionNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
OrExpressionNode {
parent: None,
children: Vec::new(),
begin_token,
end_token,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AndExpressionNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl AndExpressionNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
AndExpressionNode {
parent: None,
children: Vec::new(),
begin_token,
end_token,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EqualityExpressionNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub operators: Vec<EqualityOp>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl EqualityExpressionNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
EqualityExpressionNode {
parent: None,
children: Vec::new(),
operators: Vec::new(),
begin_token,
end_token,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ComparisonExpressionNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub operators: Vec<ComparisonOp>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl ComparisonExpressionNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
ComparisonExpressionNode {
parent: None,
children: Vec::new(),
operators: Vec::new(),
begin_token,
end_token,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AddExpressionNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub operators: Vec<AddOp>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl AddExpressionNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
AddExpressionNode {
parent: None,
children: Vec::new(),
operators: Vec::new(),
begin_token,
end_token,
}
}
pub fn left<'a>(&self, arena: &'a Arena) -> &'a AstNode {
arena.get_node(self.children[0])
}
pub fn right<'a>(&self, arena: &'a Arena) -> Option<&'a AstNode> {
self.children.get(1).map(|id| arena.get_node(*id))
}
pub fn op(&self, index: usize) -> Option<AddOp> {
self.operators.get(index).copied()
}
pub fn first_op(&self) -> Option<AddOp> {
self.operators.first().copied()
}
pub fn op_operand_pairs(&self) -> impl Iterator<Item = (AddOp, NodeId)> + '_ {
self.operators.iter().copied().zip(self.children.iter().skip(1).copied())
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MultExprNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub operators: Vec<MultExprOp>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl MultExprNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
MultExprNode {
parent: None,
children: Vec::new(),
operators: Vec::new(),
begin_token,
end_token,
}
}
pub fn left<'a>(&self, arena: &'a Arena) -> &'a AstNode {
arena.get_node(self.children[0])
}
pub fn right<'a>(&self, arena: &'a Arena) -> Option<&'a AstNode> {
self.children.get(1).map(|id| arena.get_node(*id))
}
pub fn op(&self, index: usize) -> Option<MultExprOp> {
self.operators.get(index).copied()
}
pub fn first_op(&self) -> Option<MultExprOp> {
self.operators.first().copied()
}
pub fn op_operand_pairs(&self) -> impl Iterator<Item = (MultExprOp, NodeId)> + '_ {
self.operators.iter().copied().zip(self.children.iter().skip(1).copied())
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UnaryExprNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub operator: Option<UnaryOp>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl UnaryExprNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
UnaryExprNode {
parent: None,
children: Vec::new(),
operator: None,
begin_token,
end_token,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PrimaryExprNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl PrimaryExprNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
PrimaryExprNode {
parent: None,
children: Vec::new(),
begin_token,
end_token,
}
}
pub fn value<'a>(&self, arena: &'a Arena) -> &'a str {
&arena.get_token(self.begin_token).image
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct LiteralNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl LiteralNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
LiteralNode {
parent: None,
children: Vec::new(),
begin_token,
end_token,
}
}
pub fn value<'a>(&self, arena: &'a Arena) -> &'a str {
&arena.get_token(self.begin_token).image
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct StringLiteralNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl StringLiteralNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
StringLiteralNode {
parent: None,
children: Vec::new(),
begin_token,
end_token,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct VariableNode {
pub parent: Option<NodeId>,
pub children: Vec<NodeId>,
pub begin_token: TokenId,
pub end_token: TokenId,
}
impl VariableNode {
pub fn new(begin_token: TokenId, end_token: TokenId) -> Self {
VariableNode {
parent: None,
children: Vec::new(),
begin_token,
end_token,
}
}
}