# Control Hooks

Beyond the top-level grammar rule, which *has* to be supplied to a parsing run, and an action class template, which *can* be supplied to a parsing run, a third customisation point within the PEGTL allows the user to provide a *control* class (template) to a parsing run.

The control class must implement a set of static hook functions that are called by the PEGTL in order to

1. customise which exceptions are thrown in case of errors, and

2. add custom debug logging to follow the details of a parsing run.

## Contents

* [Normal Control](#normal-control)
* [Debug Functions](#debug-functions)
* [Exception Throwing](#exception-throwing)
* [Debugging and Tracing](#debugging-and-tracing)
* [Advanced Control](#advanced-control)
* [Changing Control](#changing-control)

## Normal Control

The `normal` control class template included with the PEGTL is used by default and shows which hook functions there are.

```c++
template< typename Rule >
struct normal
{
   template< typename Input, typename ... States >
   static void start( const Input &, States && ... )
   { }

   template< typename Input, typename ... States >
   static void success( const Input &, States && ... )
   { }

   template< typename Input, typename ... States >
   static void failure( const Input &, States && ... )
   { }

   template< typename Input, typename ... States >
   static void raise( const Input & in, States && ... )
   {
      throw parse_error( "parse error matching " +
                         internal::demangle< Rule >(), in );
   }

   template< apply_mode A,
             template< typename ... > class Action,
             template< typename ... > class Control,
             typename Input,
             typename ... States >
   static bool match( Input & in, States && ... st )
   {
      return internal::rule_match_one< Rule,
                                       A,
                                       Action,
                                       Control >( in, st ... );
   }
};
```

All control functions are called with the current input and all additional state arguments.

## Debug Functions

Before attempting to match a rule `R`, the PEGTL calls `C< R >::start()` where `C` is the current control class template.

Depending on what happens during the attempt to match `R`, one of the other three functions might be called.

- If `R` succeeds, then `C< R >::success()` is called; compared to the call to `C< R >::start()`, the input will have consumed whatever the successful match of `R` consumed.

- If `R` finishes with a failure, i.e. a return value of `false` from its `match()`-function, then `C< R >::failure()` is called; a failed match is not allowed to consume input.

- If `R` is wrapped in `must< R >`, a global failure is generated by calling `C< R >::raise()` to throw some exception as is expected by the PEGTL in this case.

- If a sub-rule of `R` finishes with a global failure, and the exception is not caught by a `try_catch` or similar combinator, then no other function of `C< R >` is called after `C< R >::start()`.

## Exception Throwing

The `raise()`-control-hook-function *must* throw an exception.
For most parts of the PEGTL the exception class is irrelevant and any user-defined data type can be thrown by a user-defined control hook.

The `try_catch` rule only catches exceptions of type `pegtl::parse_error`!

When custom exception types are used then `try_catch_type` must be used with the custom exception class that they are supposed to catch as first template argument.

## Debugging and Tracing

For debugging a grammar and tracing exactly what happens during a parsing run, the control class methods `start()`, `success()` and `failure()` can be used.
A minimal example of how this can be done is included with the PEGTL in the `pegtl/trace.hh` header file.

```c++
template< typename Rule >
struct tracer
      : normal< Rule >
{
   template< typename Input, typename ... States >
   static void start( const Input & in, States && ... )
   {
      std::cerr << position_info( in )
                << "  start  "
                << internal::demangle< Rule >()
                << std::endl;
   }

   template< typename Input, typename ... States >
   static void success( const Input & in, States && ... )
   {
      std::cerr << position_info( in )
                << " success "
                << internal::demangle< Rule >()
                << std::endl;
   }

   template< typename Input, typename ... States >
   static void failure( const Input & in, States && ... st )
   {
      std::cerr << position_info( in )
                << " failure "
                << internal::demangle< Rule >()
                << std::endl;
   }
};
```

## Advanced Control

The control template's `match()`-function is the first or outside-most function that is called in the flow that eventually leads to calling a rule's `match()`-function.

The normal implementation simply forwards all template parameters and function arguments unchanged.

For advanced use cases it is however possible to create a custom control class with a custom `match()`-function that can change "everything" before forwarding as needed.

## Changing Control

Just like the action class template, a custom control class template can be used by either

1. supplying it as explicit template argument to the `parse()`-functions, or

2. setting it for a portion of the grammar with the `pegtl::control` combinator.

Copyright (c) 2014-2016 Dr. Colin Hirsch and Daniel Frey
