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