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