File Coverage

lib/Data/SExpression/Parser.yp
Criterion Covered Total %
statement 49 50 98.0
branch 16 22 72.7
condition 3 3 100.0
subroutine 19 19 100.0
pod 0 8 0.0
total 87 102 85.2


line stmt bran cond sub pod time code
1             # -*- mode: perl -*-
2             #
3             # Parser.yp
4             #
5             # Grammar to parse SExpressions for Data::SExpression
6             #
7             #
8              
9             %{
10 9     9   489 use Data::SExpression::Cons;
  9         16  
  9         76  
11 9     9   372 use Scalar::Util qw(weaken);
  9         15  
  9         18562  
12             %}
13              
14             %%
15 24     24 0 17281  
16 24 50   53   77 sexpression: expression { $_[0]->YYAccept; return $_[1]; }
  53         208  
  53         273  
17             ;
18              
19             expression: NUMBER
20 61     61   180 | SYMBOL { $_[0]->handler->new_symbol($_[1]) }
21 12     12   31 | STRING { $_[0]->handler->new_string($_[1]) }
22             | list
23             | quoted
24              
25             ;
26              
27 60     60   131 list: '(' list_interior ')' { $_[2] }
28             ;
29              
30              
31             list_interior:
32 13     13   36 expression '.' expression { $_[0]->handler->new_cons($_[1], $_[3]) }
33 50     50   122 | expression list_interior { $_[0]->handler->new_cons($_[1], $_[2]) }
34 37     37   85 | expression { $_[0]->handler->new_cons($_[1], undef) }
35 10     10   23 | { undef }
36              
37             ;
38              
39             quoted:
40 7     7   15 QUOTE expression { $_[0]->handler->new_cons($_[0]->handler->new_symbol($_[1]),
41             $_[0]->handler->new_cons($_[2], undef))}
42 24         1470 ;
43              
44             %%
45 24         139  
46             sub set_input {
47 67     67 0 380 my $self = shift;
48 67         87 my $input = shift;
49 67 50       159 die(__PACKAGE__ . "::set_input called with 0 arguments") unless defined($input);
50 67         204 $self->YYData->{INPUT} = $input;
51             }
52              
53             sub set_handler {
54 11     11 0 22 my $self = shift;
55 11 50       107 my $handler = shift or die(__PACKAGE__ . "::set_handler called with 0 arguments");
56 11         68 $self->YYData->{HANDLER} = $handler;
57 11         39 weaken $self->YYData->{HANDLER};
58             }
59              
60             sub handler {
61 194     194 0 333 my $self = shift;
62 194         420 return $self->YYData->{HANDLER};
63             }
64              
65             sub unparsed_input {
66 54     54 0 233 my $self = shift;
67 54         140 return substr($self->YYData->{INPUT}, pos($self->YYData->{INPUT}));
68             }
69              
70              
71             my %quotes = (q{'} => 'quote',
72             q{`} => 'quasiquote',
73             q{,} => 'unquote');
74              
75              
76             sub lexer {
77 305     305 0 653 my $self = shift;
78              
79 305 50       716 defined($self->YYData->{INPUT}) or return ('', undef);
80              
81 305         959 my $symbol_char = qr{[*!\$[:alpha:]\?<>=/+:_{}-]};
82              
83 305         771 for($self->YYData->{INPUT}) {
84 305         867 $_ =~ /\G \s* (?: ; .* \s* )* /gcx;
85              
86 305 100 100     1721 /\G ([+-]? \d+ (?:[.]\d*)?) /gcx
87             || /\G ([+-]? [.] \d+) /gcx
88             and return ('NUMBER', $1);
89              
90 267 100       7522 /\G ($symbol_char ($symbol_char | \d | [.] )*)/gcx
91             and return ('SYMBOL', $1);
92              
93 201 50       452 /\G (\| [^|]* \|) /gcx
94             and return ('SYMBOL', $1);
95              
96 201 50       587 /\G " ([^"\\]* (?: \\. [^"\\]*)*) "/gcx
    100          
97             and return ('STRING', defined($1) ? $1 : "");
98              
99 173 100       1159 /\G ([().])/gcx
100             and return ($1, $1);
101              
102 23 100       90 /\G ([`',]) /gcx
103             and return ('QUOTE', $quotes{$1});
104              
105 15         60 return ('', undef);
106             }
107             }
108              
109             sub error {
110 1     1 0 1 my $self = shift;
111 1         11 my ($tok, $val) = $self->YYLexer->($self);
112 1         3 die("Parse error near: '" . $self->unparsed_input . "'");
113 0         0 return undef;
114             }
115              
116             sub parse {
117 54     54 0 234 my $self = shift;
118 54         249 return $self->YYParse(yylex => \&lexer, yyerror => \&error);
119             }