File Coverage

blib/lib/Gherkin/ParserBase.pm
Criterion Covered Total %
statement 42 53 79.2
branch 2 10 20.0
condition 2 6 33.3
subroutine 16 17 94.1
pod 0 4 0.0
total 62 90 68.8


line stmt bran cond sub pod time code
1             package Gherkin::ParserBase;
2             $Gherkin::ParserBase::VERSION = '25.0.1';
3 1     1   8 use strict;
  1         1  
  1         27  
4 1     1   4 use warnings;
  1         2  
  1         31  
5              
6 1         7 use Class::XSAccessor accessors =>
7 1     1   467 [ qw/ast_builder token_matcher stop_at_first_error max_errors/, ];
  1         2462  
8              
9 1     1   753 use Gherkin::ParserContext;
  1         3  
  1         28  
10 1     1   394 use Gherkin::Exceptions;
  1         2  
  1         25  
11 1     1   450 use Gherkin::AstBuilder;
  1         4  
  1         40  
12              
13 1     1   540 use Gherkin::TokenMatcher;
  1         4  
  1         31  
14 1     1   431 use Gherkin::TokenScanner;
  1         13  
  1         516  
15              
16             sub new {
17 3     3 0 6314 my ( $class, $ast_builder, $token_matcher ) = @_;
18 3   33     24 bless {
      33        
19             ast_builder => $ast_builder || Gherkin::AstBuilder->new(),
20             token_matcher => $token_matcher || Gherkin::TokenMatcher->new(),
21             stop_at_first_error => 0,
22             max_errors => 10,
23             },
24             $class;
25             }
26              
27 3     3 0 12 sub get_result { return $_[0]->ast_builder->get_result }
28              
29             sub add_error {
30 0     0 0 0 my ( $self, $context, $error ) = @_;
31              
32 0         0 $context->add_errors($error);
33              
34 0         0 my @errors = $context->errors;
35 0 0       0 Gherkin::Exceptions::CompositeParser->throw(@errors)
36             if @errors > $self->max_errors;
37             }
38              
39             sub _start_rule {
40 33     33   68 my ( $self, $context, $ruleType ) = @_;
41 33         65 $self->_handle_ast_error( $context, start_rule => $ruleType );
42             }
43              
44             sub _end_rule {
45 33     33   64 my ( $self, $context, $ruleType ) = @_;
46 33         63 $self->_handle_ast_error( $context, end_rule => $ruleType );
47             }
48              
49             sub _build {
50 36     36   82 my ( $self, $context, $token ) = @_;
51 36         63 $self->_handle_ast_error( $context, build => $token );
52             }
53              
54             sub _handle_ast_error {
55 102     102   178 my ( $self, $context, $method_name, $arg ) = @_;
56             my $action = sub {
57 102     102   333 $self->ast_builder->$method_name($arg);
58 102         348 };
59              
60 102         208 $self->handle_external_error( $context, 1, $action );
61             }
62              
63             sub handle_external_error {
64 315     315 0 533 my ( $self, $context, $default_value, $action ) = @_;
65 315 50       663 return $action->() if $self->stop_at_first_error;
66              
67 315         418 my $result = eval { $action->() };
  315         504  
68 315 50       1226 return $result unless $@;
69              
70             # Non-structured exceptions
71 0 0         die $@ unless ref $@;
72              
73 0 0         if ( ref $@ eq 'Gherkin::Exceptions::CompositeParser' ) {
74 0           $self->add_error( $context, $_ ) for @{ $@->errors };
  0            
75 0           return $default_value;
76             } else {
77 0           $self->add_error( $context, $@ );
78 0           return $default_value;
79             }
80             }
81              
82             1;