1 /*
2 * This file is part of the FortranProject plugin for Code::Blocks IDE
3 * and licensed under the GNU General Public License, version 3
4 * http://www.gnu.org/licenses/gpl-3.0.html
5 */
6
7 #include "parserthreadf.h"
8
9 #include <sdk.h>
10 #ifndef CB_PRECOMP
11 #include <wx/tokenzr.h>
12 #endif
13 #include <set>
14
15 #include "usetokenf.h"
16
ParserThreadF(const wxString & projectFilename,const wxString & bufferOrFilename,TokensArrayF * tokens,FortranSourceForm fsForm,bool isBuffer,IncludeDB * includeDB)17 ParserThreadF::ParserThreadF(const wxString& projectFilename,
18 const wxString& bufferOrFilename,
19 TokensArrayF* tokens,
20 FortranSourceForm fsForm,
21 bool isBuffer,
22 IncludeDB* includeDB)
23 :
24 m_pTokens(tokens),
25 m_pLastParent(0L),
26 m_pIncludeDB(includeDB),
27 m_Briefend(_T("@brief_end@"))
28 {
29 m_InterfaceOperator = 0;
30 m_InterfaceAssignment = 0;
31 m_InterfaceRead = 0;
32 m_InterfaceWrite = 0;
33
34 m_pPPDefineTokens = new TokensArrayF();
35 m_inIfdef = 0;
36
37 if (!isBuffer)
38 {
39 if (!bufferOrFilename.IsEmpty())
40 {
41 m_Filename = bufferOrFilename;
42 m_Tokens.Init(m_Filename, fsForm);
43 wxChar sep = wxFileName::GetPathSeparator();
44 m_pLastParent = DoAddFileToken(bufferOrFilename.AfterLast(sep), projectFilename);
45 }
46 }
47 else
48 {
49 m_Tokens.InitFromBuffer(bufferOrFilename, fsForm);
50 }
51 InitSecondEndPart();
52 }
53
ParserThreadF(const wxString & projectFilename,const wxString & filename,TokensArrayF * tokens,FortranSourceForm fsForm,IncludeDB * includeDB,const wxString & buffer)54 ParserThreadF::ParserThreadF(const wxString& projectFilename,
55 const wxString& filename,
56 TokensArrayF* tokens,
57 FortranSourceForm fsForm,
58 IncludeDB* includeDB,
59 const wxString& buffer)
60 :
61 m_pTokens(tokens),
62 m_pLastParent(0L),
63 m_pIncludeDB(includeDB),
64 m_Briefend(_T("@brief_end@"))
65 {
66 m_InterfaceOperator = 0;
67 m_InterfaceAssignment = 0;
68 m_InterfaceRead = 0;
69 m_InterfaceWrite = 0;
70
71 m_pPPDefineTokens = new TokensArrayF();
72 m_inIfdef = 0;
73
74 m_Filename = filename;
75 m_Tokens.InitFromBuffer(buffer, fsForm);
76 m_Tokens.SetFilename(filename);
77 wxChar sep = wxFileName::GetPathSeparator();
78 m_pLastParent = DoAddFileToken(filename.AfterLast(sep), projectFilename);
79
80 InitSecondEndPart();
81 }
82
~ParserThreadF()83 ParserThreadF::~ParserThreadF()
84 {
85 //dtor
86 delete m_pPPDefineTokens;
87 }
88
InitSecondEndPart()89 void ParserThreadF::InitSecondEndPart()
90 {
91 m_KnownEndSecPart.insert(_T("subroutine"));
92 m_KnownEndSecPart.insert(_T("function"));
93 m_KnownEndSecPart.insert(_T("module"));
94 m_KnownEndSecPart.insert(_T("submodule"));
95 m_KnownEndSecPart.insert(_T("type"));
96 m_KnownEndSecPart.insert(_T("interface"));
97 m_KnownEndSecPart.insert(_T("program"));
98 m_KnownEndSecPart.insert(_T("block"));
99 m_KnownEndSecPart.insert(_T("blockdata"));
100 m_KnownEndSecPart.insert(_T("associate"));
101 m_KnownEndSecPart.insert(_T("procedure"));
102
103 m_NumberOfBlockConstruct = 0;
104 }
105
Parse()106 bool ParserThreadF::Parse()
107 {
108 if (!m_pTokens || !m_Tokens.IsOK())
109 {
110 return false;
111 }
112
113 while (1)
114 {
115 wxString token = m_Tokens.GetToken();
116 if (token.IsEmpty())
117 break;
118
119 wxString tok_low = token.Lower();
120 wxString next = m_Tokens.PeekToken();
121 wxString nex_low = next.Lower();
122
123 if (tok_low.Matches(_T("use")))
124 {
125 HandleUse();
126 }
127 else if (tok_low.Matches(_T("module")) && !nex_low.Matches(_T("procedure"))
128 && !nex_low.Matches(_T("function")) && !nex_low.Matches(_T("subroutine")))
129 {
130 HandleModule();
131 }
132 else if (tok_low.Matches(_T("submodule")) && !nex_low.Matches(_T("procedure")))
133 {
134 HandleSubmodule();
135 }
136 else if (tok_low.Matches(_T("program")))
137 {
138 HandleFunction(tkProgram);
139 }
140 else if (tok_low.Matches(_T("function")))
141 {
142 HandleFunction(tkFunction);
143 }
144 else if (tok_low.Matches(_T("subroutine")))
145 {
146 HandleFunction(tkSubroutine);
147 }
148 else if (tok_low.Matches(_T("type")) && !nex_low(0,1).Matches(_T("(")) && !nex_low.Matches(_T("is")))
149 {
150 HandleType();
151 }
152 else if (tok_low.Matches(_T("block")))
153 {
154 if (nex_low.Matches(_T("data")))
155 {
156 token = m_Tokens.GetToken();
157 tok_low = token.Lower();
158 next = m_Tokens.PeekToken();
159 nex_low = next.Lower();
160 HandleBlockData();
161 }
162 else
163 {
164 HandleBlockConstruct();
165 }
166 }
167 else if (tok_low.Matches(_T("blockdata")))
168 {
169 HandleBlockData();
170 }
171 else if (tok_low.Matches(_T("include")))
172 {
173 HandleInclude();
174 }
175 else if (tok_low.GetChar(0) == '#')
176 {
177 HandlePPDirective(token);
178 }
179 else if (tok_low.Matches(_T("interface")))
180 {
181 HandleInterface();
182 }
183 else if (tok_low.Matches(_T("associate")))
184 {
185 HandleAssociateConstruct();
186 }
187 else if ((tok_low.Matches(_T("select")) && nex_low.Matches(_T("type"))) ||
188 tok_low.Matches(_T("selecttype")))
189 {
190 HandleSelectTypeConstruct();
191 }
192 else if ((tok_low.Matches(_T("select")) && nex_low.Matches(_T("case"))) ||
193 tok_low.Matches(_T("selectcase")))
194 {
195 HandleSelectCaseConstruct();
196 }
197 else if (tok_low.Matches(_T("end")))
198 {
199 // something is wrong with code or parser
200 m_Tokens.SkipToOneOfChars(";", true);
201 }
202 else if (tok_low.Matches(_T("procedure")) && nex_low(0,1).Matches(_T("(")))
203 {
204 ParseTypeBoundProcedures(token, true, false);
205 }
206 else
207 {
208 bool needDefault = true;
209 bool hasFunctionInLine;
210 TokensArrayF tokTmpArr;
211 CheckParseOneDeclaration(token, tok_low, next, nex_low, needDefault, tokTmpArr, hasFunctionInLine);
212 }
213 }
214
215 if (!m_Filename.IsEmpty() && m_pIncludeDB)
216 {
217 //update IncludeDB
218 wxChar sep = wxFileName::GetPathSeparator();
219 m_pIncludeDB->SetInclude(m_Filename.AfterLast(sep), m_IncludeList);
220 }
221 return true;
222 }
223
DoAddToken(TokenKindF kind,const wxString & name,const wxString & args,const wxString & typeDefinition)224 TokenF* ParserThreadF::DoAddToken(TokenKindF kind, const wxString& name, const wxString& args, const wxString& typeDefinition)
225 {
226 TokenF* newToken = new TokenF;
227 newToken->m_Name = name.Lower();
228
229 newToken->m_TokenKind = kind;
230 newToken->m_pParent = m_pLastParent;
231 newToken->m_Filename = m_Tokens.GetFilename();
232 newToken->m_LineStart = m_Tokens.GetLineNumber();
233 newToken->m_DisplayName = name;
234 newToken->m_Args = args;
235 newToken->m_TypeDefinition = typeDefinition;
236 newToken->m_DefinitionLength = 1;
237
238 if (m_pLastParent)
239 {
240 m_pLastParent->AddChild(newToken);
241 }
242 else
243 {
244 m_pTokens->Add(newToken);
245 }
246
247 return newToken;
248 }
249
DoAddToken(TokenKindF kind,const wxString & name,const wxString & args,const unsigned int defStartLine)250 TokenF* ParserThreadF::DoAddToken(TokenKindF kind, const wxString& name, const wxString& args, const unsigned int defStartLine)
251 {
252 TokenF* newToken = new TokenF;
253 newToken->m_Name = name.Lower();
254
255 newToken->m_TokenKind = kind;
256 newToken->m_pParent = m_pLastParent;
257 newToken->m_Filename = m_Tokens.GetFilename();
258 newToken->m_DisplayName = name;
259 newToken->m_Args = args;
260 newToken->m_TypeDefinition = wxEmptyString;
261
262 newToken->m_LineStart = defStartLine;
263 newToken->m_DefinitionLength = m_Tokens.GetLineNumber() - defStartLine + 1;
264
265
266 if (m_pLastParent)
267 {
268 m_pLastParent->AddChild(newToken);
269 }
270 else
271 {
272 m_pTokens->Add(newToken);
273 }
274
275 return newToken;
276 }
277
DoAddFileToken(const wxString & filename,const wxString & projectFilename)278 FileTokenF* ParserThreadF::DoAddFileToken(const wxString& filename, const wxString& projectFilename)
279 {
280 FileTokenF* newToken = new FileTokenF;
281 newToken->m_Name = filename.Lower();
282
283 newToken->m_TokenKind = tkFile;
284 newToken->m_pParent = m_pLastParent;
285 newToken->m_Filename = m_Tokens.GetFilename();
286 newToken->m_LineStart = 0;
287 newToken->m_DisplayName = filename;
288 newToken->m_DefinitionLength = 1;
289
290 m_pTokens->Add(newToken);
291
292 newToken->m_ProjectFilename = projectFilename;
293
294 return newToken;
295 }
296
HandleUse()297 void ParserThreadF::HandleUse()
298 {
299 wxString modName;
300 wxArrayString lineTok = m_Tokens.GetTokensToEOL();
301 ModuleNature modNature = mnNonIntrinsic;
302 int ltCount = lineTok.GetCount();
303 int idx = lineTok.Index(_T("::"));
304 if (idx != wxNOT_FOUND)
305 {
306 if (idx > 0)
307 {
308 if (lineTok.Item(idx-1).Lower().IsSameAs(_T("intrinsic")))
309 {
310 modNature = mnIntrinsic;
311 }
312 }
313 idx++;
314 }
315 else
316 {
317 idx = 0;
318 }
319 if (ltCount > idx)
320 {
321 modName = lineTok.Item(idx);
322 }
323 else
324 {
325 return; //something wrong
326 }
327 UseTokenF* pUseTok = DoAddUseToken(modName);
328 pUseTok->SetModuleNature(modNature);
329
330 idx++;
331 if (ltCount <= idx)
332 {
333 return; // no more on the line
334 }
335 if (lineTok.Item(idx).Lower().IsSameAs(_T("only")))
336 {
337 pUseTok->SetOnly(true);
338 idx++;
339 while (true)
340 {
341 idx++;
342 if (ltCount <= idx)
343 break;
344 wxString localName = lineTok.Item(idx);
345 wxString externalName;
346
347 if (localName.Lower().IsSameAs(_T("operator")))
348 {
349 idx += 4; // operator (.st.) => operator (.kt.)
350 continue;
351 }
352 if (ltCount > idx+1 && lineTok.Item(idx+1).IsSameAs(_T("=>")))
353 {
354 //it is rename
355 if (ltCount > idx+2)
356 {
357 idx += 2;
358 externalName = lineTok.Item(idx);
359 }
360 else
361 {
362 break; // '=>' on end of line
363 }
364 }
365 if (externalName.IsEmpty())
366 pUseTok->AddToNamesList(localName);
367 else
368 pUseTok->AddToRenameList(localName, externalName);
369 }
370 }
371 else
372 {
373 pUseTok->SetOnly(false);
374 // rename-list
375 while (true)
376 {
377 if (lineTok.Item(idx).Lower().IsSameAs(_T("operator")))
378 {
379 idx += 5; // operator (.st.) => operator (.kt.)
380 }
381 if (ltCount > idx+1 && lineTok.Item(idx+1).IsSameAs(_T("=>")))
382 {
383 wxString localName = lineTok.Item(idx);
384 wxString externalName;
385 if (ltCount > idx+2)
386 {
387 idx += 2;
388 externalName = lineTok.Item(idx);
389 }
390 else
391 {
392 break; // '=>' on end of line
393 }
394 pUseTok->AddToRenameList(localName, externalName);
395 idx++;
396 if (ltCount <= idx)
397 break;
398 }
399 else
400 {
401 break;
402 }
403 }
404 }
405 }
406
407
DoAddUseToken(const wxString & modName)408 UseTokenF* ParserThreadF::DoAddUseToken(const wxString& modName)
409 {
410 UseTokenF* newToken = new UseTokenF();
411 newToken->m_Name = modName.Lower();
412
413 newToken->m_TokenKind = tkUse;
414 newToken->m_pParent = m_pLastParent;
415 newToken->m_Filename = m_Tokens.GetFilename();
416 newToken->m_DisplayName = modName;
417 newToken->m_TypeDefinition = wxEmptyString;
418
419 newToken->m_LineStart = m_Tokens.GetLineNumber();
420 newToken->m_DefinitionLength = 1;
421
422 if (m_pLastParent)
423 {
424 m_pLastParent->AddChild(newToken);
425 }
426 else
427 {
428 m_pTokens->Add(newToken);
429 }
430
431 return newToken;
432 }
433
434
HandleModule()435 void ParserThreadF::HandleModule()
436 {
437 TokenKindF kind = tkModule;
438 TokenF* old_parent = m_pLastParent;
439
440 int countAccessList = 0;
441 wxString token = m_Tokens.GetTokenSameLine();
442 TokenAccessKind taDefKind = taPublic;
443 ModuleTokenF* modToken;
444 if (token.IsEmpty())
445 modToken = DoAddModuleToken(_T("unnamed"));
446 else
447 modToken = DoAddModuleToken(token);
448 m_pLastParent = modToken;
449
450 // Parse documentation
451 m_ParentDocs.Clear();
452 DocBlock docs;
453 GetDocBlock(docs, false, modToken->m_LineStart, true);
454 if (docs.HasBrief() || docs.HasDescription())
455 modToken->m_DocString << docs.GetBrief() + m_Briefend + docs.GetDescription();
456
457 wxArrayString privateNameList;
458 wxArrayString publicNameList;
459 wxArrayString protectedNameList;
460
461 TokensArrayF typeTokensAll;
462 TokensArrayF interfGenTokens;
463 TokensArrayF interfTokens;
464
465 while (1)
466 {
467 token = m_Tokens.GetToken();
468 if (token.IsEmpty())
469 break;
470 wxString tok_low = token.Lower();
471
472 wxString next = m_Tokens.PeekToken();
473 wxString nex_low = next.Lower();
474 if ( ((m_Tokens.GetLineNumber() == m_Tokens.GetPeekedLineNumber()) && IsEnd(tok_low, nex_low)) ||
475 ((m_Tokens.GetLineNumber() != m_Tokens.GetPeekedLineNumber()) && IsEnd(tok_low, _T(""))) )
476 {
477 m_Tokens.SkipToOneOfChars(";", true);
478 break;
479 }
480 else if (tok_low.Matches(_T("type")) && !nex_low(0,1).Matches(_T("(")))
481 {
482 bool needDefault=true;
483 TokenF* tokTmp = 0;
484 HandleType(needDefault, tokTmp);
485 if (tokTmp)
486 typeTokensAll.Add(tokTmp);
487 if (!needDefault && tokTmp)
488 {
489 if (tokTmp->m_TokenAccess == taPrivate)
490 privateNameList.Add(tokTmp->m_Name);
491 else
492 publicNameList.Add(tokTmp->m_Name);
493 }
494 }
495 else if (tok_low.Matches(_T("subroutine")))
496 {
497 HandleFunction(tkSubroutine, taDefKind);
498 }
499 else if (tok_low.Matches(_T("function")))
500 {
501 HandleFunction(tkFunction, taDefKind);
502 }
503 else if (tok_low.Matches(_T("use")))
504 {
505 HandleUse();
506 }
507 else if (tok_low.Matches(_T("interface")))
508 {
509 TokenF* tokTmp = 0;
510 bool isGeneric = false;
511 HandleInterface(taDefKind, tokTmp, isGeneric);
512 if (isGeneric && tokTmp)
513 interfGenTokens.Add(tokTmp);
514 if (tokTmp)
515 interfTokens.Add(tokTmp);
516 }
517 else if (tok_low.Matches(_T("include")))
518 {
519 HandleInclude();
520 }
521 else if (tok_low.GetChar(0) == '#')
522 {
523 HandlePPDirective(token);
524 }
525 else if (tok_low.Matches(_T("private")))
526 {
527 bool changeDefault;
528 HandleAccessList(taPrivate, changeDefault, countAccessList, privateNameList);
529 if (changeDefault)
530 {
531 modToken->SetDefaultPublic(false);
532 taDefKind = taPrivate;
533 }
534 }
535 else if (tok_low.Matches(_T("public")))
536 {
537 bool changeDefault;
538 HandleAccessList(taPublic, changeDefault, countAccessList, publicNameList);
539 if (changeDefault)
540 {
541 modToken->SetDefaultPublic(true);
542 taDefKind = taPublic;
543 }
544 }
545 else if (tok_low.Matches(_T("protected")))
546 {
547 bool tmpB;
548 HandleAccessList(taProtected, tmpB, countAccessList, protectedNameList);
549 }
550 else if (kind == tkModule)
551 {
552 bool needDefault=true;
553 bool hasFunctionInLine;
554 TokensArrayF tokTmpArr;
555 CheckParseOneDeclaration(token, tok_low, next, nex_low, needDefault, tokTmpArr, hasFunctionInLine);
556 if (!needDefault)
557 {
558 for (size_t i=0; i<tokTmpArr.Count(); i++)
559 {
560 if (tokTmpArr.Item(i)->m_TokenAccess == taPrivate)
561 privateNameList.Add(tokTmpArr.Item(i)->m_Name);
562 else
563 publicNameList.Add(tokTmpArr.Item(i)->m_Name);
564 }
565 }
566 }
567 }
568 modToken->AddLineEnd(m_Tokens.GetLineNumber());
569 m_pLastParent = old_parent;
570
571 for (size_t i=0; i<interfTokens.GetCount(); i++)
572 {
573 interfTokens.Item(i)->m_TokenAccess = taDefKind;
574 if (interfTokens.Item(i)->m_TokenKind == tkInterfaceExplicit)
575 {
576 TokensArrayF* chs = &interfTokens.Item(i)->m_Children;
577 for (size_t j=0; j<chs->GetCount(); j++)
578 {
579 chs->Item(j)->m_TokenAccess = taDefKind;
580 }
581 }
582 }
583
584 for (size_t i=0; i<publicNameList.GetCount(); i++)
585 {
586 modToken->AddToPublicList(publicNameList.Item(i));
587 }
588 for (size_t i=0; i<privateNameList.GetCount(); i++)
589 {
590 modToken->AddToPrivateList(privateNameList.Item(i));
591 }
592
593 TokensArrayF* toks = &modToken->m_Children;
594 if (toks)
595 {
596 for (size_t i=0; i<toks->GetCount(); i++)
597 {
598 SetTokenAccess(modToken, toks->Item(i), taDefKind);
599
600 if (protectedNameList.Index(toks->Item(i)->m_Name) != wxNOT_FOUND)
601 {
602 toks->Item(i)->m_TokenAccess = taProtected;
603 }
604 else if (toks->Item(i)->m_TokenKind == tkInterfaceExplicit)
605 {
606 TokensArrayF* chs = &toks->Item(i)->m_Children;
607 if (chs)
608 {
609 for (size_t j=0; j<chs->GetCount(); j++)
610 {
611 SetTokenAccess(modToken, chs->Item(j), taDefKind);
612 }
613 }
614 }
615 }
616 }
617
618 // find kind of children of GenericInterfaces
619 for (size_t i=0; i<interfGenTokens.GetCount(); i++)
620 {
621 TokensArrayF* chs = &interfGenTokens.Item(i)->m_Children;
622 for (size_t j=0; j<chs->GetCount(); j++)
623 {
624 wxString intfname = chs->Item(j)->m_Name;
625 TokensArrayF* modChs = &modToken->m_Children;
626 TokenKindF tk;
627 bool found = false;
628 for (size_t k=0; k<modChs->GetCount(); k++)
629 {
630 if ((modChs->Item(k)->m_TokenKind == tkSubroutine || modChs->Item(k)->m_TokenKind == tkFunction) &&
631 modChs->Item(k)->m_Name.IsSameAs(intfname))
632 {
633 tk = modChs->Item(k)->m_TokenKind;
634 found = true;
635 break;
636 }
637 else if (modChs->Item(k)->m_TokenKind == tkInterfaceExplicit ||
638 modChs->Item(k)->m_TokenKind == tkInterface)
639 {
640 TokensArrayF* intfExpChs = &modChs->Item(k)->m_Children;
641 if (intfExpChs)
642 {
643 for (size_t m=0; m<intfExpChs->GetCount(); m++)
644 {
645 if ((intfExpChs->Item(m)->m_TokenKind == tkSubroutine || intfExpChs->Item(m)->m_TokenKind == tkFunction) &&
646 intfExpChs->Item(m)->m_Name.IsSameAs(intfname))
647 {
648 tk = intfExpChs->Item(m)->m_TokenKind;
649 found = true;
650 break;
651 }
652 }
653 if (found)
654 break;
655 }
656 }
657 }
658
659 if (found)
660 {
661 // write kind for GenericInterface
662 if (tk == tkFunction)
663 interfGenTokens.Item(i)->m_TypeDefinition = _T("function");
664 else
665 interfGenTokens.Item(i)->m_TypeDefinition = _T("subroutine");
666 break;
667 }
668 }
669 }
670
671 for (size_t i=0; i<typeTokensAll.GetCount(); i++)
672 {
673 TokensArrayF* chs = &typeTokensAll.Item(i)->m_Children;
674 TokensArrayF genericProc;
675 for (size_t j=0; j<chs->GetCount(); j++)
676 {
677 if (chs->Item(j)->m_TokenKind == tkProcedure)
678 {
679 wxString procName;
680 if (chs->Item(j)->m_PartLast.IsEmpty())
681 procName = chs->Item(j)->m_Name;
682 else
683 procName = chs->Item(j)->m_PartLast;
684
685 TokensArrayF* modChs = &modToken->m_Children;
686 TokenKindF tk;
687 bool found = false;
688 for (size_t k=0; k<modChs->GetCount(); k++)
689 {
690 if ((modChs->Item(k)->m_TokenKind == tkSubroutine || modChs->Item(k)->m_TokenKind == tkFunction) &&
691 modChs->Item(k)->m_Name.IsSameAs(procName))
692 {
693 tk = modChs->Item(k)->m_TokenKind;
694 found = true;
695 break;
696 }
697 else if (modChs->Item(k)->m_TokenKind == tkInterfaceExplicit)
698 {
699 TokensArrayF* intfExpChs = &modChs->Item(k)->m_Children;
700 if (intfExpChs)
701 {
702 for (size_t m=0; m<intfExpChs->GetCount(); m++)
703 {
704 if ((intfExpChs->Item(m)->m_TokenKind == tkSubroutine || intfExpChs->Item(m)->m_TokenKind == tkFunction) &&
705 intfExpChs->Item(m)->m_Name.IsSameAs(procName))
706 {
707 tk = intfExpChs->Item(m)->m_TokenKind;
708 found = true;
709 break;
710 }
711 }
712 if (found)
713 break;
714 }
715 }
716 }
717
718 if (found)
719 {
720 if (tk == tkFunction)
721 chs->Item(j)->m_TypeDefinition = _T("function");
722 else
723 chs->Item(j)->m_TypeDefinition = _T("subroutine");
724 }
725 }
726 else if (chs->Item(j)->m_TokenKind == tkInterface)
727 genericProc.Add(chs->Item(j));
728 }
729
730 for (size_t k=0; k<genericProc.GetCount(); k++)
731 {
732 wxStringTokenizer tkz(genericProc.Item(k)->m_PartLast);
733 while (tkz.HasMoreTokens())
734 {
735 wxString pron = tkz.GetNextToken().Lower();
736 for (size_t j=0; j<chs->GetCount(); j++)
737 {
738 if (chs->Item(j)->m_TokenKind == tkProcedure && chs->Item(j)->m_Name.IsSameAs(pron))
739 {
740 genericProc.Item(k)->m_TypeDefinition = chs->Item(j)->m_TypeDefinition;
741 break;
742 }
743 }
744 break;
745 }
746 }
747 }
748
749 if (modToken->m_DocString.IsEmpty())
750 {
751 unsigned int ln = modToken->m_LineStart + modToken->m_DefinitionLength - 1;
752 docs.Clear();
753 GetDocBlock(docs, true, ln, true); // look bellow the declaration for the non-doxyblocks documentation.
754 if (docs.HasBrief() || docs.HasDescription())
755 modToken->m_DocString << docs.GetBrief() + m_Briefend + docs.GetDescription();
756 }
757 }
758
HandleSubmodule()759 void ParserThreadF::HandleSubmodule()
760 {
761 TokenF* old_parent = m_pLastParent;
762 unsigned int defStartLine = m_Tokens.GetLineNumber();
763 wxString ancestorModule;
764 wxString parentSubmodule;
765 wxString submName;
766
767 wxString token = m_Tokens.GetTokenSameFortranLine();
768
769 if (!token.IsEmpty() && token(0,1).Matches(_T("(")))
770 {
771 token = token.Mid(1).BeforeFirst(')');
772 int i = token.Find(':');
773 if (i != wxNOT_FOUND)
774 {
775 ancestorModule = token.Mid(0,i).Trim().Trim(false);
776 if (i+1 < int(token.Length()))
777 parentSubmodule = token.Mid(i+1).Trim().Trim(false);
778 }
779 else
780 ancestorModule = token.Trim().Trim(false);
781
782 token = m_Tokens.GetTokenSameFortranLine();
783 if (!token.IsEmpty())
784 submName = token;
785 else
786 submName = _T("unnamed");
787 }
788 else if(token.IsEmpty())
789 submName = _T("unnamed");
790 else
791 submName = token;
792
793 SubmoduleTokenF* pSubmodToken = DoAddSubmoduleToken(submName, ancestorModule, parentSubmodule, defStartLine);
794 m_pLastParent = pSubmodToken;
795
796 while (1)
797 {
798 token = m_Tokens.GetToken();
799 if (token.IsEmpty())
800 break;
801 wxString tok_low = token.Lower();
802
803 wxString next = m_Tokens.PeekToken();
804 wxString nex_low = next.Lower();
805 if ( ((m_Tokens.GetLineNumber() == m_Tokens.GetPeekedLineNumber()) && IsEnd(tok_low, nex_low)) ||
806 ((m_Tokens.GetLineNumber() != m_Tokens.GetPeekedLineNumber()) && IsEnd(tok_low, _T(""))) )
807 {
808 m_Tokens.SkipToOneOfChars(";", true);
809 break;
810 }
811 else if (tok_low.Matches(_T("type")) && !nex_low(0,1).Matches(_T("(")))
812 {
813 HandleType();
814 }
815 else if (tok_low.Matches(_T("subroutine")))
816 {
817 HandleFunction(tkSubroutine);
818 }
819 else if (tok_low.Matches(_T("function")))
820 {
821 HandleFunction(tkFunction);
822 }
823 else if (tok_low.Matches(_T("use")))
824 {
825 HandleUse();
826 }
827 else if (tok_low.Matches(_T("interface")))
828 {
829 HandleInterface();
830 }
831 else if (tok_low.Matches(_T("include")))
832 {
833 HandleInclude();
834 }
835 else if (tok_low.GetChar(0) == '#')
836 {
837 HandlePPDirective(token);
838 }
839 else if (tok_low.Matches(_T("module")) && nex_low.Matches(_T("procedure")))
840 {
841 m_Tokens.GetToken();
842 HandleSubmoduleProcedure();
843 }
844 else
845 {
846 bool needDefault=true;
847 bool hasFunctionInLine;
848 TokensArrayF tokTmpArr;
849 CheckParseOneDeclaration(token, tok_low, next, nex_low, needDefault, tokTmpArr, hasFunctionInLine);
850 }
851 }
852 pSubmodToken->AddLineEnd(m_Tokens.GetLineNumber());
853 m_pLastParent = old_parent;
854 }
855
DoAddModuleToken(const wxString & modName)856 ModuleTokenF* ParserThreadF::DoAddModuleToken(const wxString& modName)
857 {
858 ModuleTokenF* newToken = new ModuleTokenF();
859 newToken->m_Name = modName.Lower();
860
861 newToken->m_TokenKind = tkModule;
862 newToken->m_pParent = m_pLastParent;
863 newToken->m_Filename = m_Tokens.GetFilename();
864 newToken->m_DisplayName = modName;
865 newToken->m_TypeDefinition = wxEmptyString;
866
867 newToken->m_LineStart = m_Tokens.GetLineNumber();
868 newToken->m_DefinitionLength = 1;
869
870 if (m_pLastParent)
871 {
872 m_pLastParent->AddChild(newToken);
873 }
874 else
875 {
876 m_pTokens->Add(newToken);
877 }
878
879 return newToken;
880 }
881
DoAddSubmoduleToken(const wxString & submName,const wxString & ancestorModule,const wxString & parentSubmodule,unsigned int defStartLine)882 SubmoduleTokenF* ParserThreadF::DoAddSubmoduleToken(const wxString& submName, const wxString& ancestorModule,
883 const wxString& parentSubmodule, unsigned int defStartLine)
884 {
885 SubmoduleTokenF* newToken = new SubmoduleTokenF();
886 newToken->m_Name = ancestorModule.Lower();
887 newToken->m_Name << _T(":") << submName.Lower();
888 newToken->m_TokenKind = tkSubmodule;
889 newToken->m_pParent = m_pLastParent;
890 newToken->m_Filename = m_Tokens.GetFilename();
891 newToken->m_DisplayName = submName;
892 newToken->m_DisplayName << _T(" (") << ancestorModule;
893 if (!parentSubmodule.IsEmpty())
894 newToken->m_DisplayName << _T(":") << parentSubmodule;
895 newToken->m_DisplayName << _T(")");
896 newToken->m_TypeDefinition = wxEmptyString;
897
898 newToken->m_LineStart = defStartLine;
899 newToken->m_DefinitionLength = 1;
900
901 newToken->m_AncestorModuleName = ancestorModule.Lower();
902 newToken->m_ParentSubmoduleName = parentSubmodule.Lower();
903
904 if (m_pLastParent)
905 m_pLastParent->AddChild(newToken);
906 else
907 m_pTokens->Add(newToken);
908 //
909 // TokenF* oldParent = m_pLastParent;
910 // m_pLastParent = newToken;
911 // wxString useName = ancestorModule.Lower();
912 // useName << _T(":") << parentSubmodule.Lower();
913 // UseTokenF* pUseTok = DoAddUseToken(useName);
914 // pUseTok->SetModuleNature(mnNonIntrinsic);
915 // m_pLastParent = oldParent;
916
917 return newToken;
918 }
919
HandleType()920 void ParserThreadF::HandleType()
921 {
922 bool needDefault;
923 TokenF* newToken = 0;
924 HandleType(needDefault, newToken);
925 }
926
HandleType(bool & needDefault,TokenF * & newToken)927 void ParserThreadF::HandleType(bool& needDefault, TokenF* &newToken)
928 {
929 needDefault = true;
930 TokenAccessKind taKind = taPublic;
931 wxString typeName;
932 wxString exTypeName;
933 wxArrayString lineTok = m_Tokens.GetTokensToEOL();
934 wxArrayString lineTokLw;
935 wxString wholeLine;
936 bool isAbstract = false;
937 MakeArrayStringLower(lineTok, lineTokLw);
938 int idx = lineTok.Index(_T("::"));
939 if (idx != wxNOT_FOUND)
940 {
941 if (idx+1 < int(lineTok.GetCount()))
942 {
943 typeName = lineTok.Item(idx+1);
944 int idex = lineTokLw.Index(_T("extends"),false);
945 if (idex != wxNOT_FOUND)
946 {
947 if (idex <= idx-2)
948 {
949 wxString ex = lineTok.Item(idex+1);
950 int idx_a = ex.Find('(');
951 int idx_b = ex.Find(')', true);
952 if ( idx_a != wxNOT_FOUND && idx_b != wxNOT_FOUND && idx_a < (idx_b-1) )
953 {
954 exTypeName = ex.Mid(idx_a+1,idx_b-idx_a-1).Trim().Trim(false);
955 }
956 }
957 }
958
959 idex = lineTokLw.Index(_T("private"));
960 if (idex != wxNOT_FOUND && idex < idx)
961 {
962 taKind = taPrivate;
963 needDefault = false;
964 }
965 else
966 {
967 idex = lineTokLw.Index(_T("public"));
968 if (idex != wxNOT_FOUND && idex < idx)
969 {
970 taKind = taPublic;
971 needDefault = false;
972 }
973 }
974
975 idex = lineTokLw.Index(_T("abstract"));
976 if (idex != wxNOT_FOUND && idex < idx)
977 {
978 isAbstract = true;
979 }
980 }
981 else
982 {
983 //something wrong
984 return;
985 }
986
987 for (int i=0; i<idx; i++)
988 {
989 if (lineTokLw.Item(i+1).StartsWith(_T("(")) || i+1 == idx)
990 wholeLine << lineTokLw.Item(i);
991 else
992 wholeLine << lineTokLw.Item(i) << _T(",");
993
994 }
995 wholeLine << _T("::");
996 for (size_t i=idx+1; i<lineTokLw.size(); i++)
997 wholeLine << lineTokLw.Item(i);
998 }
999 else
1000 {
1001 if (lineTok.GetCount() > 0)
1002 {
1003 typeName = lineTok.Item(0);
1004 }
1005 else
1006 {
1007 //something wrong
1008 return;
1009 }
1010 for (size_t i=0; i<lineTokLw.size(); i++)
1011 wholeLine << _T(" ") << lineTokLw.Item(i);
1012 }
1013 TokenF* old_parent = m_pLastParent;
1014 m_pLastParent = DoAddToken(tkType, typeName);
1015 m_pLastParent->m_ExtendsType = exTypeName;
1016 m_pLastParent->m_TokenAccess = taKind;
1017 m_pLastParent->m_IsAbstract = isAbstract;
1018 m_pLastParent->m_TypeDefinition = wholeLine;
1019
1020 // Parse documentation
1021 DocBlock docs;
1022 GetDocBlock(docs, false, m_pLastParent->m_LineStart, true);
1023 if (docs.HasBrief() || docs.HasDescription())
1024 m_pLastParent->m_DocString << docs.GetBrief() + m_Briefend + docs.GetDescription();
1025
1026 ParseDeclarations(true, true);
1027
1028 if (m_LastTokenName.IsSameAs(_T("contains")))
1029 ParseTypeBoundProcedures(wxEmptyString, false);
1030
1031 if (m_pLastParent->m_DocString.IsEmpty())
1032 {
1033 docs.Clear();
1034 GetDocBlock(docs, true, m_pLastParent->m_LineStart, true); // look bellow the declaration for the non-doxyblocks documentation.
1035 if (docs.HasBrief() || docs.HasDescription())
1036 m_pLastParent->m_DocString << docs.GetBrief() + m_Briefend + docs.GetDescription();
1037 }
1038
1039 m_pLastParent->AddLineEnd(m_Tokens.GetLineNumber());
1040 newToken = m_pLastParent;
1041 m_pLastParent = old_parent;
1042 }
1043
CheckParseOneDeclaration(wxString & token,wxString & tok_low,wxString & next,wxString & next_low,bool & needDefault,TokensArrayF & newTokenArr,bool & hasFunctionInLine)1044 void ParserThreadF::CheckParseOneDeclaration(wxString& token, wxString& tok_low, wxString& next, wxString& next_low,
1045 bool& needDefault, TokensArrayF& newTokenArr, bool& hasFunctionInLine)
1046 {
1047 hasFunctionInLine = false;
1048 if ( tok_low.IsSameAs(_T("integer")) || tok_low.IsSameAs(_T("real"))
1049 || tok_low.IsSameAs(_T("doubleprecision")) || tok_low.IsSameAs(_T("character"))
1050 || tok_low.IsSameAs(_T("complex")) || tok_low.IsSameAs(_T("logical"))
1051 || ( tok_low.IsSameAs(_T("double")) && next_low.IsSameAs(_T("precision")) )
1052 || ( tok_low.IsSameAs(_T("type")) && next_low.StartsWith(_T("(")) )
1053 || ( tok_low.IsSameAs(_T("class")) && next_low.StartsWith(_T("(")) )
1054 || tok_low.IsSameAs(_T("enumerator"))
1055 )
1056 {
1057 wxArrayString lineTok = m_Tokens.PeekTokensToEOL();
1058 if (lineTok.Index(_T("function"), false) == wxNOT_FOUND)
1059 {
1060 DocBlock docs;
1061 GetDocBlock(docs, false, m_Tokens.GetLineNumber(), false);
1062
1063 bool found = ParseDeclarationsFirstPart(token, next);
1064 if (found)
1065 {
1066 int ntold = newTokenArr.size();
1067 ParseDeclarationsSecondPart(token, needDefault, newTokenArr);
1068
1069 int ntnew = newTokenArr.size();
1070 if ((ntnew-ntold) > 0 && (docs.HasDescription() || docs.HasBrief()))
1071 {
1072 for (int i=ntold; i<ntnew; i++)
1073 {
1074 if (newTokenArr.Item(i)->m_DocString.IsEmpty())
1075 newTokenArr.Item(i)->m_DocString << docs.GetBrief() + m_Briefend + docs.GetDescription();
1076 }
1077 }
1078 }
1079 }
1080 else
1081 {
1082 hasFunctionInLine = true;
1083 }
1084 }
1085 }
1086
1087
ParseDeclarations(bool breakAtEnd,bool breakAtContains)1088 void ParserThreadF::ParseDeclarations(bool breakAtEnd, bool breakAtContains)
1089 {
1090 TokenAccessKind taDefKind = taPublic;
1091 TokensArrayF tokArr;
1092 while (1)
1093 {
1094 wxString token = m_Tokens.GetToken();
1095 m_LastTokenName = token.Lower();
1096 wxString next = m_Tokens.PeekToken();
1097 if (m_LastTokenName.IsEmpty())
1098 {
1099 break;
1100 }
1101 else if (m_LastTokenName.IsSameAs(_T("include")))
1102 {
1103 HandleInclude();
1104 }
1105 else if (m_LastTokenName.GetChar(0) == '#')
1106 {
1107 HandlePPDirective(token);
1108 }
1109 else if (m_LastTokenName.IsSameAs(_T("interface")))
1110 {
1111 HandleInterface(taDefKind);
1112 }
1113 else if (breakAtEnd &&
1114 ( ((m_Tokens.GetLineNumber() == m_Tokens.GetPeekedLineNumber()) && IsEnd(m_LastTokenName, next.Lower())) ||
1115 ((m_Tokens.GetLineNumber() != m_Tokens.GetPeekedLineNumber()) && IsEnd(m_LastTokenName, _T(""))) ))
1116 {
1117 m_Tokens.SkipToOneOfChars(";", true);
1118 break;
1119 }
1120 else if (breakAtContains && m_LastTokenName.IsSameAs(_T("contains")))
1121 {
1122 m_Tokens.SkipToOneOfChars(";", true);
1123 break;
1124 }
1125 else if (m_LastTokenName.IsSameAs(_T("private")))
1126 {
1127 bool changeDefault;
1128 int cal=0;
1129 wxArrayString pnList;
1130 HandleAccessList(taPrivate, changeDefault, cal, pnList);
1131 if (changeDefault)
1132 {
1133 taDefKind = taPrivate;
1134 }
1135 }
1136 else if (m_LastTokenName.IsSameAs(_T("public")))
1137 {
1138 bool changeDefault;
1139 int cal=0;
1140 wxArrayString pnList;
1141 HandleAccessList(taPublic, changeDefault, cal, pnList);
1142 if (changeDefault)
1143 {
1144 taDefKind = taPublic;
1145 }
1146 }
1147 else if (m_LastTokenName.IsSameAs(_T("block")) && !next.Lower().IsSameAs(_T("data")))
1148 {
1149 HandleBlockConstruct();
1150 }
1151 else if (m_LastTokenName.IsSameAs(_T("procedure")))
1152 {
1153 ParseTypeBoundProcedures(m_LastTokenName, true, false);
1154 }
1155
1156 wxArrayString lineTok = m_Tokens.PeekTokensToEOL();
1157 int funIdx = lineTok.Index(_T("function"), false);
1158 if (funIdx == wxNOT_FOUND || (funIdx > 2))
1159 {
1160 DocBlock docs;
1161 GetDocBlock(docs, false, m_Tokens.GetLineNumber(), false);
1162
1163 bool found = ParseDeclarationsFirstPart(token, next);
1164 if (found)
1165 {
1166 bool nDef=true;
1167 TokensArrayF tokArrTmp;
1168 ParseDeclarationsSecondPart(token, nDef, tokArrTmp);
1169 if (nDef)
1170 {
1171 for (size_t i=0; i<tokArrTmp.Count(); i++)
1172 {
1173 tokArr.Add(tokArrTmp.Item(i));
1174 }
1175 }
1176 int tac = tokArrTmp.Count();
1177 if (tac > 0 && (docs.HasDescription() || docs.HasBrief()))
1178 {
1179 for (int i=0; i<tac; i++)
1180 {
1181 if (tokArrTmp.Item(i)->m_DocString.IsEmpty())
1182 tokArrTmp.Item(i)->m_DocString << docs.GetBrief() + m_Briefend + docs.GetDescription();
1183 }
1184 }
1185 }
1186 }
1187 }
1188 for (size_t i=0; i<tokArr.Count(); i++)
1189 {
1190 tokArr.Item(i)->m_TokenAccess = taDefKind;
1191 }
1192 return;
1193 }
1194
1195
ParseDeclarationsFirstPart(wxString & token,wxString & next)1196 bool ParserThreadF::ParseDeclarationsFirstPart(wxString& token, wxString& next)
1197 {
1198 wxString tok_low = token.Lower();
1199 wxString next_low = next.Lower();
1200 bool found = false;
1201
1202 if ( tok_low.IsSameAs(_T("integer")) || tok_low.IsSameAs(_T("real"))
1203 || tok_low.IsSameAs(_T("doubleprecision")) || tok_low.IsSameAs(_T("character"))
1204 || tok_low.IsSameAs(_T("complex")) || tok_low.IsSameAs(_T("logical"))
1205 || tok_low.IsSameAs(_T("enumerator")) )
1206 {
1207 if (next_low.StartsWith(_T("(")))
1208 {
1209 token.Append(next);
1210 m_Tokens.GetToken();
1211 }
1212 else if (next_low.StartsWith(_T("*")))
1213 {
1214 token.Append(m_Tokens.GetToken());
1215 token.Append(m_Tokens.GetTokenSameFortranLine());
1216 }
1217 found = true;
1218 }
1219 else if (tok_low.IsSameAs(_T("double")))
1220 {
1221 if (next_low.IsSameAs(_T("precision")))
1222 {
1223 found = true;
1224 token.Append(_T(" "));
1225 token.Append(next);
1226 m_Tokens.GetToken();
1227 next = m_Tokens.PeekToken();
1228 if (next.StartsWith(_T("(")))
1229 {
1230 token.Append(next);
1231 m_Tokens.GetToken();
1232 }
1233 }
1234 }
1235 else if (tok_low.IsSameAs(_T("type")) || tok_low.IsSameAs(_T("class")))
1236 {
1237 if (next_low.StartsWith(_T("(")))
1238 {
1239 if (next_low.EndsWith(_T(")")))
1240 {
1241 wxString token_s = m_Tokens.GetToken();
1242 token_s = token_s.Mid(1,token_s.Len()-2).Trim().Trim(false);
1243 token.Append(_T("("));
1244 token.Append(token_s);
1245 token.Append(_T(")"));
1246 found = true;
1247 }
1248 else
1249 {
1250 //something wrong
1251 m_Tokens.SkipToOneOfChars(";", true);
1252 }
1253 }
1254 else if (tok_low.IsSameAs(_T("type")) && !next_low.IsSameAs(_T("is")))
1255 {
1256 // we found type definition
1257 HandleType();
1258 }
1259 }
1260 return found;
1261 }
1262
1263
ParseDeclarationsSecondPart(wxString & token,bool & needDefault,TokensArrayF & newTokenArr)1264 void ParserThreadF::ParseDeclarationsSecondPart(wxString& token, bool& needDefault, TokensArrayF& newTokenArr)
1265 {
1266 needDefault = true;
1267 TokenAccessKind taKind = taPublic;
1268 wxString defT = token;
1269 wxString dims;
1270 wxArrayString linesArr;
1271 m_Tokens.SetDetailedParsing(true);
1272 wxArrayString lineTok = m_Tokens.GetTokensToEOL(&linesArr);
1273 m_Tokens.SetDetailedParsing(false);
1274 int idx = lineTok.Index(_T("::"));
1275 if (idx != wxNOT_FOUND)
1276 {
1277 for (int i=0; i<idx; i++)
1278 {
1279 if (lineTok.Item(i).IsSameAs(_T(",")))
1280 continue;
1281
1282 if (!lineTok.Item(i).StartsWith(_T("(")))
1283 {
1284 defT.Append(_T(", "));
1285 }
1286 defT.Append(lineTok.Item(i));
1287
1288 wxString tokLw = lineTok.Item(i).Lower();
1289 if (tokLw.IsSameAs(_T("private")))
1290 {
1291 taKind = taPrivate;
1292 needDefault = false;
1293 }
1294 else if (tokLw.IsSameAs(_T("protected")))
1295 {
1296 taKind = taProtected;
1297 needDefault = false;
1298 }
1299 else if (tokLw.IsSameAs(_T("public")))
1300 {
1301 taKind = taPublic;
1302 needDefault = false;
1303 }
1304
1305 if (tokLw.IsSameAs(_T("dimension")) && lineTok.Item(i+1).StartsWith(_T("(")))
1306 {
1307 dims.Append(lineTok.Item(i+1));
1308 }
1309 }
1310 }
1311 else // "::" not found
1312 {
1313 if (lineTok.GetCount() > 0 && lineTok.Item(0).IsSameAs(_T(",")))
1314 {
1315 // it is unfinished declaration (e.g. "real, pointer, ")
1316 return;
1317 }
1318 idx = -1;
1319 }
1320
1321 wxArrayString varNames;
1322 wxArrayString varArgs;
1323 wxArrayString varComs;
1324 wxArrayString varDims;
1325 for (size_t i=idx+1; i<lineTok.GetCount(); )
1326 {
1327 wxString var1= lineTok.Item(i);
1328 if (var1.IsSameAs(_T(",")))
1329 {
1330 i++;
1331 continue;
1332 }
1333 wxString arg1;
1334 wxString dim1;
1335 while (i+1 < lineTok.GetCount())
1336 {
1337 wxString s = lineTok.Item(i+1);
1338 if ((s.StartsWith(_T("(")) && s.EndsWith(_T(")"))) || (s.StartsWith(_T("[")) && s.EndsWith(_T("]"))))
1339 {
1340 arg1 << s;
1341 i++;
1342 }
1343 else
1344 break;
1345 }
1346 dim1 << arg1;
1347 if (i+1 < lineTok.GetCount() && (lineTok.Item(i+1).IsSameAs(_T("=>")) || lineTok.Item(i+1).IsSameAs(_T("="))
1348 || lineTok.Item(i+1).IsSameAs(_T("*"))) )
1349 {
1350 i += 1;
1351 for (; i<lineTok.GetCount(); i++)
1352 {
1353 if (lineTok.Item(i).IsSameAs(_T(",")))
1354 break;
1355 else
1356 arg1 << lineTok.Item(i);
1357 }
1358 if(i >= lineTok.GetCount())
1359 {
1360 i = lineTok.GetCount() - 1;
1361 }
1362 }
1363 wxString comStr = linesArr.Item(i).AfterFirst('!');
1364 if (comStr.StartsWith(_T("<")) || comStr.StartsWith(_T(">")))
1365 comStr = comStr.Mid(1);
1366 comStr = comStr.Trim(true).Trim(false);
1367
1368 varNames.Add(var1);
1369 varArgs.Add(arg1);
1370 varComs.Add(comStr);
1371 if (dim1.IsEmpty())
1372 varDims.Add(dims);
1373 else
1374 varDims.Add(dim1);
1375 i++;
1376 }
1377 for (size_t i=0; i<varNames.GetCount(); i++)
1378 {
1379 TokenF* tok = DoAddToken(tkVariable, varNames[i], varArgs[i], defT);
1380 tok->m_DocString = varComs.Item(i);
1381 tok->m_TokenAccess = taKind;
1382 tok->AddLineEnd(tok->m_LineStart);
1383 if (varDims.Item(i).IsEmpty())
1384 {
1385 tok->AddPartFirst(token);
1386 }
1387 else
1388 {
1389 wxString tokStr = token + _T(", ") + varDims.Item(i);
1390 tok->AddPartFirst(tokStr);
1391 }
1392 newTokenArr.Add(tok);
1393 }
1394 return;
1395 }
1396
1397
HandleSubmoduleProcedure()1398 void ParserThreadF::HandleSubmoduleProcedure()
1399 {
1400 wxString token;
1401 token = m_Tokens.GetTokenSameFortranLine();
1402
1403 TokenF* old_parent = m_pLastParent;
1404 m_pLastParent = DoAddToken(tkProcedure, token);
1405
1406 GoThroughBody();
1407
1408 m_pLastParent->AddLineEnd(m_Tokens.GetLineNumber());
1409 m_pLastParent = old_parent;
1410 }
1411
1412
HandleFunction(TokenKindF kind,TokenAccessKind taKind)1413 void ParserThreadF::HandleFunction(TokenKindF kind, TokenAccessKind taKind)
1414 {
1415 m_ParentDocs.Clear();
1416 unsigned int ln = m_Tokens.GetLineNumber();
1417 GetDocBlock(m_ParentDocs, false, ln, true);
1418
1419 wxString token;
1420 token = m_Tokens.GetTokenSameFortranLine();
1421
1422 if (token.IsEmpty() && kind == tkProgram)
1423 token = _T("unnamed");
1424
1425 unsigned int defStartLine = m_Tokens.GetLineNumber();
1426 TokenF* old_parent = m_pLastParent;
1427 wxString args = m_Tokens.PeekTokenSameFortranLine();
1428
1429 if (args.IsEmpty() || !args(0,1).Matches(_T("(")))
1430 args = _T("()");
1431 else
1432 args = m_Tokens.GetTokenSameFortranLine();
1433 m_pLastParent = DoAddToken(kind, token, args, defStartLine);
1434 m_pLastParent->m_TokenAccess = taKind;
1435 if (m_ParentDocs.HasBrief() || m_ParentDocs.HasDescription())
1436 m_pLastParent->m_DocString << m_ParentDocs.GetBrief() + m_Briefend + m_ParentDocs.GetDescription();
1437
1438 if (kind == tkFunction)
1439 {
1440 wxString funkLine = m_Tokens.GetLineFortran();
1441 wxString funkLineLow = funkLine.Lower();
1442 int i_fun = funkLineLow.Find(_T("function"));
1443 if (i_fun != wxNOT_FOUND)
1444 {
1445 m_pLastParent->AddPartFirst(funkLine.Mid(0,i_fun).Trim().Trim(false));
1446 wxString secPart = funkLine.Mid(i_fun+8);
1447 i_fun = secPart.Find(')');
1448 if (i_fun != wxNOT_FOUND && (int)secPart.Len() > i_fun+1)
1449 {
1450 wxString lastPart = secPart.Mid(i_fun+1).Trim().Trim(false);
1451 m_pLastParent->AddPartLast(lastPart);
1452 wxString lastPartLow = lastPart.Lower();
1453 i_fun = lastPartLow.Find(_T("result"));
1454 if (i_fun != wxNOT_FOUND)
1455 {
1456 wxString el = lastPartLow.Mid(i_fun+6);
1457 int is = el.Find('(');
1458 int ie = el.Find(')');
1459 if (is != wxNOT_FOUND && ie != wxNOT_FOUND && ie > is)
1460 m_pLastParent->AddResultVariable(el.Mid(is+1,ie-is-1).Trim().Trim(false));
1461 }
1462 }
1463 }
1464 }
1465 GoThroughBody();
1466 m_pLastParent->AddLineEnd(m_Tokens.GetLineNumber());
1467 AddParamDocs(m_pLastParent, m_ParentDocs);
1468
1469 if (m_pLastParent->m_DocString.IsEmpty())
1470 {
1471 ln = m_pLastParent->m_LineStart + m_pLastParent->m_DefinitionLength - 1;
1472 DocBlock doc;
1473 GetDocBlock(doc, true, ln, true); // look bellow the declaration for the non-doxyblocks documentation.
1474 if (doc.HasBrief() || doc.HasDescription())
1475 m_pLastParent->m_DocString << doc.GetBrief() + m_Briefend + doc.GetDescription();
1476 }
1477
1478 m_pLastParent = old_parent;
1479 }
1480
1481
HandleBlockConstruct()1482 void ParserThreadF::HandleBlockConstruct()
1483 {
1484 unsigned int defStartLine = m_Tokens.GetLineNumber();
1485 TokenF* old_parent = m_pLastParent;
1486 m_NumberOfBlockConstruct += 1;
1487 wxString name = _T("%%tkBlockConstruct");
1488 name << wxString::Format(_T("%.3d"), m_NumberOfBlockConstruct);
1489 m_pLastParent = DoAddToken(tkBlockConstruct, name, wxEmptyString, defStartLine);
1490
1491 GoThroughBody();
1492 m_pLastParent->AddLineEnd(m_Tokens.GetLineNumber());
1493 m_pLastParent = old_parent;
1494 }
1495
1496
HandleAssociateConstruct()1497 void ParserThreadF::HandleAssociateConstruct()
1498 {
1499 TokenF* old_parent = m_pLastParent;
1500 wxString args = m_Tokens.PeekTokenSameFortranLine();
1501
1502 if (args.IsEmpty() || !args(0,1).Matches(_T("(")))
1503 args = _T("()");
1504 else
1505 args = m_Tokens.GetTokenSameFortranLine();
1506 m_pLastParent = DoAddToken(tkAssociateConstruct, wxEmptyString, args, wxEmptyString);
1507
1508 GoThroughBody();
1509 m_pLastParent->AddLineEnd(m_Tokens.GetLineNumber());
1510 m_pLastParent = old_parent;
1511 }
1512
1513
HandleSelectTypeConstruct()1514 void ParserThreadF::HandleSelectTypeConstruct()
1515 {
1516 TokenF* old_parent = m_pLastParent;
1517 wxString args = m_Tokens.PeekTokenSameFortranLine();
1518 if (args.IsEmpty() || !args(0,1).Matches(_T("(")))
1519 args = _T("()");
1520 else
1521 args = m_Tokens.GetTokenSameFortranLine();
1522
1523 while (1)
1524 {
1525 wxString token = m_Tokens.GetToken();
1526 if (token.IsEmpty())
1527 break;
1528
1529 wxString tok_low = token.Lower();
1530 wxString next = m_Tokens.PeekToken();
1531 wxString nex_low = next.Lower();
1532
1533 if ( (tok_low.Matches(_T("end")) && nex_low.Matches(_T("select"))) || tok_low.Matches(_T("endselect")) )
1534 {
1535 m_Tokens.SkipToOneOfChars(";", true);
1536 break;
1537 }
1538 else if ( (tok_low.Matches(_T("type")) && nex_low.Matches(_T("is"))) ||
1539 (tok_low.Matches(_T("class")) && nex_low.Matches(_T("is"))) )
1540 {
1541 wxString defstr = tok_low;
1542 if (m_Tokens.GetToken().IsEmpty())
1543 break;
1544 next = m_Tokens.PeekToken();
1545 nex_low = next.Lower();
1546 if (nex_low.StartsWith(_T("(")))
1547 defstr << nex_low;
1548
1549 m_pLastParent = DoAddToken(tkSelectTypeChild, wxEmptyString, args, defstr);
1550 GoThroughBody();
1551 m_pLastParent->AddLineEnd(m_Tokens.GetLineNumber());
1552 m_pLastParent = old_parent;
1553 }
1554 else if (tok_low.Matches(_T("class")) && nex_low.Matches(_T("default")))
1555 {
1556 m_pLastParent = DoAddToken(tkSelectTypeDefault, wxEmptyString, args, wxEmptyString);
1557 GoThroughBody();
1558 m_pLastParent->AddLineEnd(m_Tokens.GetLineNumber());
1559 m_pLastParent = old_parent;
1560 }
1561 else if (tok_low.Matches(_T("include")))
1562 {
1563 HandleInclude();
1564 }
1565 else if (tok_low.GetChar(0) == '#')
1566 {
1567 HandlePPDirective(token);
1568 }
1569 }
1570 m_pLastParent = old_parent;
1571 }
1572
1573
HandleSelectCaseConstruct()1574 void ParserThreadF::HandleSelectCaseConstruct()
1575 {
1576 // we are not interesting in SelectCase, but we need to catch EndSelect
1577 GoThroughBody();
1578 m_Tokens.GetToken();
1579 m_Tokens.SkipToOneOfChars(";", true);
1580 }
1581
1582
HandleInterface(TokenAccessKind taKind)1583 void ParserThreadF::HandleInterface(TokenAccessKind taKind)
1584 {
1585 TokenF* tokTmp = 0;
1586 bool isGeneric;
1587 HandleInterface(taKind, tokTmp, isGeneric);
1588 }
1589
HandleInterface(TokenAccessKind taKind,TokenF * & tokNew,bool & isGeneric)1590 void ParserThreadF::HandleInterface(TokenAccessKind taKind, TokenF* &tokNew, bool &isGeneric)
1591 {
1592 isGeneric = false;
1593 TokenF* old_parent = m_pLastParent;
1594 unsigned int defStartLine = m_Tokens.GetLineNumber();
1595 wxArrayString curLineArr = m_Tokens.GetTokensToEOL();
1596 wxString name;
1597 TokenKindF tokKin;
1598 if (curLineArr.GetCount() > 0)
1599 {
1600 wxString low = curLineArr.Item(0).Lower();
1601 if (low.IsSameAs(_T("operator")))
1602 {
1603 name.Append(_T("%%"));
1604 name.Append(curLineArr.Item(0));
1605 for (unsigned int i=1; i<curLineArr.GetCount(); i++)
1606 {
1607 name.Append(_T(" "));
1608 name.Append(curLineArr.Item(i));
1609 }
1610 m_InterfaceOperator += 1;
1611 if (m_InterfaceOperator > 1)
1612 {
1613 name << _T(" #") << m_InterfaceOperator;
1614 }
1615 }
1616 else if (low.IsSameAs(_T("assignment")))
1617 {
1618 name.Append(_T("%%"));
1619 name.Append(curLineArr.Item(0));
1620 for (unsigned int i=1; i<curLineArr.GetCount(); i++)
1621 {
1622 name.Append(_T(" "));
1623 name.Append(curLineArr.Item(i));
1624 }
1625 m_InterfaceAssignment += 1;
1626 if (m_InterfaceAssignment > 1)
1627 {
1628 name << _T(" #") << m_InterfaceAssignment;
1629 }
1630 }
1631 else if (low.IsSameAs(_T("read")))
1632 {
1633 name.Append(_T("%%"));
1634 name.Append(curLineArr.Item(0));
1635 for (unsigned int i=1; i<curLineArr.GetCount(); i++)
1636 {
1637 name.Append(_T(" "));
1638 name.Append(curLineArr.Item(i));
1639 }
1640 m_InterfaceRead += 1;
1641 if (m_InterfaceRead > 1)
1642 {
1643 name << _T(" #") << m_InterfaceRead;
1644 }
1645 }
1646 else if (low.IsSameAs(_T("write")))
1647 {
1648 name.Append(_T("%%"));
1649 name.Append(curLineArr.Item(0));
1650 for (unsigned int i=1; i<curLineArr.GetCount(); i++)
1651 {
1652 name.Append(_T(" "));
1653 name.Append(curLineArr.Item(i));
1654 }
1655 m_InterfaceWrite += 1;
1656 if (m_InterfaceWrite > 1)
1657 {
1658 name << _T(" #") << m_InterfaceWrite;
1659 }
1660 }
1661 else
1662 {
1663 // generic procedure name
1664 name.Append(curLineArr.Item(0));
1665 for (unsigned int i=1; i<curLineArr.GetCount(); i++)
1666 {
1667 name.Append(_T(" "));
1668 name.Append(curLineArr.Item(i));
1669 }
1670 isGeneric = true;
1671 }
1672 tokKin = tkInterface;
1673 }
1674 else
1675 {
1676 tokKin = tkInterfaceExplicit;
1677 }
1678
1679 m_pLastParent = DoAddToken(tokKin, name, wxEmptyString, defStartLine);
1680 m_pLastParent->m_TokenAccess = taKind;
1681 tokNew = m_pLastParent;
1682
1683 GoThroughBody();
1684
1685 if (tokKin == tkInterfaceExplicit)
1686 {
1687 TokensArrayF* toks = &m_pLastParent->m_Children;
1688 if (toks)
1689 {
1690 for (size_t i=0; i<toks->GetCount(); i++)
1691 {
1692 toks->Item(i)->m_TokenAccess = taKind;
1693 }
1694 }
1695 }
1696
1697 m_pLastParent->AddLineEnd(m_Tokens.GetLineNumber());
1698
1699 if (isGeneric)
1700 {
1701 // Parse documentation
1702 DocBlock docs;
1703 GetDocBlock(docs, false, m_pLastParent->m_LineStart, true);
1704 if (docs.HasBrief() || docs.HasDescription())
1705 m_pLastParent->m_DocString << docs.GetBrief() + m_Briefend + docs.GetDescription();
1706 else
1707 {
1708 docs.Clear();
1709 GetDocBlock(docs, true, m_pLastParent->m_LineStart, true); // look bellow the declaration for the non-doxyblocks documentation.
1710 if (docs.HasBrief() || docs.HasDescription())
1711 m_pLastParent->m_DocString << docs.GetBrief() + m_Briefend + docs.GetDescription();
1712 }
1713 }
1714
1715 m_pLastParent = old_parent;
1716 }
1717
HandleBlockData()1718 void ParserThreadF::HandleBlockData()
1719 {
1720 TokenF* old_parent = m_pLastParent;
1721 wxString token = m_Tokens.GetTokenSameLine();
1722 if (token.IsEmpty())
1723 m_pLastParent = DoAddToken(tkBlockData, _T("BD_unnamed"));
1724 else
1725 m_pLastParent = DoAddToken(tkBlockData, token);
1726
1727 while (1)
1728 {
1729 token = m_Tokens.GetToken();
1730 if (token.IsEmpty())
1731 break;
1732 wxString tok_low = token.Lower();
1733
1734 wxString next = m_Tokens.PeekToken();
1735 wxString nex_low = next.Lower();
1736 if ( ((m_Tokens.GetLineNumber() == m_Tokens.GetPeekedLineNumber()) && IsEnd(tok_low, nex_low)) ||
1737 ((m_Tokens.GetLineNumber() != m_Tokens.GetPeekedLineNumber()) && IsEnd(tok_low, _T(""))) )
1738 {
1739 m_Tokens.SkipToOneOfChars(";", true);
1740 break;
1741 }
1742 else if (tok_low.Matches(_T("include")))
1743 {
1744 HandleInclude();
1745 }
1746 else if (tok_low.GetChar(0) == '#')
1747 {
1748 HandlePPDirective(token);
1749 }
1750 }
1751 m_pLastParent->AddLineEnd(m_Tokens.GetLineNumber());
1752 m_pLastParent = old_parent;
1753 }
1754
HandleInclude()1755 void ParserThreadF::HandleInclude()
1756 {
1757 wxString token = m_Tokens.GetTokenSameFortranLine();
1758
1759 if (token.IsEmpty())
1760 return; // something wrong
1761 else if ((token.StartsWith(_T("\'")) || token.StartsWith(_T("\"")) || token.StartsWith(_T("<"))) &&
1762 (token.EndsWith(_T("\'")) || token.EndsWith(_T("\"")) || token.EndsWith(_T(">"))))
1763 {
1764 token = token.Mid(1,token.Len()-2).Trim().Trim(false);
1765 DoAddToken(tkInclude, token);
1766 m_IncludeList.Add(token);
1767 }
1768 else if (token.IsSameAs(_T("<")))
1769 {
1770 // Handle #include <filename.fpp>
1771 token = m_Tokens.GetTokenSameLine();
1772 if (m_Tokens.PeekTokenSameFortranLine().IsSameAs(_T(".")))
1773 {
1774 wxString point = m_Tokens.GetToken();
1775 token.Append(point + m_Tokens.GetTokenSameLine());
1776 }
1777 DoAddToken(tkInclude, token);
1778 m_IncludeList.Add(token);
1779 m_Tokens.SkipToEOL();
1780 }
1781 }
1782
HandlePPDirective(wxString & token)1783 void ParserThreadF::HandlePPDirective(wxString& token)
1784 {
1785 if (token.Matches(_T("#define")))
1786 HandlePPDefine();
1787 else if (token.Matches(_T("#undefine")))
1788 HandlePPUndefine();
1789 else if (token.Matches(_T("#if")) || token.Matches(_T("#ifdef")) || token.Matches(_T("#ifndef")))
1790 HandlePPIfdef(token);
1791 else if (token.Matches(_T("#endif")) || token.Matches(_T("#else")) || token.Matches(_T("#elif")))
1792 HandlePPIfdef(token);
1793 else if (token.Matches(_T("#include")))
1794 HandleInclude();
1795 else
1796 m_Tokens.SkipToEOL();
1797 }
1798
HandlePPDefine()1799 void ParserThreadF::HandlePPDefine()
1800 {
1801 // Handle #define ABC
1802 // More sophisticated cases isn't interpreted
1803 wxString token = m_Tokens.GetTokenSameLine();
1804
1805 if (token.IsEmpty())
1806 return; // something wrong
1807
1808 TokenF* newToken = new TokenF;
1809 newToken->m_TokenKind = tkMacroDefine;
1810 newToken->m_Filename = m_Tokens.GetFilename();
1811 newToken->m_DisplayName = token;
1812 newToken->m_LineStart = m_Tokens.GetLineNumber();
1813 newToken->m_LineEnd = 0;
1814
1815 m_pPPDefineTokens->Add(newToken);
1816 m_Tokens.SkipToEOL();
1817 }
1818
HandlePPUndefine()1819 void ParserThreadF::HandlePPUndefine()
1820 {
1821 // Handle #undefine ABC or #undef ABC
1822 wxString token = m_Tokens.GetTokenSameLine();
1823
1824 if (token.IsEmpty())
1825 return; // something wrong
1826
1827 for (size_t i=0; i<m_pPPDefineTokens->size(); ++i)
1828 {
1829 if (m_pPPDefineTokens->Item(i)->m_DisplayName == token)
1830 {
1831 m_pPPDefineTokens->Item(i)->m_LineEnd = m_Tokens.GetLineNumber();
1832 break;
1833 }
1834 }
1835 m_Tokens.SkipToEOL();
1836 }
1837
HandlePPIfdef(wxString & ifToken)1838 void ParserThreadF::HandlePPIfdef(wxString& ifToken)
1839 {
1840 // Handle #ifdef construct in the simplest cases.
1841 if (ifToken.IsSameAs(_T("#ifdef")) || ifToken.IsSameAs(_T("#ifndef")))
1842 {
1843 m_inIfdef += 1;
1844 wxString token = m_Tokens.GetTokenSameLine();
1845 if (token.IsEmpty())
1846 return;
1847
1848 bool hasDef = HasDefine(token, m_Tokens.GetLineNumber());
1849 if ((ifToken.IsSameAs(_T("#ifdef")) && hasDef) || (ifToken.IsSameAs(_T("#ifndef")) && !hasDef))
1850 {
1851 // Will be interpreted until correcponding #elif, #else or #endif
1852 }
1853 else
1854 {
1855 // Skip to the corresponding #elif #else or #endif
1856 m_Tokens.SkipToEOL();
1857 wxString lastTok;
1858 SkipPPIfdef(lastTok);
1859 if (lastTok.IsEmpty() || lastTok.IsSameAs(_T("#endif")))
1860 m_inIfdef -= 1;
1861 else if (lastTok.IsSameAs(_T("#elif")))
1862 HandlePPIfdef(lastTok);
1863 }
1864 }
1865 else if (ifToken.IsSameAs(_T("#if")) || ifToken.IsSameAs(_T("#elif")))
1866 {
1867 // More clever interpreter is required.
1868 // For now take as if defined in case of #if
1869 if (ifToken.IsSameAs(_T("#if")))
1870 {
1871 m_inIfdef += 1;
1872 }
1873 else
1874 {
1875 // Skip to the corresponding #endif
1876 wxString lastTok;
1877 while (true)
1878 {
1879 m_Tokens.SkipToEOL();
1880 SkipPPIfdef(lastTok);
1881 if (lastTok.IsEmpty() || lastTok.IsSameAs(_T("#endif")))
1882 break;
1883 }
1884 m_inIfdef -= 1;
1885 }
1886 }
1887 else if (ifToken.IsSameAs(_T("#else")))
1888 {
1889 // Skip to the corresponding #endif
1890 m_Tokens.SkipToEOL();
1891 wxString lastTok;
1892 SkipPPIfdef(lastTok);
1893 // here should be lastTok==#endif
1894 m_inIfdef -= 1;
1895 }
1896 else // #endif
1897 m_inIfdef -= 1;
1898
1899 m_Tokens.SkipToEOL();
1900 }
1901
HasDefine(const wxString & token,unsigned int lnum)1902 bool ParserThreadF::HasDefine(const wxString& token, unsigned int lnum)
1903 {
1904 size_t nDef = m_pPPDefineTokens->size();
1905 for (size_t i=0; i<nDef; ++i)
1906 {
1907 if (m_pPPDefineTokens->Item(i)->m_DisplayName.IsSameAs(token) &&
1908 (m_pPPDefineTokens->Item(i)->m_LineEnd == 0 ||
1909 m_pPPDefineTokens->Item(i)->m_LineEnd > lnum))
1910 {
1911 return true;
1912 }
1913 }
1914 return false;
1915 }
1916
SkipPPIfdef(wxString & tokenAtEnd)1917 void ParserThreadF::SkipPPIfdef(wxString& tokenAtEnd)
1918 {
1919 // Skip to the next corresponding #elif, #else or #endif
1920 tokenAtEnd.clear();
1921 int start_inIfdef = m_inIfdef;
1922 while (true)
1923 {
1924 wxString token = m_Tokens.GetToken();
1925 if (token.IsEmpty())
1926 break;
1927
1928 if (token.StartsWith(_T("#")))
1929 {
1930 if (token.IsSameAs(_T("#ifdef")) || token.IsSameAs(_T("#ifndef")))
1931 {
1932 m_inIfdef += 1;
1933 m_Tokens.SkipToEOL();
1934 }
1935 else if (m_inIfdef > start_inIfdef && token.IsSameAs(_T("#endif")))
1936 {
1937 m_inIfdef -= 1;
1938 m_Tokens.SkipToEOL();
1939 }
1940 else if (token.IsSameAs(_T("#define")))
1941 continue; //HandlePPDefine();
1942 else if (token.IsSameAs(_T("#undefine")) || token.IsSameAs(_T("#undef")))
1943 continue; //HandlePPUndefine();
1944 else if (m_inIfdef == start_inIfdef)
1945 {
1946 tokenAtEnd = token;
1947 break;
1948 }
1949 }
1950 else
1951 m_Tokens.SkipToEOL();
1952 }
1953 m_Tokens.SkipToEOL();
1954 }
1955
HandleAccessList(TokenAccessKind taKind,bool & changeDefault,int & countAccess,wxArrayString & nameList)1956 void ParserThreadF::HandleAccessList(TokenAccessKind taKind, bool& changeDefault, int& countAccess, wxArrayString& nameList)
1957 {
1958 changeDefault = false;
1959 wxString curLine = m_Tokens.GetLineFortran().Lower().Trim(false);
1960 int ipp = wxNOT_FOUND;
1961 if (taKind == taPrivate)
1962 ipp = curLine.Find(_T("private"));
1963 else if (taKind == taPublic)
1964 ipp = curLine.Find(_T("public"));
1965 else if (taKind == taProtected)
1966 ipp = curLine.Find(_T("protected"));
1967
1968 if (ipp == wxNOT_FOUND)
1969 return; // something is wrong
1970 else if (ipp != 0)
1971 return; // here private (public) is used as an attribute.
1972
1973 unsigned int defStartLine = m_Tokens.GetLineNumber();
1974 wxArrayString curLineArr = m_Tokens.GetTokensToEOL();
1975 if (curLineArr.GetCount() == 0)
1976 {
1977 changeDefault = true;
1978 return;
1979 }
1980 countAccess++;
1981 wxString name;
1982 name = _T("AccessList");
1983 if (countAccess > 1)
1984 name << _T(" ") << countAccess;
1985
1986 TokenF* token;
1987 token = DoAddToken(tkAccessList, name, wxEmptyString, defStartLine);
1988 token->AddLineEnd(m_Tokens.GetLineNumber());
1989 token->m_TokenAccess = taKind;
1990
1991 nameList.Add(token->m_Name);
1992 size_t i=0;
1993 if (curLineArr.Item(0).IsSameAs(_T("::")))
1994 i=1;
1995 for (; i<curLineArr.GetCount(); i++)
1996 {
1997 nameList.Add(curLineArr.Item(i).Lower());
1998 }
1999 }
2000
GoThroughBody()2001 void ParserThreadF::GoThroughBody()
2002 {
2003 wxString tok_low;
2004
2005 while (1)
2006 {
2007 unsigned int ln_tokold = m_Tokens.GetLineNumber();
2008
2009 wxString token = m_Tokens.GetToken();
2010 if (token.IsEmpty())
2011 break;
2012 else if (token.Matches(_T("::")))
2013 {
2014 m_Tokens.SkipToOneOfChars(";", true);
2015 continue;
2016 }
2017 tok_low = token.Lower();
2018
2019 wxString next = m_Tokens.PeekToken();
2020 wxString nex_low = next.Lower();
2021
2022 if ( ((m_Tokens.GetLineNumber() == m_Tokens.GetPeekedLineNumber()) && IsEnd(tok_low, nex_low)) ||
2023 ((m_Tokens.GetLineNumber() != m_Tokens.GetPeekedLineNumber()) && IsEnd(tok_low, _T(""))) )
2024 {
2025 m_Tokens.SkipToOneOfChars(";", true);
2026 break;
2027 }
2028 else if ( (tok_low.Matches(_T("end")) && nex_low.Matches(_T("select"))) || tok_low.Matches(_T("endselect")) ||
2029 (tok_low.Matches(_T("type")) && nex_low.Matches(_T("is"))) ||
2030 (tok_low.Matches(_T("class")) && nex_low.Matches(_T("is"))) ||
2031 (tok_low.Matches(_T("class")) && nex_low.Matches(_T("default"))) )
2032 {
2033 m_Tokens.UngetToken();
2034 break;
2035 }
2036 else if (tok_low.Matches(_T("type")) && !nex_low(0,1).Matches(_T("(")) && !nex_low.Matches(_T("is"))
2037 && ln_tokold != m_Tokens.GetLineNumber())
2038 {
2039 HandleType();
2040 }
2041 else if (tok_low.Matches(_T("subroutine")))
2042 {
2043 HandleFunction(tkSubroutine);
2044 }
2045 else if (tok_low.Matches(_T("function")))
2046 {
2047 HandleFunction(tkFunction);
2048 }
2049 else if (tok_low.Matches(_T("use")))
2050 {
2051 HandleUse();
2052 }
2053 else if (tok_low.Matches(_T("interface")))
2054 {
2055 HandleInterface();
2056 }
2057 else if (tok_low.Matches(_T("include")))
2058 {
2059 HandleInclude();
2060 }
2061 else if (tok_low.GetChar(0) == '#')
2062 {
2063 HandlePPDirective(token);
2064 }
2065 else if (tok_low.Matches(_T("procedure")) && m_pLastParent->m_TokenKind == tkInterface)
2066 {
2067 HandleProcedureList();
2068 }
2069 else if (tok_low.Matches(_T("module")) && (nex_low.Matches(_T("subroutine")) || nex_low.Matches(_T("function"))))
2070 {
2071 token = m_Tokens.GetToken();
2072 tok_low = token.Lower();
2073 if (tok_low.Matches(_T("subroutine")))
2074 {
2075 HandleFunction(tkSubroutine);
2076 }
2077 else if (tok_low.Matches(_T("function")))
2078 {
2079 HandleFunction(tkFunction);
2080 }
2081 }
2082 else if (tok_low.Matches(_T("block")))
2083 {
2084 if (nex_low.Matches(_T("data")))
2085 {
2086 token = m_Tokens.GetToken();
2087 tok_low = token.Lower();
2088 next = m_Tokens.PeekToken();
2089 nex_low = next.Lower();
2090 HandleBlockData();
2091 }
2092 else if (m_Tokens.GetLineNumber() != m_Tokens.GetPeekedLineNumber() || next.Matches(_T(";")))
2093 {
2094 HandleBlockConstruct();
2095 }
2096 }
2097 else if (tok_low.Matches(_T("blockdata")))
2098 {
2099 HandleBlockData();
2100 }
2101 else if (tok_low.Matches(_T("associate")))
2102 {
2103 HandleAssociateConstruct();
2104 }
2105 else if (tok_low.Matches(_T("select")) && nex_low.Matches(_T("type")))
2106 {
2107 m_Tokens.GetToken();
2108 HandleSelectTypeConstruct();
2109 }
2110 else if (tok_low.Matches(_T("selecttype")))
2111 {
2112 HandleSelectTypeConstruct();
2113 }
2114 else if ((tok_low.Matches(_T("select")) && nex_low.Matches(_T("case"))) ||
2115 tok_low.Matches(_T("selectcase")))
2116 {
2117 HandleSelectCaseConstruct();
2118 }
2119 else if (tok_low.Matches(_T("procedure")) && nex_low(0,1).Matches(_T("(")))
2120 {
2121 ParseTypeBoundProcedures(token, true, false);
2122 }
2123 else if (tok_low.Matches(_T("!bindto")))
2124 {
2125 HandleBindTo();
2126 }
2127 else
2128 {
2129 bool needDefault = true;
2130 bool hasFunctionInLine = false;
2131 TokensArrayF tokTmpArr;
2132 if (ln_tokold != m_Tokens.GetLineNumber()) // declaration can start only from a new line
2133 {
2134 CheckParseOneDeclaration(token, tok_low, next, nex_low, needDefault, tokTmpArr, hasFunctionInLine);
2135 }
2136
2137 if (tokTmpArr.size() == 0 && m_pLastParent && !hasFunctionInLine)
2138 {
2139 CheckParseCallProcedure(token, tok_low, next);
2140 }
2141 }
2142 }
2143 }
2144
HandleProcedureList()2145 void ParserThreadF::HandleProcedureList()
2146 {
2147 unsigned int lineNum = m_Tokens.GetLineNumber();
2148 wxArrayString curLineArr = m_Tokens.GetTokensToEOL();
2149
2150 for (unsigned int i=0; i<curLineArr.GetCount(); i++)
2151 {
2152 if (curLineArr.Item(i).IsSameAs(_T("::")))
2153 continue;
2154 DoAddToken(tkOther, curLineArr.Item(i), wxEmptyString, lineNum);
2155 }
2156 }
2157
ParseTypeBoundProcedures(const wxString & firstWord,bool breakAtEOL,bool passIn)2158 void ParserThreadF::ParseTypeBoundProcedures(const wxString& firstWord, bool breakAtEOL, bool passIn)
2159 {
2160 TokenAccessKind defAccKind = taPublic;
2161 bool firstTime = true;
2162 int nOperator = 0;
2163 int nAssignment = 0;
2164 while (1)
2165 {
2166 bool pass = passIn;
2167 TokenAccessKind tokAccK = defAccKind;
2168 wxString firstTokenLw;
2169 if (firstTime && !firstWord.IsEmpty())
2170 {
2171 firstTokenLw = firstWord.Lower();
2172 firstTime = false;
2173 }
2174 else
2175 firstTokenLw = m_Tokens.GetToken().Lower();
2176
2177 if (firstTokenLw.IsEmpty())
2178 break;
2179 wxString defString = firstTokenLw;
2180 unsigned int lineNum = m_Tokens.GetLineNumber();
2181 wxArrayString linesArr;
2182 wxArrayString curLineArr = m_Tokens.GetTokensToEOL(&linesArr);
2183 bool isGen = firstTokenLw.IsSameAs(_T("generic"));
2184 bool isProc = firstTokenLw.IsSameAs(_T("procedure"));
2185 if (curLineArr.Count() > 0 && (isProc || isGen) ) // &&
2186 // !curLineArr.Item(0).StartsWith(_T("(")) ) // not interface-name
2187 {
2188 wxString interfaceName;
2189 if (isProc)
2190 {
2191 wxString strInter = curLineArr.Item(0);
2192 int idx_a = strInter.Find(')',true);
2193 int idx_b = strInter.Find('(');
2194 if (idx_a != wxNOT_FOUND && idx_b != wxNOT_FOUND && idx_a > idx_b+1)
2195 {
2196 interfaceName = strInter.Mid(idx_b+1,idx_a-idx_b-1);
2197 defString << strInter;
2198 }
2199 }
2200 wxString passArg;
2201 int idx = curLineArr.Index(_T("::"));
2202 int startList;
2203 if (idx != wxNOT_FOUND)
2204 {
2205 int startIdx = interfaceName.IsEmpty() ? 0 : 1;
2206 for (int i=startIdx; i<idx; i++)
2207 {
2208 defString << _T(", ") << curLineArr.Item(i).Lower();
2209 }
2210
2211 for (int i=0; i<idx; i++)
2212 {
2213 wxString tok = curLineArr.Item(i).Lower();
2214 if (tok.IsSameAs(_T("nopass")))
2215 {
2216 pass = false;
2217 }
2218 else if (tok.IsSameAs(_T("pass")))
2219 {
2220 if (i < idx-1)
2221 {
2222 wxString strArg = curLineArr.Item(i+1);
2223 int idx_a = strArg.Find(')',true);
2224 int idx_b = strArg.Find('(');
2225 if (idx_a != wxNOT_FOUND && idx_b != wxNOT_FOUND && idx_a > idx_b+1)
2226 {
2227 passArg = strArg.Mid(idx_b+1,idx_a-idx_b-1);
2228 }
2229 }
2230 }
2231 else if (tok.IsSameAs(_T("private")))
2232 {
2233 tokAccK = taPrivate;
2234 }
2235 else if (tok.IsSameAs(_T("public")))
2236 {
2237 tokAccK = taPublic;
2238 }
2239 }
2240 startList = idx + 1;
2241 }
2242 else
2243 {
2244 startList = 0;
2245 }
2246 int countArr = curLineArr.GetCount();
2247 int ic=startList;
2248 if (!isGen)
2249 {
2250 while (ic < countArr)
2251 {
2252 // Read docs
2253 wxString comStr = linesArr.Item(ic).AfterFirst('!');
2254 if (!comStr.IsEmpty())
2255 {
2256 if (comStr.StartsWith(_T("<")) || comStr.StartsWith(_T(">")))
2257 comStr = comStr.Mid(1);
2258 comStr = comStr.Trim(true).Trim(false);
2259 }
2260
2261 wxString bindName = curLineArr.Item(ic);
2262 wxString procName;
2263 if (ic+2 < countArr)
2264 {
2265 if (curLineArr.Item(ic+1).IsSameAs(_T("=>")))
2266 {
2267 ic += 2;
2268 procName = curLineArr.Item(ic);
2269 if (ic+1 < countArr && curLineArr.Item(ic+1).StartsWith(_T("(")))
2270 ic++;
2271 }
2272 }
2273 ic++;
2274 TokenF* token = DoAddToken(tkProcedure, bindName.Lower(), wxEmptyString, lineNum);
2275 token->m_DisplayName = bindName;
2276 token->m_Pass = pass;
2277 token->m_Args = passArg;
2278 if (interfaceName.IsEmpty())
2279 {
2280 token->m_PartLast = procName.Lower();
2281 token->m_IsAbstract = false;
2282 }
2283 else
2284 {
2285 token->m_PartLast = interfaceName.Lower();
2286 token->m_IsAbstract = true;
2287 }
2288 token->AddLineEnd(m_Tokens.GetLineNumber());
2289 token->m_TokenAccess = tokAccK;
2290 token->m_TypeDefinition = defString;
2291 token->m_DocString = comStr;
2292 }
2293 }
2294 else //isGen
2295 {
2296 while (ic < countArr-2)
2297 {
2298 wxString curNam;
2299 wxString curNamLw = curLineArr.Item(ic).Lower();
2300 if (curNamLw.IsSameAs(_T("operator")) || curNamLw.IsSameAs(_T("assignment")))
2301 {
2302 curNam.Append(_T("%%"));
2303 curNam.Append(curLineArr.Item(ic));
2304 if (curLineArr.Item(ic+1).StartsWith(_("(")))
2305 {
2306 ic++;
2307 curNam.Append(curLineArr.Item(ic));
2308 }
2309 if (curNamLw.IsSameAs(_T("operator")))
2310 {
2311 nOperator += 1;
2312 curNam << _T(" #") << nOperator;
2313 }
2314 else
2315 {
2316 nAssignment += 1;
2317 curNam << _T(" #") << nAssignment;
2318 }
2319 TokenF* token = DoAddToken(tkInterface, curNam, wxEmptyString, lineNum);
2320 token->AddLineEnd(m_Tokens.GetLineNumber());
2321 }
2322 else if (curLineArr.Item(ic+1).IsSameAs(_T("=>")))
2323 {
2324 wxString bindName = curLineArr.Item(ic);
2325 TokenF* token = DoAddToken(tkInterface, bindName.Lower(), wxEmptyString, lineNum);
2326 token->m_DisplayName = bindName;
2327 ic += 2;
2328 wxString specNames;
2329 for (; ic < countArr; ic++)
2330 {
2331 specNames << curLineArr.Item(ic) << _T(" ");
2332 }
2333 token->m_PartLast = specNames.Trim();
2334 token->AddLineEnd(m_Tokens.GetLineNumber());
2335 token->m_TokenAccess = tokAccK;
2336 }
2337 ic++;
2338 }
2339 }
2340 }
2341 else if ( (curLineArr.Count() == 0 && IsEnd(firstTokenLw, wxEmptyString)) ||
2342 (curLineArr.Count() >= 1 && IsEnd(firstTokenLw,curLineArr.Item(0).Lower())) )
2343 {
2344 m_Tokens.SkipToOneOfChars(";", true);
2345 break;
2346 }
2347 else if ( firstTokenLw.IsSameAs(_T("private")) && curLineArr.Count() == 0 )
2348 {
2349 defAccKind = taPrivate;
2350 }
2351 else if ( firstTokenLw.IsSameAs(_T("final")) && curLineArr.Count() > 0 )
2352 {
2353 int idx = curLineArr.Index(_T("::"));
2354 int startIdx = (idx == wxNOT_FOUND) ? 0 : idx+1;
2355 for (size_t i=startIdx; i<curLineArr.Count(); i++)
2356 {
2357 wxString name = curLineArr.Item(i);
2358 TokenF* token = DoAddToken(tkProcedureFinal, name.Lower(), wxEmptyString, lineNum);
2359 token->m_DisplayName = name;
2360 token->AddLineEnd(m_Tokens.GetLineNumber());
2361 }
2362 }
2363
2364 if (breakAtEOL)
2365 break;
2366 }
2367 }
2368
IsEnd(wxString tok_low,wxString nex_low)2369 bool ParserThreadF::IsEnd(wxString tok_low, wxString nex_low)
2370 {
2371 bool isend = false;
2372 if ( tok_low.StartsWith(_T("end")) &&
2373 ( (tok_low.Matches(_T("end")) && (nex_low.IsEmpty() || m_KnownEndSecPart.count(nex_low))) ||
2374 tok_low.Matches(_T("endsubroutine")) ||
2375 tok_low.Matches(_T("endfunction")) ||
2376 tok_low.Matches(_T("endmodule")) ||
2377 tok_low.Matches(_T("endsubmodule")) ||
2378 tok_low.Matches(_T("endtype")) ||
2379 tok_low.Matches(_T("endinterface")) ||
2380 tok_low.Matches(_T("endprogram")) ||
2381 tok_low.Matches(_T("endblock")) ||
2382 tok_low.Matches(_T("endblockdata")) ||
2383 tok_low.Matches(_T("endassociate")) ||
2384 tok_low.Matches(_T("endprocedure")) )
2385 )
2386 {
2387 isend = true;
2388 }
2389 return isend;
2390 }
2391
MakeArrayStringLower(wxArrayString & arr,wxArrayString & arrLw)2392 void ParserThreadF::MakeArrayStringLower(wxArrayString &arr, wxArrayString &arrLw)
2393 {
2394 for(size_t i=0; i<arr.Count(); i++)
2395 {
2396 arrLw.Add(arr.Item(i).Lower());
2397 }
2398 }
2399
SetTokenAccess(ModuleTokenF * modToken,TokenF * token,TokenAccessKind defAKind)2400 void ParserThreadF::SetTokenAccess(ModuleTokenF* modToken, TokenF* token, TokenAccessKind defAKind)
2401 {
2402 if (modToken->HasNameInPrivateList(token->m_Name))
2403 {
2404 token->m_TokenAccess = taPrivate;
2405 }
2406 else if (modToken->HasNameInPublicList(token->m_Name))
2407 {
2408 if (token->m_TokenAccess != taProtected)
2409 token->m_TokenAccess = taPublic;
2410 }
2411 else
2412 {
2413 token->m_TokenAccess = defAKind;
2414 }
2415 }
2416
2417
SplitAssociateConstruct(const wxString & argLine,std::map<wxString,wxString> & assocMap)2418 void ParserThreadF::SplitAssociateConstruct(const wxString& argLine, std::map<wxString,wxString>& assocMap)
2419 {
2420 wxString args = argLine;
2421 int pos = args.Find(')',true);
2422 if (pos != wxNOT_FOUND)
2423 args.Remove(pos);
2424 args = args.AfterFirst('(');
2425
2426 int cnt = 0;
2427 int sta = 0;
2428 for(size_t i=0; i<args.Len(); i++)
2429 {
2430 if (args.GetChar(i) == '(')
2431 cnt++;
2432 else if (args.GetChar(i) == ')')
2433 cnt--;
2434
2435 if ( (args.GetChar(i) == ',' && cnt == 0) ||
2436 (i == args.Len()-1) )
2437 {
2438 wxString block;
2439 if (args.GetChar(i) == ',')
2440 block = args.Mid(sta, i-sta);
2441 else
2442 block = args.Mid(sta, i-sta+1);
2443 sta = i + 1;
2444 int sind = block.Find(_T("=>"));
2445 if (sind != wxNOT_FOUND)
2446 {
2447 wxString assocName = block.Mid(0,sind).Trim(true).Trim(false);
2448 wxString sourceExpr = block.Mid(sind+2).Trim(true).Trim(false);
2449 assocMap.insert(std::pair<wxString,wxString>(assocName, sourceExpr));
2450 }
2451 else
2452 {
2453 wxString assocName = block.Trim(true).Trim(false);
2454 assocMap.insert(std::pair<wxString,wxString>(assocName, assocName));
2455 }
2456 }
2457 }
2458 }
2459
GetDocBlock(DocBlock & docs,bool lookDown,unsigned int ln,bool takeSimpleDoc)2460 void ParserThreadF::GetDocBlock(DocBlock &docs, bool lookDown, unsigned int ln, bool takeSimpleDoc)
2461 {
2462 bool isSimpleDoc = false;
2463 bool hasDoc = false;
2464 wxArrayString docLines;
2465 unsigned int loopStart;
2466 if (lookDown)
2467 loopStart = ln+1;
2468 else
2469 loopStart = ln-1;
2470 unsigned int ii = loopStart;
2471 unsigned int nLines = m_Tokens.GetLineCount();
2472
2473 while (ii >= 1 && ii <= nLines)
2474 {
2475 wxString line = m_Tokens.GetLine(ii).Trim(false);
2476
2477 if (ii == loopStart && !line.StartsWith(_T("!")))
2478 isSimpleDoc = false;
2479 else if (ii == loopStart && line.StartsWith(_T("!")))
2480 {
2481 if (!lookDown && (line.StartsWith(_T("!!")) || line.StartsWith(_T("!<")) || line.StartsWith(_T("!>"))))
2482 isSimpleDoc = false;
2483 else
2484 {
2485 isSimpleDoc = true;
2486 if (!takeSimpleDoc)
2487 break;
2488 }
2489 }
2490
2491 if (line.StartsWith(_T("!")))
2492 {
2493 if (line.StartsWith(_T("!!")) || line.StartsWith(_T("!<")) || line.StartsWith(_T("!>")))
2494 {
2495 docLines.Add(line.Mid(2).Trim(true).Trim(false));
2496 }
2497 else if (isSimpleDoc)
2498 {
2499 docLines.Add(line.Mid(1).Trim(true).Trim(false));
2500 }
2501 else
2502 break;
2503
2504 hasDoc = true;
2505 }
2506 else if (hasDoc && line.IsEmpty())
2507 break;
2508 else if (!line.IsEmpty())
2509 break;
2510
2511 if (lookDown)
2512 ii++;
2513 else
2514 ii--;
2515 }
2516
2517 if (isSimpleDoc && docLines.GetCount()>0)
2518 {
2519 // Not Doxygen comments
2520 // Take first 3 nonempty lines and use it as a doc-string
2521 wxString docLine;
2522 int isimp = 0;
2523 if (lookDown)
2524 loopStart = 0;
2525 else
2526 loopStart = docLines.GetCount()-1;
2527 int j = loopStart;
2528
2529 while ((lookDown && j < (int) docLines.GetCount()) || (!lookDown && j >= 0))
2530 {
2531 size_t sidx = docLines[j].find_first_not_of(_T("! \t"));
2532 if (sidx != wxString::npos)
2533 {
2534 size_t sidx2 = docLines[j].find_first_not_of(docLines[j].at(sidx)); // an attempt to avoid e.g. !********
2535 if (sidx2 != wxString::npos)
2536 {
2537 //if (isimp == 3) // take 3 lines at most
2538 if (docLine.size() > 400) // limit number of symbols
2539 {
2540 docLine << _T("...");
2541 break;
2542 }
2543 if (sidx2 > sidx+2)
2544 docLine << _T(" ") + docLines[j].Mid(sidx2);
2545 else
2546 docLine << _T(" ") + docLines[j].Mid(sidx);
2547
2548 isimp += 1;
2549 }
2550 else if (!docLine.IsEmpty())
2551 break;
2552 }
2553 else if (!docLine.IsEmpty())
2554 break;
2555
2556 if (lookDown)
2557 j++;
2558 else
2559 j--;
2560 }
2561 if (!docLine.IsEmpty())
2562 docs.AddDescription(docLine.Trim(false));
2563
2564 }
2565 else if (docLines.GetCount()>0)
2566 {
2567 // Doxygen docs
2568 wxString description;
2569 wxString brief;
2570 wxArrayString paramNames;
2571 wxArrayString paramDescr;
2572 bool inbrief = false;
2573 bool indescription = false;
2574 for (int i=docLines.GetCount()-1; i>=0; i--)
2575 {
2576 bool iscommand = false;
2577
2578 if (docLines[i].IsEmpty())
2579 {
2580 inbrief = false;
2581 indescription = false;
2582 continue;
2583 }
2584 else if (docLines[i].StartsWith(_T("\\")) || docLines[i].StartsWith(_T("@")))
2585 {
2586 inbrief = false;
2587 indescription = false;
2588 iscommand = true;
2589 }
2590
2591 bool isbrief = false;
2592 bool isparam = false;
2593 if (iscommand)
2594 {
2595 size_t sidx = docLines[i].find(_T("brief"),1);
2596 if (sidx == 1)
2597 isbrief = true;
2598
2599 if (!isbrief)
2600 {
2601 sidx = docLines[i].find(_T("param"),1);
2602 if (sidx == 1)
2603 isparam = true;
2604 }
2605 }
2606
2607 if (isbrief)
2608 {
2609 brief = docLines[i].Mid(6).Trim(false);
2610 inbrief = true;
2611 indescription = false;
2612 }
2613 else if (inbrief)
2614 {
2615 wxString repNoStr = TrimRepetitives(docLines[i]);
2616 if (!repNoStr.IsEmpty())
2617 brief << _T(" ") << repNoStr;
2618 }
2619 else if (isparam)
2620 {
2621 wxString pline = docLines[i].Mid(6).Trim(false);
2622 size_t sidx = pline.find_first_of(_T(" \t"));
2623 if (sidx != wxString::npos)
2624 {
2625 paramDescr.Add(pline.Mid(sidx+1).Trim(false));
2626 paramNames.Add(pline.Mid(0,sidx));
2627 }
2628 indescription = false;
2629 }
2630 else if (!iscommand && description.IsEmpty() && paramNames.Count() == 0)
2631 {
2632 indescription = true;
2633 }
2634
2635 if (indescription)
2636 {
2637 wxString repNoStr = TrimRepetitives(docLines[i]);
2638 if (!repNoStr.IsEmpty())
2639 description << repNoStr + _T(" ");
2640 }
2641
2642 }
2643
2644 if (!description.IsEmpty())
2645 docs.AddDescription(description.Trim());
2646 if (!brief.IsEmpty())
2647 docs.AddBrief(brief);
2648 for (size_t i=0; i<paramDescr.size(); i++)
2649 {
2650 docs.AddParam(paramNames[i], paramDescr[i]);
2651 }
2652 }
2653 }
2654
TrimRepetitives(wxString & inStr)2655 wxString ParserThreadF::TrimRepetitives(wxString& inStr)
2656 {
2657 // an attempt to avoid e.g. !********
2658 wxString outStr;
2659 size_t sidx = inStr.find_first_not_of(_T("! \t"));
2660 if (sidx != wxString::npos)
2661 {
2662 size_t sidx2 = inStr.find_first_not_of(inStr.at(sidx),sidx);
2663 if (sidx2 != wxString::npos)
2664 {
2665 if (sidx2 > sidx+2)
2666 outStr = inStr.Mid(sidx2);
2667 else
2668 outStr = inStr.Mid(sidx);
2669 }
2670 }
2671 return outStr;
2672 }
2673
GetDocLine(unsigned int ln)2674 wxString ParserThreadF::GetDocLine(unsigned int ln)
2675 {
2676 wxString line = m_Tokens.GetLine(ln);
2677 line = line.AfterFirst('!');
2678 if (line.StartsWith(_T("<")) || line.StartsWith(_T(">")))
2679 line = line.substr(1);
2680 return line.Trim(true).Trim(false);
2681 }
2682
AddParamDocs(TokenF * pParToken,DocBlock & docs)2683 void ParserThreadF::AddParamDocs(TokenF* pParToken, DocBlock &docs)
2684 {
2685 int npar = docs.GetParamCount();
2686 if (npar == 0)
2687 return;
2688 int nadd = 0;
2689 TokensArrayF* tokArr = &pParToken->m_Children;
2690 for (size_t j=0; j<tokArr->GetCount(); j++)
2691 {
2692 if (tokArr->Item(j)->m_TokenKind == tkVariable && tokArr->Item(j)->m_DocString.IsEmpty())
2693 {
2694 wxString descr = docs.GetValue(tokArr->Item(j)->m_Name);
2695 if (!descr.IsEmpty())
2696 {
2697 tokArr->Item(j)->m_DocString = descr;
2698 nadd++;
2699 if (nadd == npar)
2700 break;
2701 }
2702 }
2703 }
2704 }
2705
HandleBindTo()2706 void ParserThreadF::HandleBindTo()
2707 {
2708 wxString line = m_Tokens.GetCurrentLine().Trim(true).Trim(false);
2709 line = line.Mid(7).Trim(false).Lower();
2710 DoAddToken(tkBindTo, wxEmptyString, line.BeforeFirst('!').Trim());
2711 m_Tokens.SkipToEOL();
2712 }
2713
CheckParseCallProcedure(wxString & token,wxString & tok_low,wxString & next)2714 void ParserThreadF::CheckParseCallProcedure(wxString& token, wxString& tok_low, wxString& next)
2715 {
2716 if ( tok_low.IsSameAs(_T("call")) )
2717 {
2718 wxArrayString args_arr;
2719 token = m_Tokens.GetTokenSameFortranLine();
2720 while (true)
2721 {
2722 wxString nextTok = m_Tokens.PeekTokenSameFortranLine();
2723 if (nextTok.IsSameAs(_T("%")))
2724 {
2725 token << m_Tokens.GetTokenSameFortranLine();
2726 token << m_Tokens.GetTokenSameFortranLine();
2727 }
2728 else if (nextTok.StartsWith(_T("(")) && nextTok.EndsWith(_T(")")))
2729 {
2730 args_arr.Add(m_Tokens.GetTokenSameFortranLine());
2731 }
2732 else
2733 break;
2734 }
2735 if (token != wxEmptyString)
2736 {
2737 DoAddToken(tkCallSubroutine, token);
2738 for (size_t i=0; i<args_arr.size(); ++i)
2739 {
2740 token = args_arr.Item(i);
2741 if (token.StartsWith(_T("(")) && token.EndsWith(_T(")")))
2742 {
2743 // we have argument list. Find function-array calls.
2744 wxString args = token.Mid(1, token.length()-2);
2745 TakeFunctionsCallsFromString(args);
2746 }
2747 }
2748 }
2749 }
2750 else
2751 {
2752 if (next.StartsWith(_T("(")))
2753 {
2754 wxString curLine = m_Tokens.GetLineFortran();
2755 TakeFunctionsCallsFromString(curLine);
2756 m_Tokens.SkipToOneOfChars(";", true);
2757 }
2758 }
2759 }
2760
TakeFunctionsCallsFromString(const wxString & strIn)2761 void ParserThreadF::TakeFunctionsCallsFromString(const wxString& strIn)
2762 {
2763 wxString str = strIn;
2764 for (int i=0; i<20; i++)
2765 {
2766 int idx = str.Find(_T("("));
2767 if (idx == wxNOT_FOUND)
2768 {
2769 break;
2770 }
2771 else if (idx > 0)
2772 {
2773 int idxStart;
2774 wxString funName;
2775 int idxEnd = idx-1;
2776 while (true)
2777 {
2778 wxString wordTmp;
2779 GetWordBefore(str, idxEnd, wordTmp, idxStart);
2780 if (wordTmp.IsEmpty())
2781 {
2782 break;
2783 }
2784 else if (wordTmp.StartsWith(_T("(")) && wordTmp.EndsWith(_T(")")))
2785 {
2786 idxEnd = idxStart - 1;
2787 }
2788 else
2789 {
2790 int idxCur = idxStart-1;
2791 for (; idxCur>=0; idxCur--)
2792 {
2793 if (!isspace(str.GetChar(idxCur)))
2794 break;
2795 }
2796
2797 if (idxCur >= 0 && str.GetChar(idxCur) == '%')
2798 {
2799 funName = _T("%") + wordTmp + funName;
2800 idxEnd = idxCur-1;
2801 }
2802 else
2803 {
2804 funName = wordTmp + funName;
2805 break;
2806 }
2807 }
2808 }
2809
2810 if (!funName.IsEmpty() && !isdigit(funName.GetChar(0)))
2811 {
2812 DoAddToken(tkCallFunction, funName);
2813 }
2814 else
2815 break; // something is wrong
2816 }
2817 str = str.Mid(idx+1);
2818 }
2819 }
2820
2821
GetWordBefore(const wxString & str,int idxEnd,wxString & funName,int & idxStart)2822 void ParserThreadF::GetWordBefore(const wxString& str, int idxEnd, wxString& funName, int& idxStart)
2823 {
2824 funName = wxEmptyString;
2825 for (; idxEnd>=0; idxEnd--)
2826 {
2827 if (!isspace(str.GetChar(idxEnd)))
2828 break;
2829 }
2830
2831 if (idxEnd < 0)
2832 return;
2833
2834 int lev = 0;
2835 for (idxStart=idxEnd; idxStart>=0; idxStart--)
2836 {
2837 if (str.GetChar(idxStart) == ')')
2838 {
2839 lev+=1;
2840 }
2841 else if (str.GetChar(idxStart) == '(')
2842 {
2843 if (lev == 0)
2844 break;
2845 else if (lev == 1)
2846 {
2847 idxStart-=1;
2848 break;
2849 }
2850 else
2851 lev-=1;
2852 }
2853 else if (!isalnum(str.GetChar(idxStart)) && str.GetChar(idxStart) != '_' && str.GetChar(idxStart) != '$')
2854 break;
2855 }
2856 idxStart += 1;
2857 funName = str.Mid(idxStart, idxEnd-idxStart+1);
2858 }
2859