The Dicenomicon 2.1 Roll Formula Language

Below are a series of production rules defining the formal grammar for the roll formula language. Note that there are a number of semantic issues that aren't defined in the grammar, but some of them are covered with footnotes. The grammar is also not completely unambiguous, though operator precedence resolves most of those ambiguities.

roll::=condition [(,|.) condtion] *

condition::=assignment
|if expr then expr [elif expr then expr]* else expr end
|expr

assignment::=@(number | ident) ← expr
|parameter ← expr1

expr::=expr expr
|expr expr
|expr < expr
|expr expr
|expr = expr
|expr expr
|expr expr
|expr > expr
|expr in expr
|expr expr
|expr + expr
|expr - expr
|expr × expr
|expr % expr
|expr / expr
|expr ÷ expr
|expr /+ expr
|expr [roll]
|function-call
|string
|variable
|die-spec
|(roll)

function-call::=function-name[number](( roll [, roll]*))

variable::=@(number | ident)
|parameter
|special-constant

parameter::=#number

die-spec::=die-count [color] (d|z) die-sides [ open ][ roll-macro ][ reducer ]
|die-count [color] ttext-die-name

die-count::=number [½]
|½
|parameter
|ε2

color::=R|G|B|C|M|Y|K|W|A|O|N

die-sides::=number
|%||
|0000|000|00|0
|6a|F
|custom-die-name
|parameter
|ε3

open::=|.+|.-|±|+|-|*

roll-macro::=macro-name [ number | parameter ]

reducer::=vs [ number | parameter ]
|(high|hi|h) [ number | parameter ]
|(low|lo|l) [ number | parameter ]
|# [ number | parameter ]
| [ number | parameter ]
|> [ number | parameter ]
|= [ number | parameter ]
| [ number | parameter ]
| [ number | parameter ]
|< [ number | parameter ]
|@

Footnotes:

  1. Expression must be composed of constant, global, or parameter values only
  2. If no number is specified for a die-count, it is assumed to be 1
  3. The number of sides can be omitted only if a roll macro is specified (in which case it uses the default number of sides specified in that macro)

Operator Precedence
∧, ∨
<, ≤, =, ≠, ≥, >, in
+, -
×, %, /, ÷, /+

Note that die-spec binds tighter than operators such as <, so:

3d10>8
is not the same as
(3d10) > 8
The former counts how many dice are greater than 8, the totals up the dice and sees if that sum is greater than 8