use std::{
fmt::{self, Display, Formatter},
ops::RangeInclusive,
rc::Rc,
sync::Arc,
};
use super::node::Span;
use derive_more::derive::{From, TryUnwrap};
use crate::{
antlr::{
hamelinparser::{
AssignmentClauseContextAll, AssignmentClauseContextAttrs, AssignmentContextAll,
AssignmentContextAttrs, FromClauseContextAll, FromClauseContextAttrs,
SelectionContextAll, SelectionContextAttrs, SortExpressionContextAll,
SortExpressionContextAttrs, TableAliasContextAttrs, TableReferenceContextAll,
TableReferenceContextAttrs,
},
interval,
},
err::TranslationError,
tree::ast::{
context::{FromCst, ParseContext},
identifier::Identifier,
},
};
use super::{
expression::{ErrorExpression, Expression},
identifier::{ParsedIdentifier, ParsedSimpleIdentifier, SimpleIdentifier},
node::Spannable,
};
use antlr_rust::tree::ParseTree;
#[derive(Debug, Clone)]
pub struct Assignment {
pub span: Span,
pub identifier: ParsedIdentifier,
pub expression: Arc<Expression>,
}
impl PartialEq for Assignment {
fn eq(&self, other: &Self) -> bool {
self.identifier == other.identifier && self.expression == other.expression
}
}
impl Assignment {
pub fn from_parts(identifier: ParsedIdentifier, expression: Expression) -> Self {
Self {
span: Span::NONE,
identifier,
expression: Arc::new(expression),
}
}
}
impl Spannable for Assignment {
fn span(&self) -> Option<RangeInclusive<usize>> {
self.span.to_range()
}
}
impl FromCst<Rc<AssignmentContextAll<'static>>> for Assignment {
fn from_cst_with_context(
cst: Rc<AssignmentContextAll<'static>>,
ctx: &mut ParseContext,
) -> Self {
let identifier = cst
.identifier()
.map(|id_cst| ParsedIdentifier::from_cst_with_context(id_cst, ctx))
.unwrap_or_else(|| {
ctx.error("missing identifier in assignment")
.at(cst.as_ref())
.emit()
.into()
});
let expression = if let Some(expr_ctx) = cst.expression() {
Expression::from_cst_with_context(expr_ctx, ctx)
} else {
let err = ctx
.error("missing expression in assignment")
.at(cst.as_ref())
.emit();
Expression::from_kind(ErrorExpression { error: err })
};
Self {
span: interval(cst.as_ref()).into(),
identifier,
expression: Arc::new(expression),
}
}
}
#[derive(Debug, Clone, From, PartialEq, TryUnwrap)]
pub enum AssignmentClause {
Assignment(Assignment),
Error(Arc<TranslationError>),
}
impl Spannable for AssignmentClause {
fn span(&self) -> Option<RangeInclusive<usize>> {
match self {
AssignmentClause::Assignment(a) => a.span(),
AssignmentClause::Error(_) => None,
}
}
}
impl FromCst<Rc<AssignmentClauseContextAll<'static>>> for AssignmentClause {
fn from_cst_with_context(
cst: Rc<AssignmentClauseContextAll<'static>>,
ctx: &mut ParseContext,
) -> Self {
if let Some(assignment_ctx) = cst.assignment() {
Assignment::from_cst_with_context(assignment_ctx, ctx).into()
} else if let Some(expr_ctx) = cst.expression() {
let expression = Expression::from_cst_with_context(expr_ctx.clone(), ctx);
let identifier = Identifier::infer_from_expression(&expression).unwrap_or_else(|| {
SimpleIdentifier::new(expr_ctx.get_text().replace('`', "")).into()
});
Assignment::from_parts(identifier, expression).into()
} else {
ctx.error("invalid assignment clause")
.at(cst.as_ref())
.emit()
.into()
}
}
}
#[derive(Debug, Clone)]
pub struct TableAlias {
pub span: Span,
pub alias: ParsedSimpleIdentifier,
pub table: TableReference,
}
impl Spannable for TableAlias {
fn span(&self) -> Option<RangeInclusive<usize>> {
self.span.to_range()
}
}
impl PartialEq for TableAlias {
fn eq(&self, other: &Self) -> bool {
self.alias == other.alias && self.table == other.table
}
}
#[derive(Debug, Clone)]
pub struct TableReference {
pub span: Span,
pub identifier: ParsedIdentifier,
}
impl PartialEq for TableReference {
fn eq(&self, other: &Self) -> bool {
self.identifier == other.identifier
}
}
impl Spannable for TableReference {
fn span(&self) -> Option<RangeInclusive<usize>> {
self.span.to_range()
}
}
impl FromCst<Rc<TableReferenceContextAll<'static>>> for TableReference {
fn from_cst_with_context(
cst: Rc<TableReferenceContextAll<'static>>,
ctx: &mut ParseContext,
) -> Self {
let identifier = cst
.identifier()
.map(|id| ParsedIdentifier::from_cst_with_context(id, ctx))
.unwrap_or_else(|| {
ctx.error("missing table identifier")
.at(cst.as_ref())
.emit()
.into()
});
Self {
span: interval(cst.as_ref()).into(),
identifier,
}
}
}
#[derive(Debug, Clone, From, PartialEq, TryUnwrap)]
pub enum FromClause {
TableAlias(Arc<TableAlias>),
TableReference(Arc<TableReference>),
}
impl FromClause {
pub fn table_reference(&self) -> TableReference {
match self {
FromClause::TableReference(tr) => tr.as_ref().clone(),
FromClause::TableAlias(ta) => ta.table.clone(),
}
}
}
impl Spannable for FromClause {
fn span(&self) -> Option<RangeInclusive<usize>> {
match self {
FromClause::TableAlias(ta) => ta.span(),
FromClause::TableReference(tr) => tr.span(),
}
}
}
impl FromCst<Rc<FromClauseContextAll<'static>>> for FromClause {
fn from_cst_with_context(
cst: Rc<FromClauseContextAll<'static>>,
ctx: &mut ParseContext,
) -> Self {
if let Some(table_alias_ctx) = cst.tableAlias() {
let alias = table_alias_ctx
.simpleIdentifier()
.map(|x| ParsedSimpleIdentifier::from_cst_with_context(x.as_ref(), ctx))
.unwrap_or_else(|| {
ctx.error("missing alias identifier")
.at(cst.as_ref())
.emit()
.into()
});
let table_ref_ctx = table_alias_ctx.tableReference();
let identifier = table_ref_ctx
.as_ref()
.and_then(|tr| tr.identifier())
.map(|id| ParsedIdentifier::from_cst_with_context(id, ctx))
.unwrap_or_else(|| {
ctx.error("missing table reference")
.at(cst.as_ref())
.emit()
.into()
});
Arc::new(TableAlias {
span: interval(table_alias_ctx.as_ref()).into(),
alias,
table: TableReference {
span: table_ref_ctx
.as_ref()
.map(|tr| interval(tr.as_ref()))
.into(),
identifier,
},
})
.into()
} else if let Some(table_ref_ctx) = cst.tableReference() {
Arc::new(TableReference::from_cst_with_context(table_ref_ctx, ctx)).into()
} else {
Arc::new(TableReference {
span: Span::NONE,
identifier: ctx
.error("invalid from clause")
.at(cst.as_ref())
.emit()
.into(),
})
.into()
}
}
}
impl From<TableAlias> for FromClause {
fn from(value: TableAlias) -> Self {
Self::from(Arc::new(value))
}
}
impl From<TableReference> for FromClause {
fn from(value: TableReference) -> Self {
Self::from(Arc::new(value))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SortOrder {
Asc,
Desc,
}
#[derive(Debug, Clone)]
pub struct SortExpression {
pub span: Span,
pub expression: Arc<Expression>,
pub order: Option<SortOrder>,
}
impl PartialEq for SortExpression {
fn eq(&self, other: &Self) -> bool {
self.expression == other.expression && self.order == other.order
}
}
impl Spannable for SortExpression {
fn span(&self) -> Option<RangeInclusive<usize>> {
self.span.to_range()
}
}
impl FromCst<Rc<SortExpressionContextAll<'static>>> for SortExpression {
fn from_cst_with_context(
cst: Rc<SortExpressionContextAll<'static>>,
ctx: &mut ParseContext,
) -> Self {
let expression = if let Some(expr_ctx) = cst.expression() {
Expression::from_cst_with_context(expr_ctx.clone(), ctx)
} else {
let err = ctx
.error("missing expression in sort")
.at(cst.as_ref())
.emit();
Expression::from_kind(ErrorExpression { error: err.clone() })
};
let order = if cst.ASC().is_some() {
Some(SortOrder::Asc)
} else if cst.DESC().is_some() {
Some(SortOrder::Desc)
} else {
None
};
Self {
span: interval(cst.as_ref()).into(),
expression: Arc::new(expression),
order,
}
}
}
#[derive(Debug, Clone)]
pub struct Selection {
pub span: Span,
pub identifier: ParsedIdentifier,
}
impl PartialEq for Selection {
fn eq(&self, other: &Self) -> bool {
self.identifier == other.identifier
}
}
impl Selection {
pub fn from_identifier(identifier: ParsedIdentifier) -> Self {
Self {
span: Span::NONE,
identifier,
}
}
}
impl Spannable for Selection {
fn span(&self) -> Option<RangeInclusive<usize>> {
self.span.to_range()
}
}
impl FromCst<Rc<SelectionContextAll<'static>>> for Selection {
fn from_cst_with_context(
cst: Rc<SelectionContextAll<'static>>,
ctx: &mut ParseContext,
) -> Self {
let identifier = cst
.identifier()
.map(|id| ParsedIdentifier::from_cst_with_context(id, ctx))
.unwrap_or_else(|| {
ctx.error("missing identifier in selection")
.at(cst.as_ref())
.emit()
.into()
});
Self {
span: interval(cst.as_ref()).into(),
identifier,
}
}
}
impl Assignment {
pub fn subelements(&self) -> usize {
self.expression.subelements() + 1
}
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: usize) -> fmt::Result {
write!(f, "{} = ", self.identifier)?;
let hang = indentation + self.identifier.to_string().len() + 3;
let expr_indent = if self.expression.subelements() > 4 {
indentation
} else {
hang
};
self.expression.fmt_indented(f, expr_indent)
}
}
impl Display for Assignment {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.fmt_indented(f, 0)
}
}
impl AssignmentClause {
pub fn subelements(&self) -> usize {
match self {
AssignmentClause::Assignment(a) => a.subelements(),
AssignmentClause::Error(_) => 0,
}
}
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: usize) -> fmt::Result {
match self {
AssignmentClause::Assignment(a) => a.fmt_indented(f, indentation),
AssignmentClause::Error(_) => write!(f, "?!"),
}
}
}
impl Display for AssignmentClause {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.fmt_indented(f, 0)
}
}
impl Display for TableReference {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.identifier)
}
}
impl Display for TableAlias {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{} = {}", self.alias, self.table)
}
}
impl FromClause {
pub fn fmt_indented(&self, f: &mut Formatter<'_>, _indentation: usize) -> fmt::Result {
match self {
FromClause::TableAlias(ta) => write!(f, "{}", ta),
FromClause::TableReference(tr) => write!(f, "{}", tr),
}
}
}
impl Display for FromClause {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.fmt_indented(f, 0)
}
}
impl Display for SortOrder {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SortOrder::Asc => write!(f, "ASC"),
SortOrder::Desc => write!(f, "DESC"),
}
}
}
impl SortExpression {
pub fn subelements(&self) -> usize {
self.expression.subelements() + 1
}
pub fn fmt_indented(&self, f: &mut Formatter<'_>, indentation: usize) -> fmt::Result {
self.expression.fmt_indented(f, indentation)?;
if let Some(order) = &self.order {
write!(f, " {}", order)?;
}
Ok(())
}
}
impl Display for SortExpression {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.fmt_indented(f, 0)
}
}
impl Display for Selection {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.identifier)
}
}