pacc logo

Types

Every pacc rule has a type, which can be almost any C type. The type of a rule appears in its definition, directly after the name introduced by ::. (In many ways, I would have preferred to prefix types to names like C itself, but then we'd have to terminate rules, say with semi-colons, and that appealed even less.)

The rules for types are as follows.

  1. If a rule has an explicit type, that is its type; othewise
  2. the rule has the same type as the previous rule; unless
  3. it is the first rule, in which case the default type is int.
  4. Every path through a rule must include exactly one expression with the type of the rule; unless
  5. the type of the rule is void, in which case no expressions are allowed.

Rule 3 explains how we have got away so far without explicit type declarations—in their absence, everything defaults to int. Let's revisit our example again, here's french2.pacc

Start ← Yes → 1 / No → 0
Yes :: void ← "yes" / "oui"
No ← "non" / "no"

The first rule Start has type int, this time we've made that explicit. The second rule Yes has type void, again by explicit declaration. The third rule No has no explicit type, so by rule 2 its type is void.

Warning

The type of an implicitly-typed rule depends on where it is in the grammar! Rearranging rules can change the meaning of a grammar!

Arguably this is unfortunate (perhaps there should be a strict mode where every rule must have an explicit type?) but in practice most pacc grammars have only a few different types, so implicit typing saves a lot of, errm, typing.

Any C type that can be constructed with words and the * character can be used as a pacc type. This includes pointers, structures, and unions, but not vectors (arrays) or function types. You could use a typedef for those if you really wanted to, and include it (directly or more likely by #include) in the pacc preamble.