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
68 changes: 44 additions & 24 deletions rust/parser/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ use super::{
define::function::visit_definition_function,
expression::{visit_expression, visit_expression_function},
literal::{visit_integer_literal, visit_quoted_string_literal},
statement::{
thing::{visit_relation, visit_statement_thing},
visit_statement,
},
statement::{thing::visit_relation, visit_statement},
type_::{visit_label, visit_label_list},
visit_reduce_assignment_var, visit_var, visit_var_named, visit_vars, IntoChildNodes, Node, Rule, RuleMatcher,
};
Expand All @@ -23,7 +20,7 @@ use crate::{
token::{Order, ReduceOperator},
Spanned,
},
parser::{define::function::visit_function_block, statement::single::visit_statement_assignment},
parser::define::function::visit_function_block,
pattern::{Conjunction, Disjunction, Negation, Optional, Pattern},
query::{
pipeline::{
Expand All @@ -44,7 +41,6 @@ use crate::{
},
Pipeline,
},
statement::Statement,
value::StringLiteral,
TypeRef, TypeRefAny,
};
Expand Down Expand Up @@ -171,39 +167,45 @@ fn visit_pattern_try(node: Node<'_>) -> Optional {
fn visit_clause_insert(node: Node<'_>) -> Insert {
debug_assert_eq!(node.as_rule(), Rule::clause_insert);
let span = node.span();
let statements = node
.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)),
_ => unreachable!(
"Unrecognised statement inside insert clause: {:?}",
TypeQLError::IllegalGrammar { input: child.as_str().to_owned() }
),
})
.collect();
Insert::new(span, statements)
let mut children = node.into_children();
let patterns = visit_patterns(children.skip_expected(Rule::INSERT).consume_expected(Rule::patterns));
debug_assert_eq!(children.try_consume_any(), None);
Insert::new(span, patterns)
}

fn visit_clause_put(node: Node<'_>) -> Put {
debug_assert_eq!(node.as_rule(), Rule::clause_put);
let span = node.span();
let statement_things = node.into_children().skip_expected(Rule::PUT).map(visit_statement_thing).collect();
Put::new(span, statement_things)
let mut children = node.into_children();
let patterns = visit_patterns(children.skip_expected(Rule::PUT).consume_expected(Rule::patterns));
debug_assert_eq!(children.try_consume_any(), None);
Put::new(span, patterns)
}

fn visit_clause_update(node: Node<'_>) -> Update {
debug_assert_eq!(node.as_rule(), Rule::clause_update);
let span = node.span();
let statement_things = node.into_children().skip_expected(Rule::UPDATE).map(visit_statement_thing).collect();
Update::new(span, statement_things)
let mut children = node.into_children();
let patterns = visit_patterns(children.skip_expected(Rule::UPDATE).consume_expected(Rule::patterns));
debug_assert_eq!(children.try_consume_any(), None);
Update::new(span, patterns)
}

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 +237,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
10 changes: 6 additions & 4 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_put = { PUT ~ ( statement_thing ~ SEMICOLON )+ }
clause_update = { UPDATE ~ ( statement_thing ~ SEMICOLON )+ }
clause_insert = { INSERT ~ patterns }
clause_put = { PUT ~ patterns }
clause_update = { UPDATE ~ patterns }

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
16 changes: 8 additions & 8 deletions rust/query/pipeline/stage/put.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 Put {
pub span: Option<Span>,
pub statements: Vec<Statement>,
pub patterns: Vec<Pattern>,
}

impl Put {
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 Put {
impl Pretty for Put {
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", token::Clause::Put)?;
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,8 +49,8 @@ impl fmt::Display for Put {
Pretty::fmt(self, 0, f)
} else {
write!(f, "{}", token::Clause::Put)?;
for statement in &self.statements {
write!(f, " {statement};")?;
for pattern in &self.patterns {
write!(f, " {pattern};")?;
}
Ok(())
}
Expand Down
16 changes: 8 additions & 8 deletions rust/query/pipeline/stage/update.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 Update {
pub span: Option<Span>,
pub statements: Vec<Statement>,
pub patterns: Vec<Pattern>,
}

impl Update {
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 Update {
impl Pretty for Update {
fn fmt(&self, indent_level: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", token::Clause::Update)?;
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,8 +49,8 @@ impl fmt::Display for Update {
Pretty::fmt(self, 0, f)
} else {
write!(f, "{}", token::Clause::Update)?;
for statement in &self.statements {
write!(f, " {statement};")?;
for pattern in &self.patterns {
write!(f, " {pattern};")?;
}
Ok(())
}
Expand Down