%token BAGS %token CONTAIN %token NO %token OTHER %token COMMA "," %token DOT "." %token EOF %token NUMBER %token WORD %start rules %% let rules := ~ = list(rule); EOF; <> let rule := ~ = bag; CONTAIN; ~ = contents; DOT; <> let contents := | NO; OTHER; BAGS; { [] } | ~ = separated_nonempty_list(COMMA, number_bag); <> let number_bag := n = NUMBER; b = bag; { b, n } let bag := words = list(WORD); BAGS; { String.concat " " words }