use strum::{Display, EnumString};
use crate::{Span, Token};
#[derive(Debug, Clone)]
pub enum Segment {
Token(TokenSegment),
Node(NodeSegment),
}
impl Segment {
pub fn span(&self) -> Span {
match self {
Segment::Token(t) => t.token.span,
Segment::Node(n) => n.span,
}
}
pub fn segment_type(&self) -> SegmentType {
match self {
Segment::Token(t) => t.segment_type,
Segment::Node(n) => n.segment_type,
}
}
pub fn tokens(&self) -> Vec<&Token> {
match self {
Segment::Token(t) => vec![&t.token],
Segment::Node(n) => n.children.iter().flat_map(|c| c.tokens()).collect(),
}
}
pub fn children(&self) -> &[Segment] {
match self {
Segment::Token(_) => &[],
Segment::Node(n) => &n.children,
}
}
pub fn walk(&self, visitor: &mut dyn FnMut(&Segment)) {
visitor(self);
if let Segment::Node(n) = self {
for child in &n.children {
child.walk(visitor);
}
}
}
pub fn raw(&self) -> String {
self.tokens().iter().map(|t| t.text.as_str()).collect()
}
}
#[derive(Debug, Clone)]
pub struct TokenSegment {
pub token: Token,
pub segment_type: SegmentType,
}
#[derive(Debug, Clone)]
pub struct NodeSegment {
pub segment_type: SegmentType,
pub children: Vec<Segment>,
pub span: Span,
}
impl NodeSegment {
pub fn new(segment_type: SegmentType, children: Vec<Segment>) -> Self {
let span = if children.is_empty() {
Span::new(0, 0)
} else {
let first = children.first().unwrap().span();
let last = children.last().unwrap().span();
first.merge(last)
};
Self {
segment_type,
children,
span,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display, EnumString)]
pub enum SegmentType {
File,
Statement,
SelectStatement,
InsertStatement,
UpdateStatement,
DeleteStatement,
CreateTableStatement,
AlterTableStatement,
DropStatement,
TypeCastExpression,
OnConflictClause,
ArrayAccessExpression,
TableHint,
DeclareStatement,
SetVariableStatement,
IfStatement,
BeginEndBlock,
WhileStatement,
TryCatchBlock,
ExecStatement,
ReturnStatement,
PrintStatement,
ThrowStatement,
RaiserrorStatement,
GoStatement,
SelectClause,
FromClause,
WhereClause,
GroupByClause,
HavingClause,
OrderByClause,
LimitClause,
OffsetClause,
JoinClause,
OnClause,
UsingClause,
SetClause,
ValuesClause,
ReturningClause,
WithClause,
CteDefinition,
InsertColumnsClause,
ColumnRef,
TableRef,
FunctionCall,
FunctionArgs,
Expression,
BinaryExpression,
UnaryExpression,
ParenExpression,
CaseExpression,
WhenClause,
ElseClause,
Subquery,
ExistsExpression,
InExpression,
BetweenExpression,
CastExpression,
IsNullExpression,
LikeExpression,
WindowExpression,
OverClause,
PartitionByClause,
WindowFrameClause,
AliasExpression,
ColumnDefinition,
DataType,
ColumnConstraint,
TableConstraint,
OrderByExpression,
SortOrder,
Keyword,
Identifier,
QualifiedIdentifier,
QuotedIdentifier,
Literal,
NumericLiteral,
StringLiteral,
BooleanLiteral,
NullLiteral,
Operator,
ComparisonOperator,
ArithmeticOperator,
Comma,
Dot,
Semicolon,
Star,
LParen,
RParen,
Whitespace,
Newline,
LineComment,
BlockComment,
Unparsable,
}
impl SegmentType {
pub fn is_trivia(self) -> bool {
matches!(
self,
SegmentType::Whitespace
| SegmentType::Newline
| SegmentType::LineComment
| SegmentType::BlockComment
)
}
}