Epsilon

The Epsilon (epsilon_p and eps_p) is a multi-purpose parser that returns a zero length match.

Simple Form

In its simplest form, epsilon_p matches the null string and always returns a match of zero length:

    epsilon_p // always returns a zero-length match

This form is usually used to trigger a semantic action unconditionally. For example, it is useful in triggering error messages when a set of alternatives fail:

    r = A | B | C | eps_p[error]; // error if A, B, or C fails to match

Semantic Predicate

Semantic predicates allow you to attach a function anywhere in the grammar. In this role, the epsilon takes a 0-ary (nullary) function/functor. The run-time function/functor is typically a test that is called upon to resolve ambiguity in the grammar. A parse failure will be reported when the function/functor result evaluates to false. Otherwise an empty match will be reported. The general form is:

    eps_p(f) >> rest;

The nullary function f is called to do a semantic test (say, checking if a symbol is in the symbol table). If test returns true, rest will be evaluated. Otherwise, the production will return early with a no-match without ever touching rest.

Syntactic Predicate

Similar to Semantic predicates, Syntactic predicates assert a certain conditional syntax to be satisfied before evaluating another production. This time, epsilon_p accepts a (conditional) parser. The general form is:

    eps_p(p) >> rest;

If p is matched on the input stream then attempt to recognize rest. The parser p is called to do a syntax check. Regardless of p's success, eps_p(p) will always return a zero length match (i.e. the input is not consumed). If test returns true, rest will be evaluated. Otherwise, the production will return early with a no-match without ever touching rest.

Example:

    eps_p('0') >> oct_p // note that '0' is actually a ch_p('0') 

Epsilon here is used as a syntactic predicate. oct_p (see numerics) is parsed only if we see a leading '0'. Wrapping the leading '0' inside an epsilon makes the parser not consume anything from the input. If a '0' is seen, epsilon_p reports a successful match with zero length.

Primitive arguments

Epsilon allows primitive type arguments such as char, int, wchar_t, char const*, wchar_t const* and so on. Examples:

eps_p("hello") // same as eps_p(str_p("hello"))
eps_p
('x') // same as eps_p(ch_p('x'))

Inhibiting Semantic Actions

In a syntactic predicate eps_p(p), any semantic action directly or indirectly attached to the conditional parser p will not be called. However, semantic actions attached to epsilon itself will always be called. The following code snippets illustrates the behavior:

    eps_p(c[f])  // f not called
eps_p(c)[f] // f is called
eps_p[f] // f is called

Actually, the conditional parser p is implicitly wrapped in a no_actions_d directive:

    no_actions_d[p]

The conditional parser is required to be free from side-effects (semantic actions). The conditional parser's purpose is to resolve ambiguity by looking ahead in the input stream for a certain pattern. Ambiguity and semantic actions do not mix well. On an ambiguous grammar, backtracking happens. And when it happens, we cannot undo the effects of triggered semantic actions.

Negation

Operator ~ is defined for parsers constructed by epsilon_p/eps_p. It performs negation by complementing the results reported. ~~eps_p(x) is identical to eps_p(x).