use std::sync::{Arc, LazyLock};
use lalrpop_util::lalrpop_mod;
use miette::Diagnostic;
use thiserror::Error;
use super::{
ast::Schema,
err::{self, ParseError, ParseErrors, SchemaWarning, ToJsonSchemaErrors},
to_json_schema::cedar_schema_to_json_schema,
};
use crate::extensions::Extensions;
use crate::validator::json_schema;
lalrpop_mod!(
#[allow(warnings, unused, missing_docs, missing_debug_implementations)]
#[allow(clippy::unwrap_used, reason = "lalrpop uses unwraps, and we are trusting lalrpop to generate correct code")]
#[allow(clippy::indexing_slicing, reason = "lalrpop uses slicing, and we are trusting lalrpop to generate correct code")]
#[allow(clippy::string_slice, reason = "lalrpop uses slicing, and we are trusting lalrpop to generate correct code")]
#[allow(clippy::unreachable, reason = "lalrpop uses unreachable, and we are trusting lalrpop to generate correct code")]
#[allow(clippy::panic, reason = "lalrpop uses panic, and we are trusting lalrpop to generate correct code")]
#[allow(clippy::allow_attributes, reason = "lalrpop allows this, and we are trusting lalrpop to generate correct code")]
#[allow(clippy::allow_attributes_without_reason, reason = "lalrpop allows this, and we are trusting lalrpop to generate correct code")]
pub grammar,
"/src/validator/cedar_schema/grammar.rs"
);
fn parse_collect_errors<'a, P, T>(
parser: &P,
parse: impl FnOnce(
&P,
&mut Vec<err::RawErrorRecovery<'a>>,
&Arc<str>,
bool,
&'a str,
) -> Result<T, err::RawParseError<'a>>,
text: &'a str,
) -> Result<T, err::ParseErrors> {
let mut errs = Vec::new();
let result = parse(parser, &mut errs, &Arc::from(text), true, text);
let errors = errs
.into_iter()
.map(|rc| ParseError::from_raw_error_recovery(rc, Arc::from(text)))
.collect::<Vec<ParseError>>();
let parsed = match result {
Ok(parsed) => parsed,
Err(e) => {
return Err(ParseErrors::new(
ParseError::from_raw_parse_error(e, Arc::from(text)),
errors,
));
}
};
match ParseErrors::from_iter(errors) {
Some(errors) => Err(errors),
None => Ok(parsed),
}
}
static SCHEMA_PARSER: LazyLock<grammar::SchemaParser> = LazyLock::new(grammar::SchemaParser::new);
#[derive(Debug, Diagnostic, Error)]
#[non_exhaustive]
pub enum CedarSchemaParseErrors {
#[error(transparent)]
#[diagnostic(transparent)]
SyntaxError(#[from] err::ParseErrors),
#[error(transparent)]
#[diagnostic(transparent)]
JsonError(#[from] ToJsonSchemaErrors),
}
pub fn parse_cedar_schema_fragment<'a>(
src: &str,
extensions: &Extensions<'a>,
) -> Result<
(
json_schema::Fragment<crate::validator::RawName>,
impl Iterator<Item = SchemaWarning> + 'a,
),
CedarSchemaParseErrors,
> {
let ast: Schema = parse_collect_errors(&*SCHEMA_PARSER, grammar::SchemaParser::parse, src)?;
let tuple = cedar_schema_to_json_schema(ast, extensions)?;
Ok(tuple)
}
pub fn parse_schema(text: &str) -> Result<Schema, err::ParseErrors> {
parse_collect_errors(&*SCHEMA_PARSER, grammar::SchemaParser::parse, text)
}