blob: f4092320680dd073ef66e2c2d143ff02dcc02513 [file] [log] [blame]
#include "slang_rs_context.hpp"
#include "slang_rs_pragma_handler.hpp"
#include "clang/Lex/Preprocessor.h" /* for class Preprocessor */
#include "clang/Lex/Token.h" /* for class Token */
#include "clang/Lex/LiteralSupport.h" /* for class StringLiteralParser */
#include "clang/Basic/TokenKinds.h" /* for class Token */
#include "clang/Basic/IdentifierTable.h" /* for class IdentifierInfo */
namespace {
using namespace clang;
using namespace slang;
class RSExportVarPragmaHandler : public RSPragmaHandler {
private:
void handleItem(const std::string& Item) {
mContext->addExportVar(Item);
}
public:
RSExportVarPragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
void HandlePragma(Preprocessor& PP, Token& FirstToken) {
this->handleItemListPragma(PP, FirstToken);
}
};
class RSExportVarAllPragmaHandler : public RSPragmaHandler {
public:
RSExportVarAllPragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
void HandlePragma(Preprocessor& PP, Token& FirstToken) {
this->handleNonParamPragma(PP, FirstToken);
mContext->setExportAllNonStaticVars(true);
}
};
class RSExportFuncPragmaHandler : public RSPragmaHandler {
private:
void handleItem(const std::string& Item) {
mContext->addExportFunc(Item);
}
public:
RSExportFuncPragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
void HandlePragma(Preprocessor& PP, Token& FirstToken) {
this->handleItemListPragma(PP, FirstToken);
}
};
class RSExportFuncAllPragmaHandler : public RSPragmaHandler {
public:
RSExportFuncAllPragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
void HandlePragma(Preprocessor& PP, Token& FirstToken) {
this->handleNonParamPragma(PP, FirstToken);
mContext->setExportAllNonStaticFuncs(true);
}
};
class RSExportTypePragmaHandler : public RSPragmaHandler {
private:
void handleItem(const std::string& Item) {
mContext->addExportType(Item);
}
public:
RSExportTypePragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
void HandlePragma(Preprocessor& PP, Token& FirstToken) {
this->handleItemListPragma(PP, FirstToken);
}
};
class RSJavaPackageNamePragmaHandler : public RSPragmaHandler {
public:
RSJavaPackageNamePragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
void HandlePragma(Preprocessor& PP, Token& FirstToken) {
/* FIXME: Need to validate the extracted package name from paragma. Currently "all chars" specified in pragma will be treated as package name.
*
* 18.1 The Grammar of the Java Programming Language, http://java.sun.com/docs/books/jls/third_edition/html/syntax.html#18.1
*
* CompilationUnit:
* [[Annotations] package QualifiedIdentifier ; ] {ImportDeclaration}
* {TypeDeclaration}
*
* QualifiedIdentifier:
* Identifier { . Identifier }
*
* Identifier:
* IDENTIFIER
*
* 3.8 Identifiers, http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8
*
*/
Token& PragmaToken = FirstToken;
std::string PackageName;
/* Skip first token, "java_package_name" */
PP.LexUnexpandedToken(PragmaToken);
/* Now, the current token must be tok::lpara */
if(PragmaToken.isNot(tok::l_paren))
return;
while(PragmaToken.isNot(tok::eom)) {
/* Lex package name */
PP.LexUnexpandedToken(PragmaToken);
bool Invalid;
std::string Spelling = PP.getSpelling(PragmaToken, &Invalid);
if(!Invalid)
PackageName.append(Spelling);
/* Pre-mature end (syntax error will be triggered by preprocessor later) */
if(PragmaToken.is(tok::eom) || PragmaToken.is(tok::eof))
break;
else {
/* Next token is ')' (end of paragma) */
const Token& NextTok = PP.LookAhead(0);
if(NextTok.is(tok::r_paren)) {
mContext->setReflectJavaPackageName(PackageName);
/* Lex until meets tok::eom */
do
PP.LexUnexpandedToken(PragmaToken);
while(PragmaToken.isNot(tok::eom));
break;
}
}
}
return;
}
};
class RSReflectLicensePragmaHandler : public RSPragmaHandler {
private:
void handleItem(const std::string& Item) {
mContext->setLicenseNote(Item);
}
public:
RSReflectLicensePragmaHandler(IdentifierInfo* II, RSContext* Context) : RSPragmaHandler(II, Context) { return; }
void HandlePragma(Preprocessor& PP, Token& FirstToken) {
this->handleOptionalStringLiateralParamPragma(PP, FirstToken);
}
};
} /* anonymous namespace */
namespace slang {
RSPragmaHandler* RSPragmaHandler::CreatePragmaExportVarHandler(RSContext* Context) {
IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("export_var");
if(II != NULL)
return new RSExportVarPragmaHandler(II, Context);
else
return NULL;
}
RSPragmaHandler* RSPragmaHandler::CreatePragmaExportVarAllHandler(RSContext* Context) {
IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("export_var_all");
if(II != NULL)
return new RSExportVarAllPragmaHandler(II, Context);
else
return NULL;
}
RSPragmaHandler* RSPragmaHandler::CreatePragmaExportFuncHandler(RSContext* Context) {
IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("export_func");
if(II != NULL)
return new RSExportFuncPragmaHandler(II, Context);
else
return NULL;
}
RSPragmaHandler* RSPragmaHandler::CreatePragmaExportFuncAllHandler(RSContext* Context) {
IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("export_func_all");
if(II != NULL)
return new RSExportFuncAllPragmaHandler(II, Context);
else
return NULL;
}
RSPragmaHandler* RSPragmaHandler::CreatePragmaExportTypeHandler(RSContext* Context) {
IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("export_type");
if(II != NULL)
return new RSExportTypePragmaHandler(II, Context);
else
return NULL;
}
RSPragmaHandler* RSPragmaHandler::CreatePragmaJavaPackageNameHandler(RSContext* Context) {
IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("java_package_name");
if(II != NULL)
return new RSJavaPackageNamePragmaHandler(II, Context);
else
return NULL;
}
RSPragmaHandler* RSPragmaHandler::CreatePragmaReflectLicenseHandler(RSContext* Context) {
IdentifierInfo* II = Context->getPreprocessor()->getIdentifierInfo("set_reflect_license");
if(II != NULL)
return new RSReflectLicensePragmaHandler(II, Context);
else
return NULL;
}
void RSPragmaHandler::handleItemListPragma(Preprocessor& PP, Token& FirstToken) {
Token& PragmaToken = FirstToken;
/* Skip first token, like "export_var" */
PP.LexUnexpandedToken(PragmaToken);
/* Now, the current token must be tok::lpara */
if(PragmaToken.isNot(tok::l_paren))
return;
while(PragmaToken.isNot(tok::eom)) {
/* Lex variable name */
PP.LexUnexpandedToken(PragmaToken);
if(PragmaToken.is(tok::identifier))
this->handleItem( PP.getSpelling(PragmaToken) );
else
break;
assert(PragmaToken.isNot(tok::eom));
PP.LexUnexpandedToken(PragmaToken);
if(PragmaToken.isNot(tok::comma))
break;
}
return;
}
void RSPragmaHandler::handleNonParamPragma(Preprocessor& PP, Token& FirstToken) {
Token& PragmaToken = FirstToken;
/* Skip first token, like "export_var_all" */
PP.LexUnexpandedToken(PragmaToken);
/* Should be end immediately */
if(PragmaToken.isNot(tok::eom))
printf("RSPragmaHandler::handleNonParamPragma: expected a tok::eom\n");
return;
}
void RSPragmaHandler::handleOptionalStringLiateralParamPragma(Preprocessor& PP, Token& FirstToken) {
Token& PragmaToken = FirstToken;
/* Skip first token, like "set_reflect_license" */
PP.LexUnexpandedToken(PragmaToken);
/* Now, the current token must be tok::lpara */
if(PragmaToken.isNot(tok::l_paren))
return;
/* If not ')', eat the following string literal as the license */
PP.LexUnexpandedToken(PragmaToken);
if(PragmaToken.isNot(tok::r_paren)) {
/* Eat the whole string literal */
StringLiteralParser StringLiteral(&PragmaToken, 1, PP);
if (StringLiteral.hadError)
printf("RSPragmaHandler::handleOptionalStringLiateralParamPragma: illegal string literal\n");
else
this->handleItem( std::string(StringLiteral.GetString()) );
/* The current token should be tok::r_para */
PP.LexUnexpandedToken(PragmaToken);
if (PragmaToken.isNot(tok::r_paren))
printf("RSPragmaHandler::handleOptionalStringLiateralParamPragma: expected a ')'\n");
} else {
/* If no argument, remove the license */
this->handleItem( "" );
}
}
} /* namespace slang */