#include <lexer.hpp>
#ifdef __cplusplus
extern "C" {
#endif
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#undef dNOOP // Hack to work around "error: declaration of 'Perl___notused' has a different language linkage" error message on clang.
#define dNOOP
#define new_Array() (AV*)sv_2mortal((SV*)newAV())
#define new_Hash() (HV*)sv_2mortal((SV*)newHV())
#define new_String(s, len) sv_2mortal(newSVpv(s, len))
#define new_Int(u) sv_2mortal(newSVuv(u))
#define new_Ref(sv) sv_2mortal(newRV_inc((SV*)sv))
#define set(e) SvREFCNT_inc(e)
#define get_value(hash, key) *hv_fetchs(hash, key, strlen(key))
#ifdef __cplusplus
};
#endif
typedef Lexer * Compiler_Lexer;
MODULE = Compiler::Lexer PACKAGE = Compiler::Lexer
PROTOTYPES: DISABLE
Compiler_Lexer
_new(classname, _options)
char *classname
HV *_options
CODE:
{
const char *filename = SvPVX(get_value(_options, "filename"));
bool verbose = SvIVX(get_value(_options, "verbose"));
Lexer *lexer = new Lexer(filename, verbose);
RETVAL = lexer;
}
OUTPUT:
RETVAL
void
DESTROY(self)
Compiler_Lexer self
CODE:
{
delete self;
}
AV *
tokenize(self, script)
Compiler_Lexer self
const char *script
CODE:
{
Tokens *tokens = self->tokenize((char *)script);
AV* ret = new_Array();
size_t size = tokens->size();
for (size_t i = 0; i < size; i++) {
Token *token = tokens->at(i);
HV *hash = (HV*)new_Hash();
(void)hv_stores(hash, "stype", set(new_Int(token->stype)));
(void)hv_stores(hash, "type", set(new_Int(token->info.type)));
(void)hv_stores(hash, "kind", set(new_Int(token->info.kind)));
(void)hv_stores(hash, "line", set(new_Int(token->finfo.start_line_num)));
(void)hv_stores(hash, "has_warnings", set(new_Int(token->info.has_warnings)));
(void)hv_stores(hash, "name", set(new_String(token->info.name, strlen(token->info.name))));
(void)hv_stores(hash, "data", set(new_String(token->_data, strlen(token->_data))));
HV *stash = (HV *)gv_stashpv("Compiler::Lexer::Token", sizeof("Compiler::Lexer::Token"));
av_push(ret, set(sv_bless(new_Ref(hash), stash)));
}
self->clearContext();
RETVAL = ret;
}
OUTPUT:
RETVAL
AV *
get_groups_by_syntax_level(self, tokens_, syntax_level)
Compiler_Lexer self
AV *tokens_
int syntax_level
CODE:
{
int tokens_size = av_len(tokens_);
if (tokens_size < 0) {
RETVAL = NULL;
return;
}
Tokens tks;
for (int i = 0; i <= tokens_size; i++) {
SV *token_ = (SV *)*av_fetch(tokens_, i, FALSE);
if (sv_isa(token_, "Compiler::Lexer::Token")) {
token_ = SvRV(token_);
}
HV *token = (HV *)token_;
const char *name = SvPVX(get_value(token, "name"));
const char *data = SvPVX(get_value(token, "data"));
int line = SvIVX(get_value(token, "line"));
int has_warnings = SvIVX(get_value(token, "has_warnings"));
Enum::Token::Type::Type type = (Enum::Token::Type::Type)SvIVX(get_value(token, "type"));
Enum::Token::Kind::Kind kind = (Enum::Token::Kind::Kind)SvIVX(get_value(token, "kind"));
FileInfo finfo;
finfo.start_line_num = line;
finfo.end_line_num = line;
finfo.filename = self->finfo.filename;
TokenInfo info;
info.type = type;
info.kind = kind;
info.name = name;
info.data = data;
info.has_warnings = has_warnings;
Token *tk = new Token(std::string(data), finfo);
tk->info = info;
tk->type = type;
tk->_data = data;
tks.push_back(tk);
}
self->grouping(&tks);
self->prepare(&tks);
//self->dump(&tks);
Token *root = self->parseSyntax(NULL, &tks);
//self->dumpSyntax(root, 0);
self->parseSpecificStmt(root);
//self->dumpSyntax(root, 0);
self->setIndent(root, 0);
size_t block_id = 0;
self->setBlockIDWithDepthFirst(root, &block_id);
Tokens *stmts = self->getTokensBySyntaxLevel(root, (Enum::Parser::Syntax::Type)syntax_level);
AV* ret = new_Array();
for (size_t i = 0; i < stmts->size(); i++) {
Token *stmt = stmts->at(i);
const char *src = stmt->deparse();
size_t len = strlen(src);
HV *hash = (HV*)new_Hash();
(void)hv_stores(hash, "src", set(new_String(src, len)));
(void)hv_stores(hash, "token_num", set(new_Int(stmt->total_token_num)));
(void)hv_stores(hash, "indent", set(new_Int(stmt->finfo.indent)));
(void)hv_stores(hash, "block_id", set(new_Int(stmt->finfo.block_id)));
(void)hv_stores(hash, "start_line", set(new_Int(stmt->finfo.start_line_num)));
(void)hv_stores(hash, "end_line", set(new_Int(stmt->finfo.end_line_num)));
(void)hv_stores(hash, "has_warnings", set(new_Int(stmt->info.has_warnings)));
av_push(ret, set(new_Ref(hash)));
}
RETVAL = ret;
}
OUTPUT:
RETVAL
AV *
get_used_modules(self, script)
Compiler_Lexer self
const char *script
CODE:
{
Tokens *tokens = self->tokenize((char *)script);
self->grouping(tokens);
self->prepare(tokens);
Token *root = self->parseSyntax(NULL, tokens);
Modules *modules = self->getUsedModules(root);
AV* ret = new_Array();
for (size_t i = 0; i < modules->size(); i++) {
Module *module = modules->at(i);
const char *module_name = module->name;
const char *module_args = module->args;
size_t module_name_len = strlen(module_name);
size_t module_args_len = (module_args) ? strlen(module_args) : 0;
HV *hash = (HV*)new_Hash();
(void)hv_stores(hash, "name", set(new_String(module_name, module_name_len)));
(void)hv_stores(hash, "args", set(new_String(module_args, module_args_len)));
av_push(ret, set(new_Ref(hash)));
}
self->clearContext();
RETVAL = ret;
}
OUTPUT:
RETVAL
SV *
deparse(filename, script)
const char *filename
const char *script
CODE:
{
Lexer lexer(filename, false);
Tokens *tokens = lexer.tokenize((char *)script);
lexer.grouping(tokens);
lexer.prepare(tokens);
Token *root = lexer.parseSyntax(NULL, tokens);
const char *src = root->deparse();
size_t len = strlen(src) + 1;
size_t token_size = tokens->size();
RETVAL = newSVpv(src, len);
}
OUTPUT:
RETVAL