Refactoring Parsers

There are three types of Refactoring Parsers implemented right now, which help to abstract common parser refactoring tasks. Parser refactoring means, that a concrete parser construct is replaced (refactored) by another very similar parser construct. Two of the Refactoring Parsers described here (refactor_unary_parser and refactor_action_parser) are introduced to allow a simple and more expressive notation while using Confix Parsers and List Parsers. The third Refactoring Parser (attach_action_parser) is implemented to abstract some functionality required for the Grouping Parser. Nevertheless these Refactoring Parsers may help in solving other complex parsing tasks too.

Refactoring unary parsers

The refactor_unary_d parser generator, which should be used to generate a unary refactoring parser, transforms a construct of the following type

    refactor_unary_d[*some_parser - another_parser]

to

    *(some_parser - another_parser)

where refactor_unary_d is a predefined object of the parser generator struct refactor_unary_gen<>

The refactor_unary_d parser generator generates a new parser as shown above, only if the original construct is an auxilliary binary parser (here the difference parser) and the left operand of this binary parser is an auxilliary unary parser (here the kleene star operator). If the original parser isn't a binary parser the compilation will fail. If the left operand isn't an unary parser, no refactoring will take place.

Refactoring action parsers

The refactor_action_d parser generator, which should be used to generate an action refactoring parser, transforms a construct of the following type

    refactor_action_d[some_parser[some_actor] - another_parser]

to

    (some_parser - another_parser)[some_actor]

where refactor_action_d is a predefined object of the parser generator struct refactor_action_gen<>

The refactor_action_d parser generator generates a new parser as shown above, only if the original construct is an auxilliary binary parser (here the difference parser) and the left operand of this binary parser is an auxilliary parser generated by an attached semantic action. If the original parser isn't a binary parser the compilation will fail. If the left operand isn't an action parser, no refactoring will take place.

Attach action refactoring

The attach_action_d parser generator, which should be used to generate an attach action refactoring parser, transforms a construct of the following type

    attach_action_d[(some_parser >> another_parser)[some_actor]]

to

    some_parser[some_actor] >> another_parser[some_actor]

where attach_action_d is a predefined object of the parser generator struct attach_action_gen<>

The attach_action_d parser generator generates a new parser as shown above, only if the original construct is an auxilliary action parser and the parser to it this action is attached is an auxilliary binary parser (here the sequence parser). If the original parser isn't a action parser the compilation will fail. If the parser to which the action is attached isn't an binary parser, no refactoring will take place.

Nested refactoring

Sometimes it is required to nest different types of refactoring, i.e. to transform constructs like

    (*some_parser)[some_actor] - another_parser

to

    (*(some_parser - another_parser))[some_actor]

To simplify the construction of such nested refactoring parsers the refactor_unary_gen<> and refactor_action_gen<> both can take another refactoring parser generator type as their respective template parameter. For instance, to construct a refactoring parser generator for the mentioned nested transformation we should write:

    typedef refactor_action_gen<refactor_unary_gen<> > refactor_t;
    const refactor_t refactor_nested_d = refactor_t(refactor_unary_d);

Now we could use it as follows to get the required result:

    refactor_nested_d[(*some_parser)[some_actor] - another_parser]

An empty template parameter means not to nest this particular refactoring parser. The default template parameter is non_nesting_refactoring, a predefined helper structure for inhibiting nesting. Sometimes it is required to nest a particular refactoring parser with itself. This is achieved by providing the predefined helper structure self_nested_refactoring as the template parameter to the corresponding refactoring parser generator template.

See refactoring.cpp for a compilable example. This is part of the Spirit distribution.