File Coverage

blib/lib/RPerl/Operation/Expression/SubExpression/Literal/String.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             # [[[ HEADER ]]]
2             package RPerl::Operation::Expression::SubExpression::Literal::String;
3 4     4   29 use strict;
  4         13  
  4         157  
4 4     4   25 use warnings;
  4         12  
  4         105  
5 4     4   24 use RPerl::AfterSubclass;
  4         15  
  4         574  
6             our $VERSION = 0.006_000;
7              
8             # [[[ OO INHERITANCE ]]]
9 4     4   32 use parent qw(RPerl::Operation::Expression::SubExpression::Literal);
  4         13  
  4         27  
10 4     4   279 use RPerl::Operation::Expression::SubExpression::Literal;
  4         11  
  4         2213  
11              
12             # [[[ OO PROPERTIES ]]]
13             our hashref $properties = {};
14              
15             # [[[ SUBROUTINES & OO METHODS ]]]
16              
17             our string_hashref::method $ast_to_rperl__generate = sub {
18             ( my object $self, my string_hashref $modes) = @_;
19             my string_hashref $rperl_source_group = { PMC => q{} };
20              
21             # RPerl::diag( 'in Literal::String->ast_to_rperl__generate(), received $self = ' . "\n" . RPerl::Parser::rperl_ast__dump($self) . "\n" );
22              
23             if ( ( ref $self ) ne 'Literal_235' ) {
24             die RPerl::Parser::rperl_rule__replace(
25             'ERROR ECOGEASRP00, CODE GENERATOR, ABSTRACT SYNTAX TO RPERL: Grammar rule '
26             . ( ref $self )
27             . ' found where Literal_235 expected, dying' )
28             . "\n";
29             }
30            
31             # Literal -> LITERAL_STRING
32             my string $value = $self->{children}->[0];
33             $rperl_source_group->{PMC} .= $value;
34              
35             return $rperl_source_group;
36             };
37              
38             our string_hashref::method $ast_to_cpp__generate__CPPOPS_PERLTYPES = sub {
39             ( my object $self, my string_hashref $modes) = @_;
40             my string_hashref $cpp_source_group
41             = { CPP => q{// <<< RP::O::E::SE::L::S __DUMMY_SOURCE_CODE CPPOPS_PERLTYPES >>>}
42             . "\n" };
43              
44             #...
45             return $cpp_source_group;
46             };
47              
48             our string_hashref::method $ast_to_cpp__generate__CPPOPS_CPPTYPES = sub {
49             ( my object $self, my string_hashref $modes) = @_;
50             my string_hashref $cpp_source_group;
51              
52             # RPerl::diag( 'in Literal::String->ast_to_cpp__generate__CPPOPS_CPPTYPES(), received $self = ' . "\n" . RPerl::Parser::rperl_ast__dump($self) . "\n" );
53              
54             if ( ( ref $self ) ne 'Literal_235' ) {
55             die RPerl::Parser::rperl_rule__replace( 'ERROR ECOGEASCP00, CODE GENERATOR, ABSTRACT SYNTAX TO C++: Grammar rule ' . ( ref $self ) . ' found where Literal_235 expected, dying' ) . "\n";
56             }
57            
58             $cpp_source_group->{CPP} = $self->{children}->[0];
59            
60             # replace single-quoted Perl string with double-quoted C++ string, both non-interpolated
61             if ((substr $cpp_source_group->{CPP}, 0, 1) eq q{'}) {
62             if ((substr $cpp_source_group->{CPP}, -1, 1) eq q{'}) {
63             $cpp_source_group->{CPP} =~ s/\"/\\\"/gxms; # backslash-escape all double-quotes contained w/in single-quoted strings, before wrapping in non-escaped double-quotes
64             substr $cpp_source_group->{CPP}, 0, 1, q{"};
65             substr $cpp_source_group->{CPP}, -1, 1, q{"};
66             }
67             else {
68             die RPerl::Parser::rperl_rule__replace( 'ERROR ECOGEASCP50, CODE GENERATOR, ABSTRACT SYNTAX TO C++: string literal started with single-quote but not terminated with single-quote, dying' ) . "\n";
69             }
70             }
71             elsif ((substr $cpp_source_group->{CPP}, 0, 2) eq 'q{') {
72             if ((substr $cpp_source_group->{CPP}, -1, 1) eq '}') {
73             $cpp_source_group->{CPP} =~ s/\"/\\\"/gxms; # backslash-escape all double-quotes contained w/in single-quoted strings, before wrapping in non-escaped double-quotes
74             substr $cpp_source_group->{CPP}, 0, 2, q{"};
75             substr $cpp_source_group->{CPP}, -1, 1, q{"};
76             }
77             else {
78             die RPerl::Parser::rperl_rule__replace( 'ERROR ECOGEASCP51, CODE GENERATOR, ABSTRACT SYNTAX TO C++: string literal started with q-left-brace single-quote but not terminated with right-brace, dying' ) . "\n";
79             }
80             }
81             # NEED ADD ERROR CHECKING: double-quoted strings are okay for non-sigils containing newline or tab, non-quoted strings are not okay?
82             # else {
83             # die RPerl::Parser::rperl_rule__replace( 'ERROR ECOGEASCP52, CODE GENERATOR, ABSTRACT SYNTAX TO C++: string literal not started with single-quote, dying' ) . "\n";
84             # }
85              
86             # RPerl::diag( 'in Literal::String->ast_to_cpp__generate__CPPOPS_CPPTYPES(), have $modes->{_inside_print_operator} = ' . $modes->{_inside_print_operator} . "\n" );
87             # RPerl::diag( 'in Literal::String->ast_to_cpp__generate__CPPOPS_CPPTYPES(), have $modes->{_inside_list_elements} = ' . $modes->{_inside_list_elements} . "\n" );
88             # RPerl::diag( 'in Literal::String->ast_to_cpp__generate__CPPOPS_CPPTYPES(), have $modes->{_inside_cat_operator} = ' . $modes->{_inside_cat_operator} . "\n" );
89              
90             my boolean $cast_literal = 0;
91             if ((exists $modes->{_inside_class_properties}) and (defined $modes->{_inside_class_properties}) and $modes->{_inside_class_properties}) {
92             $cast_literal = 1;
93             }
94              
95             if ((
96             ((exists $modes->{_inside_print_operator}) and (defined $modes->{_inside_print_operator}) and $modes->{_inside_print_operator}) or
97             ((exists $modes->{_inside_die_operator}) and (defined $modes->{_inside_die_operator}) and $modes->{_inside_die_operator})
98             ) and
99             (exists $modes->{_inside_list_elements}) and (defined $modes->{_inside_list_elements}) and $modes->{_inside_list_elements}) { # and
100             # not ((exists $modes->{_inside_cat_operator}) and (defined $modes->{_inside_cat_operator}) and $modes->{_inside_cat_operator})) {
101             # if (1) {
102             # don't cast string literals when:
103             # inside OO class properties; OR
104             # inside print or die operator, and also inside list elements, and also NOT inside string concatenation operator;
105             # cout << will automatically detect type
106             $cast_literal = 1;
107             }
108              
109             if ($cast_literal) {
110             $cpp_source_group->{CPP} = $cpp_source_group->{CPP};
111             }
112             else {
113             # cast all string literals to the RPerl-defined C++ string type
114             $cpp_source_group->{CPP} = '(const string) ' . $cpp_source_group->{CPP};
115             }
116              
117             return $cpp_source_group;
118             };
119              
120             1; # end of class