Formal Recipe Description Language GrammarΒΆ

The following peggie PEG grammar formally defines the Recipe Grid recipe description language.

Note

A still detailed, though less formal, description of the recipe description language is available in the Recipe Description Language Reference.

For a higher-level introduction, see the Recipe Grid Tutorial.

# Starting point for grammar; a series of statements.
recipe <- sp? stmt+ eof

# A statement (e.g. "100g cheese" or "sauce = boil(tomatoes, onion, spices)")
stmt <- (output_list hsp? r":?=" hsp?)? ltr_shorthand eol

output_list <- output (hsp? "," hsp? output)*
output <- string

expr <- step / reference / "(" sp? ltr_shorthand sp? ")"

# Left-to-right shorthand (e.g. "1kg potatoes, peeled, cubed")
ltr_shorthand <- expr (hsp? "," hsp? action)*

# Steps (e.g. "boil(tomatoes, spices)")
step <- action
        hsp? "(" sp?
            expr
            (sp? "," sp? expr)*
            (sp? ",")?
        sp? ")"
action <- string

# References (e.g. "cheese", "1/2 of white sauce", "remaining pastry")
reference <- ((proportion / explicit_quantity / implicit_quantity) hsp?)?
             ingredient
ingredient <- string

# Quantities
implicit_quantity <- number (hsp? known_unit (hsp preposition)?)? 
explicit_quantity <- "{" hsp?
                     number (hsp? freeform_unit)?
                     hsp?  "}"
                     (hsp preposition)?

# Proportions (e.g. "remaining" or "1/3 of" or "0.3 *")
proportion    <- remainder (hsp preposition)?
               / number ( hsp preposition
                        / hsp? "%" (hsp preposition)?
                        / hsp? "*")
remainder     <- r"(?i)(remaining|remainder|rest|left[ \t]*over)\\b"

# A preposition which might follow an ingredient/quantity
preposition <- r"(?i)of([ \t]+the)?\\b"

# Units (n.b. @KNOWN_UNITS@ is substituted for a regex matching all units
# supported by this software).
known_unit    <- r"(?i)(@KNOWN_UNITS@)\\b"
freeform_unit <- static_string

# Strings
string        <- (naked_string / s_quoted_string / d_quoted_string / bracketed_string)
                 (hsp? string)?
static_string <- (naked_string / s_quoted_string / d_quoted_string)
                 (hsp? static_string)?

naked_string     <- r"[^\"',:=/(){}\s]([^\"',:=/(){}\n\r]*[^\"',:=/(){}\s])?"
d_quoted_string  <- '"' ("\\" . / r'[^"\n\r]')* '"'
s_quoted_string  <- "'" ("\\" . / r"[^'\n\r]")* "'"
bracketed_string <- "{" (interpolated_number / "\\" . / r"[^0-9{}\n\r]")* "}"
interpolated_number <- number

# Numbers
number   <- fraction / decimal
fraction <- (r"[0-9]+" hsp)? r"[0-9]+" hsp? "/" hsp? r"[0-9]+"
decimal  <- r"[0-9]+(\.[0-9]*)?"

# Whitespace
sp <- r"\s+"
hsp <- r"[ \t]+"
eol <- r"[ \t]*[\r\n]\s*" / r"[ \t]*" eof
eof <- !.

In the grammar above, the string @KNOWN_UNITS@ is substituted for a regular expression which matches the following strings (with spaces here matching any quantity of whitespace):

bag, bags, box, boxen, boxes, bulb, bulbs, can, cans, clove, cloves, cup, cups, g, gram, grams, kg, kilo, kilogram, kilograms, kilos, knob, knobs, l, lb, lbs, litre, mill, milliliter, milliliters, mills, ml, ounce, ounces, oz, ozs, pack, packet, packets, packs, pinch, pinches, pint, pints, pound, pounds, rasher, rashers, sachet, sachets, sack, sacks, strip, strips, table spoon, table spoons, tablespoon, tablespoons, tbsp, tbsps, tea spoon, tea spoons, teaspoon, teaspoons, tin, tins, tsp, tsps

Note

The above grammar is not able to distinguish between references and ingredients and so is written as if only references exist. The Recipe Grid compiler resolves this distinction in a later compilation stage.