in reply to using two Parse::RecDescent parsers together

From the docs,

$text: The remaining (unparsed) text. Changes to $text do not propagate out of unsuccessful productions, but do survive successful productions.

So we need to remove from $text what the query parser matches. Also from the docs,

If, however, the text to be matched is passed by reference [...] then any text which was consumed during the match will be removed from the start of [the referenced string].

So it's quite simple:

$TemplateParser = Parse::RecDescent->new(<<'__GRAMMAR__'); template: identifier 'TEMPLATE' '{' statement(s) '}' statement: expression | conditional | loopcontrol | { $QueryParser->query(\$text) } __GRAMMAR__

Tested.