Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions rust/parser/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ fn visit_clause_insert(node: Node<'_>) -> Insert {
.into_children()
.skip_expected(Rule::INSERT)
.map(|child| match child.as_rule() {
Rule::statement_thing => visit_statement_thing(child),
Rule::statement_assignment => Statement::Assignment(visit_statement_assignment(child)),
Rule::statement_thing => Pattern::Statement(visit_statement_thing(child)),
Rule::statement_assignment => Pattern::Statement(Statement::Assignment(visit_statement_assignment(child))),
Rule::pattern_try => Pattern::Optional(visit_pattern_try(child)),
_ => unreachable!(
"Unrecognised statement inside insert clause: {:?}",
TypeQLError::IllegalGrammar { input: child.as_str().to_owned() }
Expand All @@ -203,7 +204,18 @@ fn visit_clause_update(node: Node<'_>) -> Update {
fn visit_clause_delete(node: Node<'_>) -> Delete {
debug_assert_eq!(node.as_rule(), Rule::clause_delete);
let span = node.span();
let deletables = node.into_children().skip_expected(Rule::DELETE).map(visit_statement_deletable).collect();
let deletables = node
.into_children()
.skip_expected(Rule::DELETE)
.map(|child| match child.as_rule() {
Rule::statement_deletable => visit_statement_deletable(child),
Rule::pattern_try_deletable => visit_pattern_try_deletable(child),
_ => unreachable!(
"Unrecognised statement inside delete clause: {:?}",
TypeQLError::IllegalGrammar { input: child.as_str().to_owned() }
),
})
.collect();
Delete::new(span, deletables)
}

Expand Down Expand Up @@ -235,6 +247,24 @@ fn visit_statement_deletable(node: Node<'_>) -> Deletable {
Deletable::new(span, kind)
}

fn visit_pattern_try_deletable(node: Node<'_>) -> Deletable {
debug_assert_eq!(node.as_rule(), Rule::pattern_try_deletable);
let span = node.span();
let deletables = node
.into_children()
.skip_expected(Rule::TRY)
.map(|child| match child.as_rule() {
Rule::statement_deletable => visit_statement_deletable(child),
Rule::pattern_try_deletable => visit_pattern_try_deletable(child),
_ => unreachable!(
"Unrecognised statement inside delete clause: {:?}",
TypeQLError::IllegalGrammar { input: child.as_str().to_owned() }
),
})
.collect();
Deletable::new(span, DeletableKind::Optional { deletables })
}

fn visit_clause_fetch(node: Node<'_>) -> Fetch {
debug_assert_eq!(node.as_rule(), Rule::clause_fetch);
let span = node.span();
Expand Down
6 changes: 4 additions & 2 deletions rust/parser/typeql.pest
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ query_stage_terminal = { clause_fetch ~ SEMICOLON }

clause_match = { MATCH ~ patterns }

clause_insert = { INSERT ~ ( statement_thing ~ SEMICOLON | statement_assignment ~ SEMICOLON )+ }
clause_insert = { INSERT ~ ( ( statement_thing | statement_assignment | pattern_try ) ~ SEMICOLON )+ }
clause_put = { PUT ~ ( statement_thing ~ SEMICOLON )+ }
clause_update = { UPDATE ~ ( statement_thing ~ SEMICOLON )+ }

clause_delete = { DELETE ~ ( statement_deletable ~ SEMICOLON )+ }
clause_delete = { DELETE ~ ( ( statement_deletable | pattern_try_deletable ) ~ SEMICOLON )+ }

// STREAM OPERATORS ===========================================================

Expand Down Expand Up @@ -123,6 +123,8 @@ statement_deletable = { HAS? ~ var ~ OF ~ var
| var
}

pattern_try_deletable = { TRY ~ CURLY_OPEN ~ ( statement_deletable ~ SEMICOLON )+ ~ CURLY_CLOSE }

// SINGLE STATEMENTS ===========================================================

statement_single = { statement_is | statement_comparison | statement_assignment | statement_in }
Expand Down
28 changes: 27 additions & 1 deletion rust/query/pipeline/stage/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,27 @@ pub enum DeletableKind {
Has { attribute: Variable, owner: Variable },
Links { players: Relation, relation: Variable },
Concept { variable: Variable },
Optional { deletables: Vec<Deletable> },
}

impl Pretty for DeletableKind {}
impl Pretty for DeletableKind {
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Optional { deletables } => {
writeln!(f, "{} {{", token::Keyword::Try)?;
for deletable in deletables {
indent(indent_level + 1, f)?;
Pretty::fmt(deletable, indent_level + 1, f)?;
writeln!(f, ";")?;
indent(indent_level, f)?;
}
f.write_char('}')?;
Ok(())
}
_ => write!(f, "{}", self),
}
}
}

impl fmt::Display for DeletableKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -107,6 +125,14 @@ impl fmt::Display for DeletableKind {
write!(f, "{} {} {} {}", token::Keyword::Links, players, token::Keyword::Of, relation)
}
Self::Concept { variable } => write!(f, "{}", variable),
Self::Optional { deletables } => {
write!(f, "{} {{ ", token::Keyword::Try)?;
for deletable in deletables {
write!(f, "{}; ", deletable)?;
}
f.write_char('}')?;
Ok(())
}
}
}
}
14 changes: 7 additions & 7 deletions rust/query/pipeline/stage/insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ use std::fmt::{self, Write};

use crate::{
common::{token, Span, Spanned},
pattern::Pattern,
pretty::{indent, Pretty},
statement::Statement,
};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Insert {
pub span: Option<Span>,
pub statements: Vec<Statement>,
pub patterns: Vec<Pattern>,
}

impl Insert {
pub(crate) fn new(span: Option<Span>, statements: Vec<Statement>) -> Self {
Self { span, statements }
pub(crate) fn new(span: Option<Span>, patterns: Vec<Pattern>) -> Self {
Self { span, patterns }
}
}

Expand All @@ -33,10 +33,10 @@ impl Spanned for Insert {
impl Pretty for Insert {
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", token::Clause::Insert)?;
for statement in &self.statements {
for pattern in &self.patterns {
writeln!(f)?;
indent(indent_level, f)?;
Pretty::fmt(statement, indent_level, f)?;
Pretty::fmt(pattern, indent_level, f)?;
f.write_char(';')?;
}
Ok(())
Expand All @@ -49,7 +49,7 @@ impl fmt::Display for Insert {
Pretty::fmt(self, 0, f)
} else {
write!(f, "{}", token::Clause::Insert)?;
for statement in &self.statements {
for statement in &self.patterns {
write!(f, " {statement};")?;
}
Ok(())
Expand Down