use super::Parser;
use crate::{
EdgeEndpoint, EdgeTableDefinition, ElementExposure, ElementLabel, ElementLabelExposure,
Identifier, PropertyExposure, Span, SyntaxError, TokenKind, VertexTableDefinition,
};
impl Parser<'_> {
pub(super) fn parse_vertex_table_definition(
&mut self,
) -> Result<VertexTableDefinition, SyntaxError> {
let start = self.current().span.start;
let table = self.parse_qualified_name()?;
let alias = self.parse_optional_as_alias()?;
let key = self.parse_optional_key()?;
let exposure = self.parse_optional_element_exposure()?;
Ok(VertexTableDefinition {
table,
alias,
key,
exposure,
span: Span::new(start, self.previous_end()),
})
}
pub(super) fn parse_edge_table_definition(
&mut self,
) -> Result<EdgeTableDefinition, SyntaxError> {
let start = self.current().span.start;
let table = self.parse_qualified_name()?;
let alias = self.parse_optional_as_alias()?;
let key = self.parse_optional_key()?;
self.expect_keyword("SOURCE")?;
let source = self.parse_edge_endpoint()?;
self.expect_keyword("DESTINATION")?;
let destination = self.parse_edge_endpoint()?;
let exposure = self.parse_optional_element_exposure()?;
Ok(EdgeTableDefinition {
table,
alias,
key,
source,
destination,
exposure,
span: Span::new(start, self.previous_end()),
})
}
fn parse_edge_endpoint(&mut self) -> Result<EdgeEndpoint, SyntaxError> {
let start = self.current().span.start;
if self.consume_keyword("KEY") {
let key = self.parse_identifier_list()?;
self.expect_keyword("REFERENCES")?;
let vertex = self.parse_identifier()?;
let vertex_key = self.parse_identifier_list()?;
Ok(EdgeEndpoint {
key,
vertex,
vertex_key,
span: Span::new(start, self.previous_end()),
})
} else {
let vertex = self.parse_identifier()?;
Ok(EdgeEndpoint {
key: Vec::new(),
vertex,
vertex_key: Vec::new(),
span: Span::new(start, self.previous_end()),
})
}
}
fn parse_optional_as_alias(&mut self) -> Result<Option<Identifier>, SyntaxError> {
if self.consume_keyword("AS") {
self.parse_identifier().map(Some)
} else {
Ok(None)
}
}
fn parse_optional_key(&mut self) -> Result<Vec<Identifier>, SyntaxError> {
if self.consume_keyword("KEY") {
self.parse_identifier_list()
} else {
Ok(Vec::new())
}
}
fn parse_optional_element_exposure(&mut self) -> Result<Option<ElementExposure>, SyntaxError> {
if matches!(
self.current().kind,
TokenKind::Comma | TokenKind::RightParen
) {
return Ok(None);
}
if !["NO", "PROPERTIES", "LABEL", "DEFAULT"]
.into_iter()
.any(|keyword| self.at_keyword(keyword))
{
return Err(self.unexpected("LABEL, DEFAULT LABEL, PROPERTIES, or NO PROPERTIES"));
}
let start = self.current().span.start;
let mut labels = Vec::new();
if self.at_keyword("NO") || self.at_keyword("PROPERTIES") {
let properties = self.parse_property_exposure()?;
labels.push(ElementLabelExposure {
label: ElementLabel::Implicit,
properties,
span: Span::new(start, self.previous_end()),
});
} else {
while self.at_keyword("LABEL") || self.at_keyword("DEFAULT") {
let label_start = self.current().span.start;
let label = if self.consume_keyword("LABEL") {
ElementLabel::Named(self.parse_identifier()?)
} else {
self.expect_keyword("DEFAULT")?;
self.expect_keyword("LABEL")?;
ElementLabel::Default
};
let properties = if self.at_keyword("NO") || self.at_keyword("PROPERTIES") {
self.parse_property_exposure()?
} else {
PropertyExposure::AllColumns
};
labels.push(ElementLabelExposure {
label,
properties,
span: Span::new(label_start, self.previous_end()),
});
}
}
Ok(Some(ElementExposure {
labels,
span: Span::new(start, self.previous_end()),
}))
}
fn parse_property_exposure(&mut self) -> Result<PropertyExposure, SyntaxError> {
if self.consume_keyword("NO") {
self.expect_keyword("PROPERTIES")?;
return Ok(PropertyExposure::NoProperties);
}
self.expect_keyword("PROPERTIES")?;
if self.consume_keyword("ALL") {
self.expect_keyword("COLUMNS")?;
return Ok(PropertyExposure::AllColumns);
}
self.expect_kind(TokenKind::LeftParen, "(")?;
let expressions = self.parse_labeled_expressions("at least one property expression")?;
self.expect_kind(TokenKind::RightParen, ")")?;
Ok(PropertyExposure::Expressions(expressions))
}
}