File Coverage

lib/Compiler/Lexer.xs
Criterion Covered Total %
statement 40 101 39.6
branch 7 126 5.5
condition n/a
subroutine n/a
pod n/a
total 47 227 20.7


line stmt bran cond sub pod time code
1             #include <lexer.hpp>
2             #ifdef __cplusplus
3             extern "C" {
4             #endif
5             #define PERL_NO_GET_CONTEXT
6             #include "EXTERN.h"
7             #include "perl.h"
8             #include "XSUB.h"
9              
10             #include "ppport.h"
11             #undef dNOOP // Hack to work around "error: declaration of 'Perl___notused' has a different language linkage" error message on clang.
12             #define dNOOP
13              
14             #define new_Array() (AV*)sv_2mortal((SV*)newAV())
15             #define new_Hash() (HV*)sv_2mortal((SV*)newHV())
16             #define new_String(s, len) sv_2mortal(newSVpv(s, len))
17             #define new_Int(u) sv_2mortal(newSVuv(u))
18             #define new_Ref(sv) sv_2mortal(newRV_inc((SV*)sv))
19             #define set(e) SvREFCNT_inc(e)
20             #define get_value(hash, key) *hv_fetchs(hash, key, strlen(key))
21             #ifdef __cplusplus
22             };
23             #endif
24              
25             typedef Lexer * Compiler_Lexer;
26              
27             MODULE = Compiler::Lexer PACKAGE = Compiler::Lexer
28             PROTOTYPES: DISABLE
29              
30             Compiler_Lexer
31             _new(classname, _options)
32             char *classname
33             HV *_options
34             CODE:
35             {
36 27           const char *filename = SvPVX(get_value(_options, "filename"));
37 27           bool verbose = SvIVX(get_value(_options, "verbose"));
38 27 50         Lexer *lexer = new Lexer(filename, verbose);
39 27           RETVAL = lexer;
40             }
41             OUTPUT:
42             RETVAL
43              
44             void
45             DESTROY(self)
46             Compiler_Lexer self
47             CODE:
48             {
49 27 50         delete self;
50             }
51              
52             AV *
53             tokenize(self, script)
54             Compiler_Lexer self
55             const char *script
56             CODE:
57             {
58 35           Tokens *tokens = self->tokenize((char *)script);
59 35           AV* ret = new_Array();
60 70           size_t size = tokens->size();
61 8823 100         for (size_t i = 0; i < size; i++) {
62 17576           Token *token = tokens->at(i);
63 8788           HV *hash = (HV*)new_Hash();
64 17576           (void)hv_stores(hash, "stype", set(new_Int(token->stype)));
65 17576           (void)hv_stores(hash, "type", set(new_Int(token->info.type)));
66 17576           (void)hv_stores(hash, "kind", set(new_Int(token->info.kind)));
67 17576           (void)hv_stores(hash, "line", set(new_Int(token->finfo.start_line_num)));
68 17576           (void)hv_stores(hash, "has_warnings", set(new_Int(token->info.has_warnings)));
69 17576           (void)hv_stores(hash, "name", set(new_String(token->info.name, strlen(token->info.name))));
70 17576           (void)hv_stores(hash, "data", set(new_String(token->_data, strlen(token->_data))));
71 8788           HV *stash = (HV *)gv_stashpv("Compiler::Lexer::Token", sizeof("Compiler::Lexer::Token"));
72 17576           av_push(ret, set(sv_bless(new_Ref(hash), stash)));
73             }
74 35           self->clearContext();
75 35           RETVAL = ret;
76             }
77             OUTPUT:
78             RETVAL
79              
80             AV *
81             get_groups_by_syntax_level(self, tokens_, syntax_level)
82             Compiler_Lexer self
83             AV *tokens_
84             int syntax_level
85             CODE:
86             {
87 0           int tokens_size = av_len(tokens_);
88 0 0         if (tokens_size < 0) {
89 0           RETVAL = NULL;
90 0           return;
91             }
92 0           Tokens tks;
93 0 0         for (int i = 0; i <= tokens_size; i++) {
94 0 0         SV *token_ = (SV *)*av_fetch(tokens_, i, FALSE);
95 0 0         if (sv_isa(token_, "Compiler::Lexer::Token")) {
    0          
96 0           token_ = SvRV(token_);
97             }
98 0           HV *token = (HV *)token_;
99 0 0         const char *name = SvPVX(get_value(token, "name"));
100 0 0         const char *data = SvPVX(get_value(token, "data"));
101 0 0         int line = SvIVX(get_value(token, "line"));
102 0 0         int has_warnings = SvIVX(get_value(token, "has_warnings"));
103 0 0         Enum::Token::Type::Type type = (Enum::Token::Type::Type)SvIVX(get_value(token, "type"));
104 0 0         Enum::Token::Kind::Kind kind = (Enum::Token::Kind::Kind)SvIVX(get_value(token, "kind"));
105             FileInfo finfo;
106 0           finfo.start_line_num = line;
107 0           finfo.end_line_num = line;
108 0           finfo.filename = self->finfo.filename;
109             TokenInfo info;
110 0           info.type = type;
111 0           info.kind = kind;
112 0           info.name = name;
113 0           info.data = data;
114 0           info.has_warnings = has_warnings;
115 0 0         Token *tk = new Token(std::string(data), finfo);
    0          
    0          
116 0           tk->info = info;
117 0           tk->type = type;
118 0           tk->_data = data;
119 0 0         tks.push_back(tk);
120             }
121 0 0         self->grouping(&tks);
122 0 0         self->prepare(&tks);
123             //self->dump(&tks);
124 0 0         Token *root = self->parseSyntax(NULL, &tks);
125             //self->dumpSyntax(root, 0);
126 0 0         self->parseSpecificStmt(root);
127             //self->dumpSyntax(root, 0);
128 0 0         self->setIndent(root, 0);
129 0           size_t block_id = 0;
130 0 0         self->setBlockIDWithDepthFirst(root, &block_id);
131 0 0         Tokens *stmts = self->getTokensBySyntaxLevel(root, (Enum::Parser::Syntax::Type)syntax_level);
132 0 0         AV* ret = new_Array();
    0          
133 0 0         for (size_t i = 0; i < stmts->size(); i++) {
134 0           Token *stmt = stmts->at(i);
135 0 0         const char *src = stmt->deparse();
136 0           size_t len = strlen(src);
137 0 0         HV *hash = (HV*)new_Hash();
    0          
138 0 0         (void)hv_stores(hash, "src", set(new_String(src, len)));
    0          
    0          
139 0 0         (void)hv_stores(hash, "token_num", set(new_Int(stmt->total_token_num)));
    0          
    0          
140 0 0         (void)hv_stores(hash, "indent", set(new_Int(stmt->finfo.indent)));
    0          
    0          
141 0 0         (void)hv_stores(hash, "block_id", set(new_Int(stmt->finfo.block_id)));
    0          
    0          
142 0 0         (void)hv_stores(hash, "start_line", set(new_Int(stmt->finfo.start_line_num)));
    0          
    0          
143 0 0         (void)hv_stores(hash, "end_line", set(new_Int(stmt->finfo.end_line_num)));
    0          
    0          
144 0 0         (void)hv_stores(hash, "has_warnings", set(new_Int(stmt->info.has_warnings)));
    0          
    0          
145 0 0         av_push(ret, set(new_Ref(hash)));
    0          
    0          
146             }
147 0           RETVAL = ret;
148             }
149             OUTPUT:
150             RETVAL
151              
152             AV *
153             get_used_modules(self, script)
154             Compiler_Lexer self
155             const char *script
156             CODE:
157             {
158 12           Tokens *tokens = self->tokenize((char *)script);
159 12           self->grouping(tokens);
160 12           self->prepare(tokens);
161 12           Token *root = self->parseSyntax(NULL, tokens);
162 12           Modules *modules = self->getUsedModules(root);
163 12           AV* ret = new_Array();
164 38 100         for (size_t i = 0; i < modules->size(); i++) {
165 26           Module *module = modules->at(i);
166 26           const char *module_name = module->name;
167 26           const char *module_args = module->args;
168 26           size_t module_name_len = strlen(module_name);
169 26 50         size_t module_args_len = (module_args) ? strlen(module_args) : 0;
170 26           HV *hash = (HV*)new_Hash();
171 52           (void)hv_stores(hash, "name", set(new_String(module_name, module_name_len)));
172 52           (void)hv_stores(hash, "args", set(new_String(module_args, module_args_len)));
173 52           av_push(ret, set(new_Ref(hash)));
174             }
175 12           self->clearContext();
176 12           RETVAL = ret;
177             }
178             OUTPUT:
179             RETVAL
180              
181             SV *
182             deparse(filename, script)
183             const char *filename
184             const char *script
185             CODE:
186             {
187 0           Lexer lexer(filename, false);
188 0 0         Tokens *tokens = lexer.tokenize((char *)script);
189 0 0         lexer.grouping(tokens);
190 0 0         lexer.prepare(tokens);
191 0 0         Token *root = lexer.parseSyntax(NULL, tokens);
192 0 0         const char *src = root->deparse();
193 0           size_t len = strlen(src) + 1;
194 0           size_t token_size = tokens->size();
195 0 0         RETVAL = newSVpv(src, len);
196             }
197             OUTPUT:
198             RETVAL