1 #ifndef _CppBase_Internal_h_ 2 #define _CppBase_Internal_h_ 3 4 namespace Upp { 5 6 const char *SkipString(const char *s); 7 8 void RemoveComments(String& l, bool& incomment); 9 10 const VectorMap<String, String>& GetNamespaceMacros(); 11 const Index<String>& GetNamespaceEndMacros(); 12 13 struct CppMacro : Moveable<CppMacro> { 14 String param; 15 String body; 16 byte md5[16]; 17 18 String Define(const char *s); SetUndefCppMacro19 void SetUndef() { body = "\x7f"; } IsUndefCppMacro20 bool IsUndef() const { return body[0] == '\x7f' && body[1] == '\0'; } 21 22 String Expand(const Vector<String>& p, const Vector<String>& ep) const; 23 24 void Serialize(Stream& s); 25 26 String ToString() const; 27 }; 28 29 enum PPItemType { 30 PP_DEFINES, 31 PP_INCLUDE, 32 PP_USING, 33 PP_NAMESPACE, 34 PP_NAMESPACE_END 35 }; 36 37 struct PPItem { 38 int type; 39 String text; 40 int segment_id; 41 SerializePPItem42 void Serialize(Stream& s) { s % type % text % segment_id; } 43 }; 44 45 struct PPMacro : Moveable<PPMacro> { 46 CppMacro macro; 47 int segment_id; // a group of macros in single file, between other elements (include, namespace. using, undef...) 48 int line; // line in file 49 int undef_segment_id; // macro has matching undef in the same file within this segment 50 SerializePPMacro51 void Serialize(Stream& s) { s % macro % segment_id % line % undef_segment_id; } ToStringPPMacro52 String ToString() const { return AsString(macro) + " " + AsString(segment_id); } 53 PPMacroPPMacro54 PPMacro() { segment_id = undef_segment_id = 0; } 55 }; 56 57 struct PPFile { // contains "macro extract" of file, only info about macros defined and namespaces 58 Time filetime; 59 Array<PPItem> item; 60 Index<String> includes; 61 Vector<String> keywords; 62 String md5sum; 63 64 void Parse(Stream& in); SerializePPFile65 void Serialize(Stream& s) { s % filetime % item % includes % keywords % md5sum; } 66 void Dump() const; 67 68 private: 69 Vector<int> ppmacro; // indicies of macros in sAllMacros 70 71 void CheckEndNamespace(Vector<int>& namespace_block, int level, Md5Stream& md5); 72 }; 73 74 PPMacro *FindPPMacro(const String& id, Index<int>& segment_id, int& segmenti); 75 const CppMacro *FindMacro(const String& id, Index<int>& segment_id, int& segmenti); 76 77 String GetIncludePath(); 78 79 String GetSegmentFile(int segment_id); 80 81 void MakePP(const Index<String>& paths); // this is the only place to change PPFile info, cannot be run concurrently with anything else 82 83 const PPFile& GetPPFile(const char *path); // only returns information created by MakePP 84 85 String GetIncludePath(const String& s, const String& filedir); 86 bool IncludesFile(const String& parent_path, const String& header_path); 87 88 struct FlatPP { 89 Index<int> segment_id; 90 Index<String> usings; 91 }; 92 93 const FlatPP& GetFlatPPFile(const char *path); // with #includes resolved 94 95 struct Cpp { 96 static Index<String> kw; 97 98 bool incomment; 99 bool done; 100 101 Index<String> visited; 102 103 Index<int> segment_id; // segments of included macros 104 VectorMap<String, PPMacro> macro; // macros defined 105 int std_macros; // standard macros (keywords and trick - fixed) 106 Index<String> notmacro; // accelerator / expanding helper 107 String prefix_macro; // for handling multiline macros 108 109 String output; // preprocessed file 110 // Index<String> usedmacro; 111 Index<String> namespace_using; // 'using namespace' up to start of file 112 Vector<String> namespace_stack; // namspace up to start of file 113 114 Md5Stream md5; 115 116 void Define(const char *s); 117 118 void ParamAdd(Vector<String>& param, const char *b, const char *e); 119 String Expand(const char *s); 120 void DoFlatInclude(const String& header_path); 121 void Do(const String& sourcefile, Stream& in, const String& currentfile, bool get_macros); 122 123 bool Preprocess(const String& sourcefile, Stream& in, const String& currentfile, 124 bool just_get_macros = false); 125 126 String GetDependeciesMd5(const Vector<String>& m); 127 128 typedef Cpp CLASSNAME; 129 }; 130 131 enum tk_Keywords { 132 Tmarker_before_first = 255, 133 #define CPPID(x) tk_##x, 134 #include "keyword.i" 135 #undef CPPID 136 }; 137 138 enum t_Terms { 139 t_eof, 140 t_string = -200, 141 t_integer, 142 t_double, 143 t_character, 144 t_dblcolon, // :: 145 t_mulass, // *= 146 t_divass, // /= 147 t_modass, // %= 148 t_xorass, // ^= 149 t_neq, // <> 150 t_dot_asteriks, // .* 151 t_elipsis, // ... 152 t_inc, // ++ 153 t_addass, // += 154 t_dec, // - 155 t_arrow_asteriks, // ->* 156 t_arrow, // -> 157 t_subass, // -= 158 t_and, // & 159 t_andass, // &= 160 t_or, // | 161 t_orass, // |= 162 t_eq, // == 163 t_shl, // << 164 t_shlass, // <<= 165 t_le, // <= 166 t_shr, // >> 167 t_shrass, // >>= 168 t_ge, // >= 169 te_integeroverflow, 170 te_badcharacter, 171 te_badstring, 172 }; 173 174 class LexSymbolStat 175 { 176 public: 177 LexSymbolStat(); 178 void Reset(int minSymbol, int maxSymbol); 179 void IncStat(int symbol); 180 int GetStat(int symbol) const; 181 int SumStat(const Vector<int> & symbols) const; 182 void Merge(const LexSymbolStat & other); 183 184 private: 185 Vector<int> v; 186 int minSymbol; 187 }; 188 189 190 class Lex { 191 #ifdef _DEBUG 192 const char *pp; 193 #endif 194 const char *ptr; 195 const char *pos; 196 197 Index<String> id; 198 int endkey; 199 int braceslevel; 200 201 struct Term : Moveable<Term>{ 202 const char *ptr; 203 int code; 204 String text; 205 double number; 206 bool grounding; 207 TermTerm208 Term() { grounding = false; } 209 }; 210 211 bool statsCollected; 212 LexSymbolStat symbolStat; 213 BiVector<Term> term; 214 int body; 215 bool grounding; 216 Char(int c)217 bool Char(int c) { if(*ptr == c) { ptr++; return true; } else return false; } AddCode(int code)218 void AddCode(int code) { Term& tm = term.AddTail(); tm.code = code; tm.ptr = pos; tm.grounding = grounding; } AssOp(int noass,int ass)219 void AssOp(int noass, int ass) { AddCode(Char('=') ? ass : noass); } 220 void Next(); 221 bool Prepare(int pos); 222 int GetCharacter(); 223 void ThrowError(const char *e); 224 225 public: 226 Event<const String&> WhenError; 227 228 struct Grounding {}; 229 230 int Code(int pos = 0); 231 bool IsId(int pos = 0); 232 String Id(int pos = 0); 233 int Int(int pos = 0); 234 double Double(int pos = 0); 235 int Chr(int pos = 0); 236 String Text(int pos = 0); 237 238 void Get(int n = 1); GetCode()239 int GetCode() { int q = Code(); Get(); return q; } GetId()240 String GetId() { String q = Id(); Get(); return q; } GetInt()241 int GetInt() { int q = Int(); Get(); return q; } GetDouble()242 double GetDouble() { double q = Double(); Get(); return q; } GetChr()243 int GetChr() { int q = Chr(); Get(); return q; } GetText()244 String GetText() { String q = Text(); Get(); return q; } 245 Id(const String & s)246 int Id(const String& s) { return id.FindAdd(s) + 256; } 247 GetBracesLevel()248 int GetBracesLevel() const { return braceslevel; } ClearBracesLevel()249 void ClearBracesLevel() { braceslevel = 0; } 250 BeginBody()251 void BeginBody() { body++; } EndBody()252 void EndBody() { body--; } ClearBody()253 void ClearBody() { body = 0; } IsBody()254 bool IsBody() const { return body; } IsGrounded()255 bool IsGrounded() { Code(); return term.GetCount() && term[0].grounding; } 256 void SkipToGrounding(); 257 258 const char *Pos(int pos = 0); 259 int operator[](int pos) { return Code(pos); } 260 operator int() { return Code(0); } 261 void operator++() { return Get(); } 262 263 void Dump(int pos); 264 265 void Init(const char *s); 266 void StartStatCollection(); 267 const LexSymbolStat & FinishStatCollection(); 268 269 Lex(); 270 }; 271 272 struct SrcFile { 273 SrcFile(); 274 rval_default(SrcFile); 275 276 String text; 277 Vector<int> linepos; 278 int preprocessorLinesRemoved; 279 int blankLinesRemoved; 280 int commentLinesRemoved; 281 }; 282 283 struct Parser; 284 285 SrcFile PreProcess(Stream& in, Parser& parser); 286 287 String CppItemKindAsString(int kind); 288 289 struct Parser : ParserContext { 290 struct Decla { 291 bool s_static = false; 292 bool s_extern = false; 293 bool s_register = false; 294 bool s_mutable = false; 295 bool s_explicit = false; 296 bool s_virtual = false; 297 String name; 298 bool function = false; 299 bool type_def = false; 300 bool isfriend = false; 301 bool istemplate = false; 302 bool istructor = false; 303 bool isdestructor = false; 304 bool isptr = false; 305 bool nofn = false; 306 bool oper = false; 307 bool castoper = false; 308 309 String tnames; 310 String type; 311 String natural; 312 }; 313 314 struct Decl : Decla { 315 Array<Decl> param; 316 317 rval_default(Decl); DeclParser::Decl318 Decl() {} 319 }; 320 321 struct RecursionCounter 322 { 323 int change; 324 int &count; 325 RecursionCounter(int &count_i, int change_i = 1) : changeParser::RecursionCounter326 change(change_i), count(count_i) 327 { 328 count += change; 329 } ~RecursionCounterParser::RecursionCounter330 ~RecursionCounter() { count -= change; } 331 }; 332 333 SrcFile file; 334 Lex lex; 335 int filei; 336 byte filetype; 337 String title; 338 int struct_level; 339 340 Event<int, const String&> err; 341 342 int lpos, line; 343 344 CppBase *base; 345 346 int RPtr(); 347 348 bool Key(int code); 349 bool EatBody(); 350 String ResolveAutoType(); 351 void TryLambda(); 352 bool Skipars(int& q); 353 354 void Cv(); 355 String TType(); 356 String ReadType(Decla& d, const String& tname, const String& tparam); 357 void Qualifier(bool override_final = false); 358 void ParamList(Decl& d); 359 void Declarator(Decl& d, const char *p); 360 void EatInitializers(); 361 void Vars(Array<Decl>& r, const char *p, bool type_def, bool more); 362 void ReadMods(Decla& d); 363 Array<Decl> Declaration0(bool l0, bool more, const String& tname, const String& tparam); 364 Array<Decl> Declaration(bool l0/* = false*/, bool more/* = false*/, const String& tname, const String& tparam); 365 bool IsParamList(int q); 366 void Elipsis(Decl& d); 367 Decl& Finish(Decl& d, const char *p); 368 void AddNamespace(const String& n, const String& name); 369 bool Scope(const String& tp, const String& tn); 370 371 String TemplateParams(String& pnames); 372 String TemplateParams(); 373 String TemplatePnames(); 374 String Name(String& h, bool& castoper, bool& oper); 375 String Name(bool& castoper, bool& oper); 376 String Constant(); 377 String ReadOper(bool& castoper); 378 379 int GetLine(const char *pos); 380 void Line(); 381 void Check(bool b, const char *err); 382 void CheckKey(int c); 383 384 void ClassEnum(); 385 bool IsEnum(int i); 386 bool UsingNamespace(); 387 void SetScopeCurrent(); 388 void ScopeBody(); 389 void DoNamespace(); 390 void Do(); 391 String AnonymousName(); 392 String StructDeclaration(const String& tp, const String& tn); 393 void Enum(bool vars); 394 395 CppItem& Item(const String& scope, const String& using_namespace, const String& item, 396 const String& name, bool impl); 397 CppItem& Item(const String& scope, const String& using_namespace, const String& item, 398 const String& name); 399 400 CppItem& Fn(const Decl& d, const String& templ, bool body, 401 const String& tname, const String& tparam); 402 403 struct Error {}; 404 405 void ThrowError(const String& e); 406 void Resume(int bl); 407 408 void MatchPars(); 409 bool VCAttribute(); 410 bool TryDecl(); 411 void Statement(); 412 void Locals(const String& type); 413 String Tparam(int& q); 414 bool IsNamespace(const String& scope); 415 416 friend class Lex; // Fix to make Lex::ThrowError 417 418 typedef Parser CLASSNAME; 419 420 public: 421 void AddMacro(int lineno, const String& macro); 422 423 bool dobody; 424 Function<String(String, String, String)> qualify; // used to qualify local variable names (needs main codebase and its mutex) 425 int currentScopeDepth; 426 int maxScopeDepth; 427 428 String namespace_info; 429 getPreprocessedFileParser430 const SrcFile &getPreprocessedFile() { return file; } 431 432 void Do(Stream& in, CppBase& _base, int file, int filetype, 433 const String& title, Event<int, const String&> _err, 434 const Vector<String>& typenames, 435 const Vector<String>& namespace_stack, 436 const Index<String>& namespace_using); 437 ParserParser438 Parser() : dobody(false) { lex.WhenError = THISBACK(ThrowError); } 439 }; 440 441 void QualifyTypes(CppBase& base, const String& scope, CppItem& m); 442 String QualifyKey(const CppBase& base, const String& scope, const String& type, const String& usings); 443 444 const Array<CppItem>& GetTypeItems(const CppBase& codebase, const String& type); 445 446 Vector<String> MakeXP(const char *s); 447 448 }; 449 450 #endif 451