/// A whitespace character, which can be a space or a tab
WHITESPACE = { " " | "\t" }
/// One or more whitespace characters
SPACE = { WHITESPACE+ }
/// A list of one or more products, separated by either a newline or space
products = {(product ~ (NEWLINE | SPACE))*}
/// A single product entry, which consists of various fields like product name, skin type, ingredients, etc
product = { product_name ~ skin_type ~ ingredients ~ rating ~ price ~ user_ratings ~ recommendations ~ reviews ~ availability }
/// The rating of a product, denoted by the "*Rating*:" label, followed by an optional space, a number, and a newline
rating = { "*Rating*:" ~ SPACE? ~ number ~ NEWLINE }
/// The availability of a product, denoted by the "*Availability*:" label, followed by an optional space and a boolean value (true/false)
availability = { "*Availability*:" ~ SPACE? ~ boolean ~ NEWLINE }
/// The price of a product, denoted by the "*Price*:" label, followed by an optional space, a number, an optional space, an optional currency, and a newline
price = { "*Price*:" ~ SPACE? ~ number ~ SPACE? ~ currency? ~ NEWLINE }
/// The user ratings of a product, denoted by the "*User Ratings*:" label, followed by a list of numbers and a newline
user_ratings = { "*User Ratings*:" ~ SPACE? ~ number_list ~ NEWLINE }
/// The product name, denoted by the "*Product" label, followed by a number (product identifier), a colon, and the product name text
product_name = { "*Product " ~ (ASCII_DIGIT+) ~ "*:" ~ any_text }
/// Recommendations for the product, denoted by the "*Recommendations*:" label followed by any text describing the recommendations
recommendations = { "*Recommendations*:" ~ any_text }
/// Ingredients of the product, denoted by the "*Ingredients*:" label followed by any text describing the ingredients
ingredients = { "*Ingredients*:" ~ any_text }
/// Reviews of the product, denoted by the "*Reviews*:" label followed by optional space and one or more reviews
reviews = { "*Reviews*:" ~ SPACE? ~ (review)* }
/// The skin type of the product, denoted by the "*Skin Type*:" label followed by text describing the skin type
skin_type = { "*Skin Type*:" ~ any_text }
/// A number, which can be an integer or a floating-point number, optionally starting with a negative sign
number = { ("-"? ~ ASCII_DIGIT+) ~ (("." ~ ASCII_DIGIT+)?) }
/// A list of numbers enclosed in square brackets, separated by commas
number_list = { "[" ~ number ~ ("," ~ SPACE? ~ number)* ~ "]" }
/// A product review, which consists of a number (rating) followed by a period and some text
review = { NEWLINE? ~ number ~ "." ~ any_text }
/// A currency symbol, which can be "UAH", "EUR", or "USD"
currency = { "UAH" | "EUR" | "USD" }
/// Any text, which can be any sequence of characters (except newline), optionally preceded by whitespace
any_text = { SPACE? ~ (!NEWLINE ~ ANY)+ ~ NEWLINE }
/// A boolean value, which can be either "true" or "false"
boolean = { ("true" | "false") }