use crate::common::{FileId, Ignored, Span};
use crate::parser::error::{ParseError, grammar_bug};
use crate::parser::{Lexeme, Rule, span_of};
use pest::iterators::Pair;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct InputDirective {
relation_name: String,
parameters: HashMap<String, String>,
span: Ignored<Span>,
}
impl InputDirective {
pub(crate) fn new(
relation_name: String,
parameters: HashMap<String, String>,
span: Span,
) -> Self {
Self {
relation_name,
parameters,
span: Ignored(span),
}
}
#[must_use]
pub(crate) fn relation_name(&self) -> &str {
&self.relation_name
}
#[must_use]
pub(crate) fn parameters(&self) -> &HashMap<String, String> {
&self.parameters
}
#[must_use]
#[inline]
pub(crate) fn span(&self) -> Span {
self.span.0
}
}
fn parse_io_directive(
parsed_rule: Pair<Rule>,
file: FileId,
missing_name_msg: &'static str,
) -> Result<(String, HashMap<String, String>, Span), ParseError> {
let mut inner = parsed_rule.into_inner();
let name_pair = inner.next().ok_or_else(|| grammar_bug(missing_name_msg))?;
let span = span_of(&name_pair, file);
let relation_name = name_pair.as_str().to_lowercase();
let parameters = parse_io_params(inner)?;
Ok((relation_name, parameters, span))
}
fn parse_io_params<'i>(
inner: impl Iterator<Item = pest::iterators::Pair<'i, Rule>>,
) -> Result<HashMap<String, String>, ParseError> {
let mut parameters = HashMap::new();
for node in inner {
if node.as_rule() == Rule::io_params {
parameters = parse_io_params_node(node)?;
}
}
Ok(parameters)
}
pub(super) fn parse_io_params_node(
node: Pair<Rule>,
) -> Result<HashMap<String, String>, ParseError> {
debug_assert_eq!(node.as_rule(), Rule::io_params);
let mut parameters = HashMap::new();
for io_param in node.into_inner() {
let mut kv = io_param.into_inner();
let key = kv
.next()
.ok_or_else(|| grammar_bug("io parameter missing name"))?
.as_str()
.to_string();
let value = kv
.next()
.ok_or_else(|| grammar_bug("io parameter missing value"))?
.as_str()
.trim_matches('"')
.to_string();
parameters.insert(key, value);
}
Ok(parameters)
}
impl Lexeme for InputDirective {
fn from_parsed_rule(parsed_rule: Pair<Rule>, file: FileId) -> Result<Self, ParseError> {
let (relation_name, parameters, span) =
parse_io_directive(parsed_rule, file, "input directive missing relation name")?;
Ok(Self {
relation_name,
parameters,
span: Ignored(span),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct OutputDirective {
relation_name: String,
parameters: HashMap<String, String>,
span: Ignored<Span>,
}
impl OutputDirective {
pub(crate) fn new(
relation_name: String,
parameters: HashMap<String, String>,
span: Span,
) -> Self {
Self {
relation_name,
parameters,
span: Ignored(span),
}
}
#[must_use]
pub(crate) fn relation_name(&self) -> &str {
&self.relation_name
}
#[must_use]
pub(crate) fn parameters(&self) -> &HashMap<String, String> {
&self.parameters
}
#[must_use]
#[inline]
pub(crate) fn span(&self) -> Span {
self.span.0
}
}
impl Lexeme for OutputDirective {
fn from_parsed_rule(parsed_rule: Pair<Rule>, file: FileId) -> Result<Self, ParseError> {
let (relation_name, parameters, span) =
parse_io_directive(parsed_rule, file, "output directive missing relation name")?;
Ok(Self {
relation_name,
parameters,
span: Ignored(span),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct PrintSizeDirective {
relation_name: String,
span: Ignored<Span>,
}
impl PrintSizeDirective {
pub(crate) fn new(relation_name: String, span: Span) -> Self {
Self {
relation_name,
span: Ignored(span),
}
}
#[must_use]
pub(crate) fn relation_name(&self) -> &str {
&self.relation_name
}
#[must_use]
#[inline]
pub(crate) fn span(&self) -> Span {
self.span.0
}
}
impl Lexeme for PrintSizeDirective {
fn from_parsed_rule(parsed_rule: Pair<Rule>, file: FileId) -> Result<Self, ParseError> {
let mut inner = parsed_rule.into_inner();
let name_pair = inner
.next()
.ok_or_else(|| grammar_bug("printsize directive missing relation name"))?;
let span = span_of(&name_pair, file);
let relation_name = name_pair.as_str().to_lowercase();
Ok(Self {
relation_name,
span: Ignored(span),
})
}
}