Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Syntax

This page lists the rules of the format. For examples, see Diary Format.

Lines

  • Files are UTF-8 text.
  • Windows line endings work. Chow writes Unix line endings.
  • Whitespace is spaces or tabs.
  • ; starts a comment that runs to the end of the line.
  • Blank lines are ignored.
  • Servings, recipe lines, and the lines of a day are indented. A continued nutrient list is indented further. Everything else starts in the first column.
  • A serving or unit can contain spaces. It ends at =, at x, or at the end of the line.

Grammar

The grammar is in EBNF. ws is one or more spaces or tabs.

diary        = [ marker ] { line } ;
marker       = "format" ws "2" [ trail ] newline ;   (* the root file only *)
line         = blank | comment | include | food_block | recipe_block
             | container | target | timed | day_block ;

comment      = ws? ";" text newline ;
include      = "include" ws path [ trail ] newline ;

food_block   = food_header serving_line { serving_line } ;   (* at least one serving *)
food_header  = "food" ws handle ws name [ ws ";" ws tags ] newline ;
serving_line = ws serving ws "=" [ ws nutrients ] [ trail ] newline
               { continuation } ;
continuation = deeper nutrients [ trail ] newline ;          (* no "=" *)

recipe_block = date ws "recipe" ws handle ws name [ trail ] newline
               { recipe_line } ;                             (* at least one ingredient *)
recipe_line  = ws ( "container" ws container_id
                  | "weight" ws number ws weight_unit
                  | "servings" ws number
                  | handle ws portion ) [ trail ] newline ;
container    = "container" ws container_id ws name ws number ws weight_unit
               [ trail ] newline ;

target       = date ws "target" ws nutrients [ trail ] newline
               { continuation } ;

timed        = date ws record ;
day_block    = date [ trail ] newline { ws record } ;        (* a date alone on its line *)
record       = time ws ( entry | inline | burn | reading ) ;
entry        = handle ws portion [ trail ] newline ;
inline       = name ws serving ws "=" [ ws nutrients ] [ trail ] newline
               { continuation } ;
burn         = "burn" ws number ws "kcal" ws name [ trail ] newline ;
reading      = "metric" ws metric_id ws number ws metric_unit [ trail ] newline ;

portion      = number ws "x" ws serving                     (* 2 x 170 g *)
             | serving ;                                    (* 340 g, 1 tsp *)
serving      = number ws unit ;                             (* "170 g", "1 medium onion" *)
unit         = word { ws word } ;

handle       = idchar { idchar } ;                          (* not a keyword *)
container_id = idchar { idchar } ;
metric_id    = idchar { idchar } ;
idchar       = letter | digit | "_" | "-" ;                 (* ASCII *)
metric_unit  = char { char } ;                              (* no whitespace *)
weight_unit  = unit ;                                       (* one that folds to g, kg, mg, oz or lb *)

name         = '"' { char - '"' } '"' ;
tags         = tag { ws tag } ;
tag          = key ":" ( bareword | '"' { char - '"' } '"' ) ;

nutrients    = nutrient { ws nutrient } ;
nutrient     = ( number | number "%" ) ws nutrient_id ;     (* "150 kcal", "15% iron" *)
nutrient_id  = idchar { idchar } ;

date         = digit digit digit digit "-" digit digit "-" digit digit ;
time         = digit digit ":" digit digit ;                (* 24-hour, HH:MM, local *)
number       = digit { digit } [ "." digit { digit } ] ;    (* never negative *)
trail        = ws? ";" text ;

Errors

Chow rejects a diary with any of these, and reports the file and line:

  • A line that matches no record
  • A date that isn’t on the calendar, or a time outside 00:00 to 23:59
  • A number, portion, or serving it can’t read
  • An unknown nutrient id, or a percentage of a nutrient with no daily value
  • A basis other than fda2016 or rdi1993
  • A burn in a unit other than kcal
  • An unknown metric, or a unit the metric doesn’t accept
  • A serving outside a food, or a food with no serving
  • A reserved word as a handle
  • An inline entry with x
  • A format line anywhere but the top of main.chow
  • Two foods or recipes with the same handle
  • Two servings of one food that are the same
  • Two containers with the same id, or two targets on the same date
  • An include that loops back to its own file, or names a file Chow can’t read
  • A recipe with no ingredient, a repeated container, weight, or servings line, a container without weight, or a weight not in a weight unit
  • A servings count or weight that isn’t above zero

An entry with an unknown handle or a portion that doesn’t match is not an error. It is unresolved.