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 "keywordsparserf.h"
8 
9 #include <sdk.h>
10 #ifndef CB_PRECOMP
11     #include <wx/tokenzr.h>
12     #include <wx/string.h>
13     #include <wx/arrstr.h>
14     #include <wx/file.h>
15 
16     #include <globals.h>
17     #include <cbstyledtextctrl.h>
18     #include <configmanager.h>
19     #include <logmanager.h>
20 #endif
21 
22 #include "parserthreadf.h"
23 
KeywordsParserF()24 KeywordsParserF::KeywordsParserF():
25     m_Parser(false)
26 {
27     m_IsDone = false;
28     wxString filename = ConfigManager::GetDataFolder() + _T("/images/fortranproject/fortran_procedures.f90");
29     if (!wxFileExists(filename))
30     {
31         Manager::Get()->GetLogManager()->Log(_T("FortranProject plugin error: file ")+filename+_T(" was not found."));
32         return;
33     }
34     m_Parser.Reparse(filename, filename, fsfFree);
35 
36     TokensArrayF* pTokensArr = m_Parser.GetTokens();
37     TokensArrayF* pTokens = &pTokensArr->Item(0)->m_Children;
38 
39     for (size_t i=0; i<pTokens->GetCount(); i++)
40     {
41         if (pTokens->Item(i)->m_TokenKind == tkSubroutine)
42         {
43             m_SubrSet.insert(pTokens->Item(i)->m_Name);
44         }
45         else if (pTokens->Item(i)->m_TokenKind == tkFunction)
46         {
47             m_FuncSet.insert(pTokens->Item(i)->m_Name);
48         }
49         else if (pTokens->Item(i)->m_TokenKind == tkModule && pTokens->Item(i)->m_Name.IsSameAs(_T("openmp")))
50         {
51             TokensArrayF* pOMPMod = &pTokens->Item(i)->m_Children;
52             for (size_t j=0; j<pOMPMod->GetCount(); j++)
53             {
54                 if (pOMPMod->Item(j)->m_TokenKind == tkVariable)
55                     m_OpenMPKeywords.Add(pOMPMod->Item(j)->m_DisplayName);
56             }
57         }
58         else if (pTokens->Item(i)->m_TokenKind == tkModule && pTokens->Item(i)->m_Name.IsSameAs(_T("openacc")))
59         {
60             TokensArrayF* pACCMod = &pTokens->Item(i)->m_Children;
61             for (size_t j=0; j<pACCMod->GetCount(); j++)
62             {
63                 if (pACCMod->Item(j)->m_TokenKind == tkVariable)
64                     m_OpenACCKeywords.Add(pACCMod->Item(j)->m_DisplayName);
65             }
66         }
67     }
68     MakeOtherKeywordSet();
69     m_IsDone = true;
70 }
71 
~KeywordsParserF()72 KeywordsParserF::~KeywordsParserF()
73 {
74     //dtor
75 }
76 
HasTokenSuitableKind(const wxString & name,int tokKind)77 bool KeywordsParserF::HasTokenSuitableKind(const wxString& name, int tokKind)
78 {
79     if (!m_IsDone)
80         return true;
81 
82     wxString nameLow = name.Lower();
83     bool found = false;
84     if ( (m_FuncSet.count(nameLow) && (tokKind & tkFunction)) ||
85          (m_SubrSet.count(nameLow) && (tokKind & tkSubroutine)) ||
86          (m_OtherKeywordSet.count(nameLow) && (tokKind & tkOther)) )
87         found = true;
88 
89     return found;
90 }
91 
GetCallTips(const wxString & name,wxArrayString & callTips,TokensArrayFlat * result)92 void KeywordsParserF::GetCallTips(const wxString& name, wxArrayString& callTips, TokensArrayFlat* result)
93 {
94     int tokKind = tkFunction | tkSubroutine;
95     size_t resCountOld = result->GetCount();
96     size_t resCount = m_Parser.FindMatchTokensDeclared(name, *result, tokKind, false);
97     for (size_t i=resCountOld; i<resCount; ++i)
98     {
99         callTips.Add(result->Item(i)->m_Args);
100     }
101 }
102 
FindTokens(const wxString & name,TokensArrayFlat & result)103 void KeywordsParserF::FindTokens(const wxString& name, TokensArrayFlat& result)
104 {
105     int tokKind = tkFunction | tkSubroutine;
106     m_Parser.FindMatchTokensDeclared(name, result, tokKind, false);
107 }
108 
MakeOtherKeywordSet()109 void KeywordsParserF::MakeOtherKeywordSet()
110 {
111     TokensArrayFlatClass tokensTmp;
112     TokensArrayFlat* result = tokensTmp.GetTokens();
113     size_t resCount = m_Parser.FindMatchTokensDeclared(_T("list_of_other_fortran_keywords"), *result, tkFunction, false);
114     if (resCount != 1)
115     {
116         Manager::Get()->GetLogManager()->Log(_T("FortranProject plugin error: "));
117         Manager::Get()->GetLogManager()->Log(_T("Can't parse 'list_of_other_fortran_keywords' function."));
118         return;
119     }
120     TokenFlat* token = result->Item(0);
121     wxString txtRange;
122     if (!m_Parser.FindTokenRange(*token, txtRange))
123     {
124         Manager::Get()->GetLogManager()->Log(_T("FortranProject plugin error: "));
125         Manager::Get()->GetLogManager()->Log(_T("Can't parse 'list_of_other_fortran_keywords' function."));
126         return;
127     }
128 
129     //Parse
130     TokensArrayClass tokensKeyTmp;
131     TokensArrayF* parsResult = tokensKeyTmp.GetTokens();
132     ParserThreadF thread = ParserThreadF(wxEmptyString, txtRange, parsResult, fsfFree, true);
133     thread.ParseDeclarations();
134 
135     for (size_t i=0; i<parsResult->GetCount(); i++)
136     {
137         if (parsResult->Item(i)->m_TokenKind == tkVariable)
138         {
139             m_OtherKeywordSet.insert(parsResult->Item(i)->m_Name);
140         }
141     }
142 }
143 
GetKeywords(CompilerDirective cdir)144 const wxArrayString* KeywordsParserF::GetKeywords(CompilerDirective cdir)
145 {
146     if (cdir == cdOpenMP)
147         return &m_OpenMPKeywords;
148     else if (cdir == cdOpenACC)
149         return &m_OpenACCKeywords;
150     return NULL;
151 }
152