slang_rs_pragma_handler.cpp revision f52a620440fa62257dfdcf2583f0f9df5b855c76
1#include "slang_rs_context.hpp" 2#include "slang_rs_pragma_handler.hpp" 3 4#include "clang/Lex/Preprocessor.h" /* for class Preprocessor */ 5#include "clang/Lex/Token.h" /* for class Token */ 6#include "clang/Lex/LiteralSupport.h" /* for class StringLiteralParser */ 7#include "clang/Basic/TokenKinds.h" /* for class Token */ 8 9namespace { 10 11using namespace clang; 12using namespace slang; 13 14class RSExportVarPragmaHandler : public RSPragmaHandler { 15private: 16 void handleItem(const std::string& Item) { 17 mContext->addExportVar(Item); 18 } 19 20public: 21 RSExportVarPragmaHandler(llvm::StringRef Name, RSContext* Context) : RSPragmaHandler(Name, Context) { return; } 22 23 void HandlePragma(Preprocessor& PP, Token& FirstToken) { 24 this->handleItemListPragma(PP, FirstToken); 25 } 26}; 27 28class RSExportVarAllPragmaHandler : public RSPragmaHandler { 29public: 30 RSExportVarAllPragmaHandler(llvm::StringRef Name, RSContext* Context) : RSPragmaHandler(Name, Context) { return; } 31 32 void HandlePragma(Preprocessor& PP, Token& FirstToken) { 33 this->handleNonParamPragma(PP, FirstToken); 34 mContext->setExportAllNonStaticVars(true); 35 } 36}; 37 38class RSExportFuncPragmaHandler : public RSPragmaHandler { 39private: 40 void handleItem(const std::string& Item) { 41 mContext->addExportFunc(Item); 42 } 43 44public: 45 RSExportFuncPragmaHandler(llvm::StringRef Name, RSContext* Context) : RSPragmaHandler(Name, Context) { return; } 46 47 void HandlePragma(Preprocessor& PP, Token& FirstToken) { 48 this->handleItemListPragma(PP, FirstToken); 49 } 50}; 51 52class RSExportFuncAllPragmaHandler : public RSPragmaHandler { 53public: 54 RSExportFuncAllPragmaHandler(llvm::StringRef Name, RSContext* Context) : RSPragmaHandler(Name, Context) { return; } 55 56 void HandlePragma(Preprocessor& PP, Token& FirstToken) { 57 this->handleNonParamPragma(PP, FirstToken); 58 mContext->setExportAllNonStaticFuncs(true); 59 } 60}; 61 62class RSExportTypePragmaHandler : public RSPragmaHandler { 63private: 64 void handleItem(const std::string& Item) { 65 mContext->addExportType(Item); 66 } 67 68public: 69 RSExportTypePragmaHandler(llvm::StringRef Name, RSContext* Context) : RSPragmaHandler(Name, Context) { return; } 70 71 void HandlePragma(Preprocessor& PP, Token& FirstToken) { 72 this->handleItemListPragma(PP, FirstToken); 73 } 74}; 75 76class RSJavaPackageNamePragmaHandler : public RSPragmaHandler { 77public: 78 RSJavaPackageNamePragmaHandler(llvm::StringRef Name, RSContext* Context) : RSPragmaHandler(Name, Context) { return; } 79 80 void HandlePragma(Preprocessor& PP, Token& FirstToken) { 81 /* FIXME: Need to validate the extracted package name from paragma. Currently "all chars" specified in pragma will be treated as package name. 82 * 83 * 18.1 The Grammar of the Java Programming Language, http://java.sun.com/docs/books/jls/third_edition/html/syntax.html#18.1 84 * 85 * CompilationUnit: 86 * [[Annotations] package QualifiedIdentifier ; ] {ImportDeclaration} 87 * {TypeDeclaration} 88 * 89 * QualifiedIdentifier: 90 * Identifier { . Identifier } 91 * 92 * Identifier: 93 * IDENTIFIER 94 * 95 * 3.8 Identifiers, http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8 96 * 97 */ 98 99 Token& PragmaToken = FirstToken; 100 std::string PackageName; 101 102 /* Skip first token, "java_package_name" */ 103 PP.LexUnexpandedToken(PragmaToken); 104 105 /* Now, the current token must be tok::lpara */ 106 if(PragmaToken.isNot(tok::l_paren)) 107 return; 108 109 while(PragmaToken.isNot(tok::eom)) { 110 /* Lex package name */ 111 PP.LexUnexpandedToken(PragmaToken); 112 113 bool Invalid; 114 std::string Spelling = PP.getSpelling(PragmaToken, &Invalid); 115 if(!Invalid) 116 PackageName.append(Spelling); 117 118 /* Pre-mature end (syntax error will be triggered by preprocessor later) */ 119 if(PragmaToken.is(tok::eom) || PragmaToken.is(tok::eof)) 120 break; 121 else { 122 /* Next token is ')' (end of paragma) */ 123 const Token& NextTok = PP.LookAhead(0); 124 if(NextTok.is(tok::r_paren)) { 125 mContext->setReflectJavaPackageName(PackageName); 126 /* Lex until meets tok::eom */ 127 do 128 PP.LexUnexpandedToken(PragmaToken); 129 while(PragmaToken.isNot(tok::eom)); 130 break; 131 } 132 } 133 } 134 return; 135 } 136}; 137 138class RSReflectLicensePragmaHandler : public RSPragmaHandler { 139private: 140 void handleItem(const std::string& Item) { 141 mContext->setLicenseNote(Item); 142 } 143 144public: 145 RSReflectLicensePragmaHandler(llvm::StringRef Name, RSContext* Context) : RSPragmaHandler(Name, Context) { return; } 146 147 void HandlePragma(Preprocessor& PP, Token& FirstToken) { 148 this->handleOptionalStringLiateralParamPragma(PP, FirstToken); 149 } 150}; 151 152} /* anonymous namespace */ 153 154namespace slang { 155 156RSPragmaHandler* RSPragmaHandler::CreatePragmaExportVarHandler(RSContext* Context) { 157 return new RSExportVarPragmaHandler("export_var", Context); 158} 159 160RSPragmaHandler* RSPragmaHandler::CreatePragmaExportVarAllHandler(RSContext* Context) { 161 return new RSExportVarPragmaHandler("export_var_all", Context); 162} 163 164RSPragmaHandler* RSPragmaHandler::CreatePragmaExportFuncHandler(RSContext* Context) { 165 return new RSExportFuncPragmaHandler("export_func", Context); 166} 167 168RSPragmaHandler* RSPragmaHandler::CreatePragmaExportFuncAllHandler(RSContext* Context) { 169 return new RSExportFuncPragmaHandler("export_func_all", Context); 170} 171 172RSPragmaHandler* RSPragmaHandler::CreatePragmaExportTypeHandler(RSContext* Context) { 173 return new RSExportTypePragmaHandler("export_type", Context); 174} 175 176RSPragmaHandler* RSPragmaHandler::CreatePragmaJavaPackageNameHandler(RSContext* Context) { 177 return new RSJavaPackageNamePragmaHandler("java_package_name", Context); 178} 179 180RSPragmaHandler* RSPragmaHandler::CreatePragmaReflectLicenseHandler(RSContext* Context) { 181 return new RSJavaPackageNamePragmaHandler("set_reflect_license", Context); 182} 183 184void RSPragmaHandler::handleItemListPragma(Preprocessor& PP, Token& FirstToken) { 185 Token& PragmaToken = FirstToken; 186 187 /* Skip first token, like "export_var" */ 188 PP.LexUnexpandedToken(PragmaToken); 189 190 /* Now, the current token must be tok::lpara */ 191 if(PragmaToken.isNot(tok::l_paren)) 192 return; 193 194 while(PragmaToken.isNot(tok::eom)) { 195 /* Lex variable name */ 196 PP.LexUnexpandedToken(PragmaToken); 197 if(PragmaToken.is(tok::identifier)) 198 this->handleItem( PP.getSpelling(PragmaToken) ); 199 else 200 break; 201 202 assert(PragmaToken.isNot(tok::eom)); 203 204 PP.LexUnexpandedToken(PragmaToken); 205 206 if(PragmaToken.isNot(tok::comma)) 207 break; 208 } 209 return; 210} 211 212void RSPragmaHandler::handleNonParamPragma(Preprocessor& PP, Token& FirstToken) { 213 Token& PragmaToken = FirstToken; 214 215 /* Skip first token, like "export_var_all" */ 216 PP.LexUnexpandedToken(PragmaToken); 217 218 /* Should be end immediately */ 219 if(PragmaToken.isNot(tok::eom)) 220 printf("RSPragmaHandler::handleNonParamPragma: expected a tok::eom\n"); 221 return; 222} 223 224void RSPragmaHandler::handleOptionalStringLiateralParamPragma(Preprocessor& PP, Token& FirstToken) { 225 Token& PragmaToken = FirstToken; 226 227 /* Skip first token, like "set_reflect_license" */ 228 PP.LexUnexpandedToken(PragmaToken); 229 230 /* Now, the current token must be tok::lpara */ 231 if(PragmaToken.isNot(tok::l_paren)) 232 return; 233 234 /* If not ')', eat the following string literal as the license */ 235 PP.LexUnexpandedToken(PragmaToken); 236 if(PragmaToken.isNot(tok::r_paren)) { 237 /* Eat the whole string literal */ 238 StringLiteralParser StringLiteral(&PragmaToken, 1, PP); 239 if (StringLiteral.hadError) 240 printf("RSPragmaHandler::handleOptionalStringLiateralParamPragma: illegal string literal\n"); 241 else 242 this->handleItem( std::string(StringLiteral.GetString()) ); 243 244 /* The current token should be tok::r_para */ 245 PP.LexUnexpandedToken(PragmaToken); 246 if (PragmaToken.isNot(tok::r_paren)) 247 printf("RSPragmaHandler::handleOptionalStringLiateralParamPragma: expected a ')'\n"); 248 } else { 249 /* If no argument, remove the license */ 250 this->handleItem( "" ); 251 } 252} 253 254} /* namespace slang */ 255