#![warn(rustdoc::broken_intra_doc_links, clippy::doc_markdown)]
#[cfg(doc)]
pub mod _extensions {
#![doc = include_str!("../extensions.md")]
}
#[cfg(doc)]
pub mod _features {
}
#[cfg(feature = "aisle")]
pub mod aisle;
pub mod analysis;
pub mod ast;
pub mod convert;
pub mod error;
pub mod ingredient_list;
pub mod located;
pub mod metadata;
pub mod model;
#[cfg(feature = "pantry")]
pub mod pantry;
pub mod parser;
pub mod quantity;
pub mod scale;
#[cfg(feature = "shopping_list")]
pub mod shopping_list;
pub mod span;
pub mod text;
mod lexer;
use bitflags::bitflags;
use serde::{Deserialize, Serialize};
use error::PassResult;
pub use analysis::ParseOptions;
pub use convert::Converter;
pub use located::Located;
pub use metadata::Metadata;
pub use model::*;
pub use parser::Modifiers;
pub use quantity::{GroupedQuantity, Quantity, Value};
pub use span::Span;
pub use text::Text;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Extensions: u32 {
const COMPONENT_MODIFIERS = 1 << 1;
const COMPONENT_ALIAS = 1 << 3;
const ADVANCED_UNITS = 1 << 5;
const MODES = 1 << 6;
const INLINE_QUANTITIES = 1 << 7;
const RANGE_VALUES = 1 << 9;
const TIMER_REQUIRES_TIME = 1 << 10;
const INTERMEDIATE_PREPARATIONS = 1 << 11 | Self::COMPONENT_MODIFIERS.bits();
const COMPAT = Self::COMPONENT_MODIFIERS.bits()
| Self::COMPONENT_ALIAS.bits()
| Self::ADVANCED_UNITS.bits()
| Self::MODES.bits()
| Self::INLINE_QUANTITIES.bits()
| Self::RANGE_VALUES.bits()
| Self::INTERMEDIATE_PREPARATIONS.bits();
}
}
impl Default for Extensions {
fn default() -> Self {
Self::all()
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct CooklangParser {
extensions: Extensions,
converter: Converter,
}
pub type RecipeResult = PassResult<Recipe>;
pub type MetadataResult = PassResult<Metadata>;
impl CooklangParser {
pub fn new(extensions: Extensions, converter: Converter) -> Self {
Self {
extensions,
converter,
}
}
#[cfg(feature = "bundled_units")]
pub fn extended() -> Self {
Self::new(Extensions::all(), Converter::bundled())
}
pub fn canonical() -> Self {
Self::new(Extensions::empty(), Converter::empty())
}
pub fn converter(&self) -> &Converter {
&self.converter
}
pub fn extensions(&self) -> Extensions {
self.extensions
}
pub fn parse(&self, input: &str) -> RecipeResult {
self.parse_with_options(input, ParseOptions::default())
}
#[tracing::instrument(level = "debug", name = "parse", skip_all, fields(len = input.len()))]
pub fn parse_with_options(&self, input: &str, options: ParseOptions) -> RecipeResult {
let mut parser = parser::PullParser::new(input, self.extensions);
analysis::parse_events(
&mut parser,
input,
self.extensions,
&self.converter,
options,
)
}
pub fn parse_metadata(&self, input: &str) -> MetadataResult {
self.parse_metadata_with_options(input, ParseOptions::default())
}
#[tracing::instrument(level = "debug", name = "metadata", skip_all, fields(len = input.len()))]
pub fn parse_metadata_with_options(
&self,
input: &str,
options: ParseOptions,
) -> MetadataResult {
let parser = parser::PullParser::new(input, self.extensions);
let meta_events = parser.into_meta_iter();
analysis::parse_events(
meta_events,
input,
self.extensions,
&self.converter,
options,
)
.map(|c| c.metadata)
}
}
pub fn parse(input: &str) -> RecipeResult {
CooklangParser::default().parse(input)
}