BfParser.cpp 104 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308
  1. #pragma warning(disable:4996)
  2. #include "BfParser.h"
  3. #include "BfReducer.h"
  4. #include "BfPrinter.h"
  5. #include "BfDefBuilder.h"
  6. #include "BfCompiler.h"
  7. #include "BfSourceClassifier.h"
  8. #include "BfSourcePositionFinder.h"
  9. #include <sstream>
  10. #include "BeefySysLib/util/PerfTimer.h"
  11. #include "BeefySysLib/util/BeefPerf.h"
  12. #include "BeefySysLib/util/UTF8.h"
  13. #include "BfAutoComplete.h"
  14. #include "BfResolvePass.h"
  15. #include "BfElementVisitor.h"
  16. #include "BeefySysLib/util/UTF8.h"
  17. extern "C"
  18. {
  19. #include "BeefySysLib/third_party/utf8proc/utf8proc.h"
  20. }
  21. #include "BeefySysLib/util/AllocDebug.h"
  22. USING_NS_BF;
  23. static bool IsWhitespace(char c)
  24. {
  25. return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r');
  26. }
  27. static bool IsWhitespaceOrPunctuation(char c)
  28. {
  29. switch (c)
  30. {
  31. case ',':
  32. case ';':
  33. case ':':
  34. case '(':
  35. case ')':
  36. case '[':
  37. case ']':
  38. case '{':
  39. case '}':
  40. case '<':
  41. case '>':
  42. case '/':
  43. case '-':
  44. case '=':
  45. case '+':
  46. case '!':
  47. case '%':
  48. case '&':
  49. case '|':
  50. case '#':
  51. case '@':
  52. case '`':
  53. case '^':
  54. case '~':
  55. case '*':
  56. case '?':
  57. case '\n':
  58. case ' ':
  59. case '\t':
  60. case '\v':
  61. case '\f':
  62. case '\r':
  63. return true;
  64. default:
  65. return false;
  66. }
  67. }
  68. BfParser* BfParserData::ToParser()
  69. {
  70. if (mUniqueParser != NULL)
  71. {
  72. BF_ASSERT(mUniqueParser->mOrigSrcLength >= 0);
  73. BF_ASSERT((mUniqueParser->mCursorIdx >= -1) || (mUniqueParser->mCursorIdx <= mUniqueParser->mOrigSrcLength));
  74. }
  75. return mUniqueParser;
  76. }
  77. //////////////////////////////////////////////////////////////////////////
  78. /// raw_null_ostream - A raw_ostream that discards all output.
  79. /*class debug_ostream : public llvm::raw_ostream
  80. {
  81. /// write_impl - See raw_ostream::write_impl.
  82. void write_impl(const char *Ptr, size_t size) override
  83. {
  84. char str[256] = {0};
  85. memcpy(str, Ptr, std::min((int)size, 255));
  86. OutputDebugStr(str);
  87. }
  88. /// current_pos - Return the current position within the stream, not
  89. /// counting the bytes currently in the buffer.
  90. uint64_t current_pos() const override
  91. {
  92. return 0;
  93. }
  94. };*/
  95. //////////////////////////////////////////////////////////////////////////
  96. static CritSect gParseFileDataCrit;
  97. static Array<int> gFreeIds;
  98. static int gCurFreeId;
  99. int BfParseFileData::GetUniqueId(int idx)
  100. {
  101. AutoCrit autoCrit(gParseFileDataCrit);
  102. while (idx >= mUniqueIDList.size())
  103. {
  104. if (!gFreeIds.IsEmpty())
  105. {
  106. mUniqueIDList.Add(gFreeIds.back());
  107. gFreeIds.pop_back();
  108. }
  109. else
  110. mUniqueIDList.Add(gCurFreeId++);
  111. }
  112. return mUniqueIDList[idx];
  113. }
  114. BfParseFileData::~BfParseFileData()
  115. {
  116. if (!mUniqueIDList.IsEmpty())
  117. {
  118. AutoCrit autoCrit(gParseFileDataCrit);
  119. for (auto id : mUniqueIDList)
  120. gFreeIds.Add(id);
  121. }
  122. }
  123. //////////////////////////////////////////////////////////////////////////
  124. BfParserCache* Beefy::gBfParserCache = NULL;
  125. bool BfParserCache::DataEntry::operator==(const LookupEntry& lookup) const
  126. {
  127. if ((mParserData->mFileName == lookup.mFileName) &&
  128. (mParserData->mSrcLength == lookup.mSrcLength) &&
  129. (memcmp(mParserData->mSrc, lookup.mSrc, lookup.mSrcLength) == 0))
  130. {
  131. for (auto& setDefine : mParserData->mDefines_Def)
  132. if (!lookup.mProject->mPreprocessorMacros.Contains(setDefine))
  133. return false;
  134. for (auto& setDefine : mParserData->mDefines_NoDef)
  135. if (lookup.mProject->mPreprocessorMacros.Contains(setDefine))
  136. return false;
  137. return true;
  138. }
  139. return false;
  140. }
  141. BfParserCache::BfParserCache()
  142. {
  143. mRefCount = 0;
  144. }
  145. BfParserCache::~BfParserCache()
  146. {
  147. for (auto& entry : mEntries)
  148. {
  149. BF_ASSERT(entry.mParserData->mRefCount == 0);
  150. delete entry.mParserData;
  151. }
  152. }
  153. void BfParserCache::ReportMemory(MemReporter* memReporter)
  154. {
  155. int srcLen = 0;
  156. int allocBytesUsed = 0;
  157. int largeAllocs = 0;
  158. for (auto& entry : mEntries)
  159. {
  160. auto parserData = entry.mParserData;
  161. parserData->ReportMemory(memReporter);
  162. srcLen += parserData->mSrcLength;
  163. allocBytesUsed += (int)(parserData->mAlloc.mPages.size() * BfAstAllocManager::PAGE_SIZE);
  164. largeAllocs += parserData->mAlloc.mLargeAllocSizes;
  165. }
  166. int allocPages = 0;
  167. int usedPages = 0;
  168. mAstAllocManager.GetStats(allocPages, usedPages);
  169. OutputDebugStrF("Parsers: %d Chars: %d UsedAlloc: %dk BytesPerChar: %d SysAllocPages: %d SysUsedPages: %d (%dk) LargeAllocs: %dk\n", (int)mEntries.size(), srcLen, allocBytesUsed / 1024,
  170. allocBytesUsed / BF_MAX(1, srcLen), allocPages, usedPages, (usedPages * BfAstAllocManager::PAGE_SIZE) / 1024, largeAllocs / 1024);
  171. //memReporter->AddBumpAlloc("BumpAlloc", mAstAllocManager);
  172. }
  173. void BfParserData::ReportMemory(MemReporter* memReporter)
  174. {
  175. memReporter->Add("JumpTable", mJumpTableSize * sizeof(BfLineStartEntry));
  176. memReporter->Add("Source", mSrcLength);
  177. memReporter->AddBumpAlloc("AstAlloc", mAlloc);
  178. }
  179. static int DecodeInt(uint8* buf, int& idx)
  180. {
  181. int value = 0;
  182. int shift = 0;
  183. int curByte;
  184. do
  185. {
  186. curByte = buf[idx++];
  187. value |= ((curByte & 0x7f) << shift);
  188. shift += 7;
  189. } while (curByte >= 128);
  190. // Sign extend negative numbers.
  191. if (((curByte & 0x40) != 0) && (shift < 64))
  192. value |= ~0LL << shift;
  193. return value;
  194. }
  195. static int gCurDataId = 0;
  196. BfParserData::BfParserData()
  197. {
  198. mDataId = (int)BfpSystem_InterlockedExchangeAdd32((uint32*)&gCurDataId, 1) + 1;
  199. mHash = 0;
  200. mRefCount = -1;
  201. mJumpTable = NULL;
  202. mJumpTableSize = 0;
  203. mFailed = false;
  204. mCharIdData = NULL;
  205. mUniqueParser = NULL;
  206. mDidReduce = false;
  207. mParseFileData = NULL;
  208. }
  209. BfParserData::~BfParserData()
  210. {
  211. if (mParseFileData != NULL)
  212. {
  213. BF_ASSERT(mParseFileData->mRefCount >= 0);
  214. mParseFileData->mRefCount--;
  215. if (mParseFileData->mRefCount == 0)
  216. {
  217. delete mParseFileData;
  218. gBfParserCache->mParseFileDataMap.Remove(mFileName);
  219. }
  220. }
  221. delete[] mJumpTable;
  222. delete[] mCharIdData;
  223. }
  224. void BfParserData::InitFileData()
  225. {
  226. BF_ASSERT(mParseFileData == NULL);
  227. BfParseFileData** valuePtr = NULL;
  228. if (gBfParserCache->mParseFileDataMap.TryAdd(mFileName, NULL, &valuePtr))
  229. {
  230. *valuePtr = new BfParseFileData();
  231. }
  232. mParseFileData = *valuePtr;
  233. mParseFileData->mRefCount++;
  234. }
  235. int BfParserData::GetCharIdAtIndex(int findIndex)
  236. {
  237. if (mCharIdData == NULL)
  238. return findIndex;
  239. int encodeIdx = 0;
  240. int charId = 1;
  241. int charIdx = 0;
  242. while (true)
  243. {
  244. int cmd = DecodeInt(mCharIdData, encodeIdx);
  245. if (cmd > 0)
  246. charId = cmd;
  247. else
  248. {
  249. int spanSize = -cmd;
  250. if ((findIndex >= charIdx) && (findIndex < charIdx + spanSize))
  251. return charId + (findIndex - charIdx);
  252. charId += spanSize;
  253. charIdx += spanSize;
  254. if (cmd == 0)
  255. return -1;
  256. }
  257. }
  258. }
  259. void BfParserData::GetLineCharAtIdx(int idx, int& line, int& lineChar)
  260. {
  261. if (mJumpTableSize <= 0)
  262. {
  263. line = 0;
  264. lineChar = 0;
  265. return;
  266. }
  267. if (idx >= mSrcLength)
  268. idx = mSrcLength - 1;
  269. auto* jumpEntry = mJumpTable + (idx / PARSER_JUMPTABLE_DIVIDE);
  270. if (jumpEntry->mCharIdx > idx)
  271. jumpEntry--;
  272. line = jumpEntry->mLineNum;
  273. lineChar = 0;
  274. int curSrcPos = jumpEntry->mCharIdx;
  275. while (curSrcPos < idx)
  276. {
  277. if (mSrc[curSrcPos] == '\n')
  278. {
  279. line++;
  280. lineChar = 0;
  281. }
  282. else
  283. {
  284. lineChar++;
  285. }
  286. curSrcPos++;
  287. }
  288. }
  289. bool BfParserData::IsUnwarnedAt(BfAstNode* node)
  290. {
  291. if (mUnwarns.empty())
  292. return false;
  293. auto unwarnItr = mUnwarns.upper_bound(node->GetSrcStart());
  294. if (unwarnItr == mUnwarns.begin())
  295. return false;
  296. unwarnItr--;
  297. int unwarnIdx = *unwarnItr;
  298. int checkIdx = node->GetSrcStart();
  299. int lineCount = 0;
  300. while (checkIdx > 0)
  301. {
  302. checkIdx--;
  303. if (checkIdx < unwarnIdx)
  304. return true;
  305. if (mSrc[checkIdx] == '\n')
  306. {
  307. lineCount++;
  308. // #unwarn must be immediately preceding the start of the statement containing this node
  309. if (lineCount == 2)
  310. return false;
  311. }
  312. }
  313. return true;
  314. }
  315. bool BfParserData::IsWarningEnabledAtSrcIndex(int warningNumber, int srcIdx)
  316. {
  317. int enabled = 1; //CDH TODO if/when we add warning level support, this default will change based on the warning number and the general project warning level setting
  318. int lastUnwarnPos = 0;
  319. for (const auto& it : mWarningEnabledChanges)
  320. {
  321. if (it.mKey > srcIdx)
  322. break;
  323. if (it.mValue.mWarningNumber == warningNumber)
  324. {
  325. if (it.mValue.mEnable)
  326. enabled++;
  327. else
  328. enabled--;
  329. }
  330. if (it.mValue.mWarningNumber == -1)
  331. lastUnwarnPos = -1;
  332. }
  333. return enabled > 0;
  334. }
  335. void BfParserData::Deref()
  336. {
  337. mRefCount--;
  338. BF_ASSERT(mRefCount >= 0);
  339. if (mRefCount == 0)
  340. {
  341. AutoCrit autoCrit(gBfParserCache->mCritSect);
  342. BfParserCache::DataEntry dataEntry;
  343. dataEntry.mParserData = this;
  344. bool didRemove = gBfParserCache->mEntries.Remove(dataEntry);
  345. BF_ASSERT(didRemove);
  346. delete this;
  347. }
  348. }
  349. //////////////////////////////////////////////////////////////////////////
  350. static int gParserCount = 0;
  351. BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem)
  352. {
  353. BfLogSys(bfSystem, "BfParser::BfParser %08X\n", this);
  354. gParserCount++;
  355. mTextVersion = -1;
  356. mEmbedKind = BfSourceEmbedKind_None;
  357. mUsingCache = false;
  358. mParserData = NULL;
  359. mAwaitingDelete = false;
  360. mScanOnly = false;
  361. mCompleteParse = false;
  362. mIsEmitted = false;
  363. mJumpTable = NULL;
  364. mProject = bfProject;
  365. mPassInstance = NULL;
  366. mSourceClassifier = NULL;
  367. mPrevRevision = NULL;
  368. mNextRevision = NULL;
  369. mOrigSrcLength = 0;
  370. mSrcAllocSize = -1;
  371. mSrcLength = 0;
  372. mSrcIdx = 0;
  373. mParserFlags = ParserFlag_None;
  374. mCursorIdx = -1;
  375. mCursorCheckIdx = -1;
  376. mLineStart = 0;
  377. //mCurToken = (BfSyntaxToken)0;
  378. mToken = BfToken_None;
  379. mSyntaxToken = BfSyntaxToken_None;
  380. mTokenStart = 0;
  381. mTokenEnd = 0;
  382. mLineNum = 0;
  383. mCompatMode = false;
  384. mQuickCompatMode = false;
  385. mLiteral.mWarnType = 0;
  386. mDataId = -1;
  387. mTriviaStart = 0;
  388. mParsingFailed = false;
  389. mInAsmBlock = false;
  390. mPreprocessorIgnoredSectionNode = NULL;
  391. mPreprocessorIgnoreDepth = 0;
  392. mAddedDependsDefines = false;
  393. if (bfProject != NULL)
  394. {
  395. for (auto macro : bfProject->mPreprocessorMacros)
  396. mPreprocessorDefines[macro] = BfDefineState_FromProject;
  397. }
  398. }
  399. //static std::set<BfAstNode*> gFoundNodes;
  400. BfParser::~BfParser()
  401. {
  402. int parserCount = gParserCount--;
  403. if (mParserData == NULL)
  404. {
  405. }
  406. else if (mParserData->mRefCount == -1)
  407. {
  408. // Owned data, never intended for cache
  409. mParserData->mSrc = NULL; // Count on BfSource dtor to release strc
  410. delete mParserData;
  411. }
  412. else if (mParserData->mRefCount == 0)
  413. {
  414. // Just never got added to the cache
  415. delete mParserData;
  416. }
  417. else
  418. {
  419. mParserData->Deref();
  420. }
  421. mSourceData = NULL;
  422. BfLogSys(mSystem, "BfParser::~BfParser %p\n", this);
  423. }
  424. void BfParser::SetCursorIdx(int cursorIdx)
  425. {
  426. mCursorIdx = cursorIdx;
  427. mCursorCheckIdx = cursorIdx;
  428. int checkIdx = cursorIdx;
  429. while (checkIdx > 0)
  430. {
  431. char c = mSrc[checkIdx - 1];
  432. if (!IsWhitespace(c))
  433. {
  434. if (c == '.')
  435. mCursorCheckIdx = checkIdx;
  436. break;
  437. }
  438. checkIdx--;
  439. }
  440. }
  441. //static int gDeleteCount = 0;
  442. //static int gIndentCount = 0;
  443. void BfParser::GetLineCharAtIdx(int idx, int& line, int& lineChar)
  444. {
  445. mParserData->GetLineCharAtIdx(idx, line, lineChar);
  446. }
  447. int BfParser::GetIndexAtLine(int line)
  448. {
  449. if (line == 0)
  450. return 0;
  451. int curLine = 0;
  452. for (int i = 0; i < mSrcLength; i++)
  453. {
  454. char c = mSrc[i];
  455. if (c == '\n')
  456. {
  457. curLine++;
  458. if (line == curLine)
  459. return i + 1;
  460. }
  461. }
  462. return -1;
  463. }
  464. void BfParser::Fail(const StringImpl& error, int offset)
  465. {
  466. mPassInstance->FailAt(error, mSourceData, mSrcIdx + offset);
  467. }
  468. void BfParser::UnexpectedCharacter()
  469. {
  470. if (mPreprocessorIgnoredSectionNode != NULL)
  471. return;
  472. int startIdx = mTokenStart;
  473. int endIdx = startIdx;
  474. char32_t c = u8_nextchar((char*)mSrc, &endIdx);
  475. int charLen = endIdx - startIdx;
  476. String str = "Unexpected character '";
  477. for (int i = 0; i < charLen; i++)
  478. str += mSrc[startIdx + i];
  479. str += StrFormat("' (0x%0X)", (int)c);
  480. mPassInstance->FailAt(str, mSourceData, startIdx);
  481. mSrcIdx = endIdx;
  482. }
  483. void BfParser::TokenFail(const StringImpl& error, int offset)
  484. {
  485. if (mPreprocessorIgnoredSectionNode == NULL)
  486. Fail(error, offset);
  487. }
  488. void BfParser::Init(uint64 cacheHash)
  489. {
  490. BF_ASSERT(mParserData == NULL);
  491. mParserData = new BfParserData();
  492. mSourceData = mParserData;
  493. mParserData->mFileName = mFileName;
  494. mParserData->InitFileData();
  495. if (mDataId != -1)
  496. mParserData->mDataId = mDataId;
  497. else
  498. mDataId = mParserData->mDataId;
  499. mParserData->mAstAllocManager = &gBfParserCache->mAstAllocManager;
  500. mParserData->mSrc = mSrc;
  501. mParserData->mSrcLength = mSrcLength;
  502. if (cacheHash != 0)
  503. {
  504. BfLogSysM("Creating cached parserData %p for %p %s\n", mParserData, this, mFileName.c_str());
  505. mParserData->mHash = cacheHash;
  506. mParserData->mRefCount = 0; // 0 means we want to EVENTUALLY write it to the cache
  507. mSrcAllocSize = -1;
  508. }
  509. else
  510. {
  511. BfLogSysM("Creating unique parserData %p for %p %s\n", mParserData, this, mFileName.c_str());
  512. mParserData->mUniqueParser = this;
  513. }
  514. mJumpTableSize = ((mSrcLength + 1) + PARSER_JUMPTABLE_DIVIDE - 1) / PARSER_JUMPTABLE_DIVIDE;
  515. mJumpTable = new BfLineStartEntry[mJumpTableSize];
  516. memset(mJumpTable, 0, mJumpTableSize * sizeof(BfLineStartEntry));
  517. mParserData->mJumpTable = mJumpTable;
  518. mParserData->mJumpTableSize = mJumpTableSize;
  519. mAlloc = &mParserData->mAlloc;
  520. mAlloc->mSourceData = mSourceData;
  521. }
  522. void BfParser::NewLine()
  523. {
  524. mLineStart = mSrcIdx;
  525. mLineNum++;
  526. if (mJumpTable == NULL)
  527. return;
  528. int idx = (mSrcIdx / PARSER_JUMPTABLE_DIVIDE);
  529. if (idx == 0)
  530. return;
  531. BF_ASSERT(idx < mJumpTableSize);
  532. BfLineStartEntry* jumpTableEntry = mJumpTable + idx;
  533. jumpTableEntry->mCharIdx = mSrcIdx;
  534. jumpTableEntry->mLineNum = mLineNum;
  535. }
  536. void BfParser::SetSource(const char* data, int length)
  537. {
  538. const int EXTRA_BUFFER_SIZE = 80; // Extra chars for a bit of AllocChars room
  539. //TODO: Check cache
  540. // Don't cache if we have a Cursorid set,
  541. // if mDataId != -1
  542. // if BfParerFlag != 0
  543. bool canCache = true;
  544. if (mDataId != -1)
  545. canCache = false;
  546. if (mParserFlags != 0)
  547. canCache = false;
  548. if (mCursorIdx != -1)
  549. canCache = false;
  550. if (mCompatMode)
  551. canCache = false;
  552. if (mQuickCompatMode)
  553. canCache = false;
  554. if (mFileName.IsEmpty())
  555. canCache = false;
  556. if (mProject == NULL)
  557. canCache = false;
  558. if (mIsEmitted)
  559. canCache = false;
  560. uint64 cacheHash = 0;
  561. if (canCache)
  562. {
  563. AutoCrit autoCrit(gBfParserCache->mCritSect);
  564. HashContext hashCtx;
  565. hashCtx.MixinStr(mFileName);
  566. hashCtx.Mixin(data, length);
  567. cacheHash = hashCtx.Finish64();
  568. BfParserCache::LookupEntry lookupEntry;
  569. lookupEntry.mFileName = mFileName;
  570. lookupEntry.mSrc = data;
  571. lookupEntry.mSrcLength = length;
  572. lookupEntry.mHash = cacheHash;
  573. lookupEntry.mProject = mProject;
  574. BfParserCache::DataEntry* dataEntryP;
  575. if (gBfParserCache->mEntries.TryGetWith(lookupEntry, &dataEntryP))
  576. {
  577. mUsingCache = true;
  578. mParserData = dataEntryP->mParserData;
  579. BF_ASSERT(mParserData->mDidReduce);
  580. BfLogSysM("Using cached parserData %p for %p %s\n", mParserData, this, mFileName.c_str());
  581. mParserData->mRefCount++;
  582. mSourceData = mParserData;
  583. mSrc = mParserData->mSrc;
  584. mSrcLength = mParserData->mSrcLength;
  585. mOrigSrcLength = mParserData->mSrcLength;
  586. mSrcAllocSize = -1;
  587. mSrcIdx = 0;
  588. mJumpTable = mParserData->mJumpTable;
  589. mJumpTableSize = mParserData->mJumpTableSize;
  590. mAlloc = &mParserData->mAlloc;
  591. return;
  592. }
  593. }
  594. mSrcLength = length;
  595. mOrigSrcLength = length;
  596. mSrcAllocSize = mSrcLength /*+ EXTRA_BUFFER_SIZE*/;
  597. char* ownedSrc = new char[mSrcAllocSize + 1];
  598. if (data != NULL)
  599. memcpy(ownedSrc, data, length);
  600. ownedSrc[length] = 0;
  601. mSrc = ownedSrc;
  602. mSrcIdx = 0;
  603. Init(cacheHash);
  604. }
  605. void BfParser::MoveSource(const char* data, int length) // Takes ownership of data ptr
  606. {
  607. mSrcLength = length;
  608. mOrigSrcLength = length;
  609. mSrcAllocSize = mSrcLength;
  610. mSrc = data;
  611. mSrcIdx = 0;
  612. Init();
  613. }
  614. void BfParser::RefSource(const char* data, int length)
  615. {
  616. mSrcLength = length;
  617. mOrigSrcLength = length;
  618. mSrcAllocSize = -1;
  619. mSrc = data;
  620. mSrcIdx = 0;
  621. Init();
  622. }
  623. bool BfParser::SrcPtrHasToken(const char* name)
  624. {
  625. const char* namePtr = name;
  626. int checkIdx = mSrcIdx - 1;
  627. while (*namePtr)
  628. {
  629. if (*(namePtr++) != mSrc[checkIdx])
  630. return false;
  631. checkIdx++;
  632. }
  633. if (!IsWhitespaceOrPunctuation(mSrc[checkIdx]))
  634. return false;
  635. mSrcIdx = checkIdx;
  636. mTokenEnd = checkIdx;
  637. return true;
  638. }
  639. void BfParser::AddErrorNode(int startIdx, int endIdx)
  640. {
  641. auto identifierNode = mAlloc->Alloc<BfIdentifierNode>();
  642. identifierNode->Init(mTriviaStart, startIdx, endIdx);
  643. //identifierNode->mSource = this;
  644. BfSource::AddErrorNode(identifierNode);
  645. }
  646. BfCommentKind BfParser::GetCommentKind(int startIdx)
  647. {
  648. if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '*') && (mSrc[startIdx + 2] == '*') && (mSrc[startIdx + 3] == '<'))
  649. return BfCommentKind_Documentation_Block_Post;
  650. if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '/') && (mSrc[startIdx + 2] == '/') && (mSrc[startIdx + 3] == '<'))
  651. return BfCommentKind_Documentation_Line_Post;
  652. if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '*') && (mSrc[startIdx + 2] == '*') && (mSrc[startIdx + 3] != '/'))
  653. return BfCommentKind_Documentation_Block_Pre;
  654. if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '/') && (mSrc[startIdx + 2] == '/') && (mSrc[startIdx + 3] != '/'))
  655. return BfCommentKind_Documentation_Line_Pre;
  656. if ((mSrc[startIdx] == '/') && (mSrc[startIdx + 1] == '*'))
  657. return BfCommentKind_Block;
  658. return BfCommentKind_Line;
  659. }
  660. bool BfParser::EvaluatePreprocessor(BfExpression* expr)
  661. {
  662. bool isInvalid = false;
  663. if (expr == NULL)
  664. return false;
  665. if (auto binaryOp = BfNodeDynCast<BfBinaryOperatorExpression>(expr))
  666. {
  667. switch (binaryOp->mOp)
  668. {
  669. case BfBinaryOp_ConditionalOr:
  670. return EvaluatePreprocessor(binaryOp->mLeft) || EvaluatePreprocessor(binaryOp->mRight);
  671. case BfBinaryOp_ConditionalAnd:
  672. return EvaluatePreprocessor(binaryOp->mLeft) && EvaluatePreprocessor(binaryOp->mRight);
  673. default: break;
  674. }
  675. }
  676. if (auto unaryOp = BfNodeDynCast<BfUnaryOperatorExpression>(expr))
  677. {
  678. switch (unaryOp->mOp)
  679. {
  680. case BfUnaryOp_Not:
  681. return !EvaluatePreprocessor(unaryOp->mExpression);
  682. default: break;
  683. }
  684. }
  685. if (auto identifier = BfNodeDynCast<BfIdentifierNode>(expr))
  686. {
  687. return HandleIfDef(identifier->ToString()) == MaybeBool_True;
  688. }
  689. if (auto parenExpr = BfNodeDynCast<BfParenthesizedExpression>(expr))
  690. {
  691. return EvaluatePreprocessor(parenExpr->mExpression);
  692. }
  693. if (auto literalExpr = BfNodeDynCast<BfLiteralExpression>(expr))
  694. {
  695. if (literalExpr->mValue.mTypeCode == BfTypeCode_Boolean)
  696. {
  697. return literalExpr->mValue.mBool;
  698. }
  699. }
  700. mPassInstance->Fail("Invalid preprocessor expression", expr);
  701. return false;
  702. }
  703. BfBlock* BfParser::ParseInlineBlock(int spaceIdx, int endIdx)
  704. {
  705. BfBlock* block = NULL;
  706. SizedArray<BfAstNode*, 8> childArr;
  707. mSrcIdx = spaceIdx;
  708. BfAstNode* startNode = NULL;
  709. int usedEndIdx = spaceIdx;
  710. int usedLineNum = mLineNum;
  711. int usedLineStart = mLineStart;
  712. while (true)
  713. {
  714. NextToken(endIdx + 1, false, true);
  715. if (mSyntaxToken == BfSyntaxToken_HIT_END_IDX)
  716. {
  717. mSrcIdx = usedEndIdx;
  718. mLineNum = usedLineNum;
  719. mLineStart = usedLineStart;
  720. auto lastNode = mSidechannelRootNode->GetLast();
  721. if (lastNode != NULL)
  722. mSrcIdx = std::max(mSrcIdx, lastNode->GetSrcEnd());
  723. break;
  724. }
  725. usedEndIdx = mSrcIdx;
  726. usedLineStart = mLineStart;
  727. usedLineNum = mLineNum;
  728. auto childNode = CreateNode();
  729. if (childNode == NULL)
  730. break;
  731. if ((childNode->IsA<BfCommentNode>()))
  732. {
  733. mSidechannelRootNode->Add(childNode);
  734. mPendingSideNodes.push_back(childNode);
  735. continue;
  736. }
  737. if (startNode == NULL)
  738. startNode = childNode;
  739. if (block == NULL)
  740. block = mAlloc->Alloc<BfBlock>();
  741. block->Add(childNode);
  742. childArr.push_back(childNode);
  743. //block->mChildArr.Add(childNode, &mAlloc);
  744. }
  745. if (block != NULL)
  746. block->Init(childArr, mAlloc);
  747. return block;
  748. }
  749. BfExpression* BfParser::CreateInlineExpressionFromNode(BfBlock* block)
  750. {
  751. BfReducer reducer;
  752. reducer.mPassInstance = mPassInstance;
  753. reducer.mAlloc = mAlloc;
  754. reducer.mCompatMode = mCompatMode;
  755. reducer.mVisitorPos = BfReducer::BfVisitorPos(block);
  756. reducer.mVisitorPos.MoveNext();
  757. auto startNode = reducer.mVisitorPos.GetCurrent();
  758. if (startNode == NULL)
  759. return NULL;
  760. auto paramExpression = reducer.CreateExpression(startNode);
  761. if ((paramExpression != NULL) && (reducer.mVisitorPos.GetNext() != NULL))
  762. mPassInstance->Fail("Expression parsing error", reducer.mVisitorPos.GetNext());
  763. return paramExpression;
  764. }
  765. void BfParser::HandlePragma(const StringImpl& pragma, BfBlock* block)
  766. {
  767. auto itr = block->begin();
  768. auto paramNode = *itr;
  769. if (paramNode->ToStringView() == "warning")
  770. {
  771. ++itr;
  772. //auto iterNode = paramNode->mNext;
  773. //BfAstNode* iterNode = parentNode->mChildArr.GetAs<BfAstNode*>(++curIdx);
  774. BfAstNode* iterNode = itr.Get();
  775. if (iterNode)
  776. {
  777. ++itr;
  778. bool enable;
  779. if (iterNode->ToStringView() == "disable")
  780. {
  781. enable = false;
  782. }
  783. else if (iterNode->ToStringView() == "restore")
  784. {
  785. enable = true;
  786. }
  787. else
  788. {
  789. enable = true;
  790. mPassInstance->FailAt("Expected \"disable\" or \"restore\" after \"warning\"", mSourceData, iterNode->GetSrcStart(), iterNode->GetSrcLength());
  791. }
  792. //iterNode = parentNode->mChildArr.GetAs<BfAstNode*>(++curIdx);
  793. iterNode = itr.Get();
  794. while (iterNode)
  795. {
  796. ++itr;
  797. auto tokenStr = iterNode->ToString();
  798. if (tokenStr != ",") // commas allowed between warning numbers but not required; we just ignore them
  799. {
  800. bool isNum = true;
  801. for (const auto it : tokenStr)
  802. {
  803. char c = it;
  804. if (c < '0' || c > '9')
  805. {
  806. isNum = false;
  807. break;
  808. }
  809. }
  810. if (isNum)
  811. {
  812. BfParserWarningEnabledChange wec;
  813. wec.mEnable = enable;
  814. wec.mWarningNumber = atoi(tokenStr.c_str());
  815. mParserData->mWarningEnabledChanges[iterNode->GetSrcStart()] = wec;
  816. }
  817. else
  818. {
  819. mPassInstance->FailAt("Expected decimal warning number", mSourceData, iterNode->GetSrcStart(), iterNode->GetSrcLength());
  820. }
  821. }
  822. //iterNode = parentNode->mChildArr.Get(++curIdx);
  823. iterNode = itr.Get();
  824. }
  825. }
  826. else
  827. {
  828. mPassInstance->FailAfterAt("Expected \"disable\" or \"restore\" after \"warning\"", mSourceData, paramNode->GetSrcEnd() - 1);
  829. }
  830. }
  831. else if (paramNode->ToStringView() == "format")
  832. {
  833. ++itr;
  834. BfAstNode* iterNode = itr.Get();
  835. if (iterNode)
  836. {
  837. if ((iterNode->ToStringView() != "disable") &&
  838. (iterNode->ToStringView() != "restore"))
  839. {
  840. mPassInstance->FailAfterAt("Expected \"disable\" or \"restore\" after \"format\"", mSourceData, paramNode->GetSrcEnd() - 1);
  841. }
  842. }
  843. }
  844. else
  845. {
  846. mPassInstance->FailAt("Unknown #pragma directive", mSourceData, paramNode->GetSrcStart(), paramNode->GetSrcLength());
  847. }
  848. }
  849. void BfParser::HandleDefine(const StringImpl& name, BfAstNode* paramNode)
  850. {
  851. mPreprocessorDefines[name] = BfDefineState_ManualSet;
  852. }
  853. void BfParser::HandleUndefine(const StringImpl& name)
  854. {
  855. mPreprocessorDefines[name] = BfDefineState_ManualUnset;
  856. }
  857. MaybeBool BfParser::HandleIfDef(const StringImpl& name)
  858. {
  859. if ((!mAddedDependsDefines) && (mProject != NULL) && (name.StartsWith("BF_DEPENDS_")))
  860. {
  861. for (auto project : mProject->mDependencies)
  862. {
  863. StringT<64> def = "BF_DEPENDS_";
  864. def.Append(project->mName);
  865. MakeUpper(def);
  866. for (auto& c : def)
  867. {
  868. if (!isalnum((uint8)c))
  869. c = '_';
  870. }
  871. mPreprocessorDefines[def] = BfDefineState_FromProject;
  872. }
  873. mAddedDependsDefines = true;
  874. }
  875. BfDefineState defineState;
  876. if (mPreprocessorDefines.TryGetValue(name, &defineState))
  877. {
  878. if (defineState == BfDefineState_FromProject)
  879. {
  880. mParserData->mDefines_Def.Add(name);
  881. }
  882. return (defineState != BfDefineState_ManualUnset) ? MaybeBool_True : MaybeBool_False;
  883. }
  884. else
  885. {
  886. mParserData->mDefines_NoDef.Add(name);
  887. return MaybeBool_False;
  888. }
  889. }
  890. MaybeBool BfParser::HandleProcessorCondition(BfBlock* paramNode)
  891. {
  892. if (paramNode == NULL)
  893. return MaybeBool_False;
  894. bool found = false;
  895. auto paramExpression = CreateInlineExpressionFromNode(paramNode);
  896. if (paramExpression != NULL)
  897. {
  898. return EvaluatePreprocessor(paramExpression) ? MaybeBool_True : MaybeBool_False;
  899. }
  900. return MaybeBool_False;
  901. }
  902. void BfParser::HandleInclude(BfAstNode* paramNode)
  903. {
  904. }
  905. void BfParser::HandleIncludeNext(BfAstNode* paramNode)
  906. {
  907. }
  908. bool BfParser::HandlePreprocessor()
  909. {
  910. int triviaStart = mTriviaStart;
  911. int checkIdx = 0;
  912. for (int checkIdx = mLineStart; checkIdx < mSrcIdx - 1; checkIdx++)
  913. {
  914. if (!isspace((uint8)mSrc[checkIdx]))
  915. {
  916. if (mPreprocessorIgnoreDepth == 0)
  917. {
  918. if (mSrc[mSrcIdx - 1] != '#')
  919. return false;
  920. mPassInstance->FailAt("Preprocessor directives must appear as the first non-whitespace character on a line", mSourceData, checkIdx);
  921. break;
  922. }
  923. else
  924. continue; // Keep searching for #endif
  925. }
  926. }
  927. String pragma;
  928. String pragmaParam;
  929. switch (mSrc[mSrcIdx - 1])
  930. {
  931. case '<':
  932. if (mPreprocessorIgnoreDepth > 0)
  933. return false;
  934. pragma = "<<<";
  935. break;
  936. case '=':
  937. if (mPreprocessorIgnoreDepth > 0)
  938. return false;
  939. pragma = "===";
  940. break;
  941. case '>':
  942. if (mPreprocessorIgnoreDepth > 1)
  943. return false;
  944. pragma = ">>>";
  945. break;
  946. }
  947. bool atEnd = false;
  948. int startIdx = mSrcIdx - 1;
  949. int spaceIdx = -1;
  950. int charIdx = -1;
  951. while (true)
  952. {
  953. char c = mSrc[mSrcIdx++];
  954. if (c == '\n')
  955. {
  956. int checkIdx = mSrcIdx - 2;
  957. bool hadSlash = false;
  958. while (checkIdx >= startIdx)
  959. {
  960. char checkC = mSrc[checkIdx];
  961. if (checkC == '\\')
  962. {
  963. hadSlash = true;
  964. break;
  965. }
  966. if ((checkC != ' ') && (checkC != '\t'))
  967. break;
  968. checkIdx--;
  969. }
  970. if (!hadSlash)
  971. break;
  972. }
  973. if (c == '\0')
  974. {
  975. mSrcIdx--;
  976. break;
  977. }
  978. if (charIdx == -1)
  979. {
  980. if (!pragma.IsEmpty())
  981. {
  982. if (!IsWhitespace(c))
  983. charIdx = mSrcIdx - 1;
  984. }
  985. else
  986. {
  987. if (!IsWhitespaceOrPunctuation(c))
  988. charIdx = mSrcIdx - 1;
  989. }
  990. }
  991. else if ((IsWhitespaceOrPunctuation(c)) && (spaceIdx == -1))
  992. spaceIdx = mSrcIdx - 1;
  993. }
  994. if (charIdx == -1)
  995. {
  996. mPassInstance->FailAt("Preprocessor directive expected", mSourceData, startIdx);
  997. return true;
  998. }
  999. int endIdx = mSrcIdx - 1;
  1000. while (endIdx >= startIdx)
  1001. {
  1002. if (!IsWhitespace(mSrc[endIdx]))
  1003. break;
  1004. endIdx--;
  1005. }
  1006. BfBlock* paramNode = NULL;
  1007. if (pragma.IsEmpty())
  1008. {
  1009. if (spaceIdx != -1)
  1010. {
  1011. pragma = String(mSrc + charIdx, mSrc + spaceIdx);
  1012. int breakIdx = spaceIdx;
  1013. while (spaceIdx <= endIdx)
  1014. {
  1015. if (!isspace((uint8)mSrc[spaceIdx]))
  1016. break;
  1017. spaceIdx++;
  1018. }
  1019. if (spaceIdx <= endIdx)
  1020. pragmaParam = String(mSrc + spaceIdx, mSrc + endIdx + 1);
  1021. paramNode = ParseInlineBlock(breakIdx, endIdx);
  1022. }
  1023. else
  1024. {
  1025. pragma = String(mSrc + charIdx, mSrc + endIdx + 1);
  1026. mSrcIdx = endIdx + 1;
  1027. }
  1028. }
  1029. else
  1030. {
  1031. mSrcIdx--;
  1032. }
  1033. bool wantsSingleParam = true;
  1034. bool addToPreprocessorAccept = false;
  1035. bool addToPreprocessorAcceptResolved = true;
  1036. bool wantedParam = false;
  1037. if (mPreprocessorIgnoreDepth > 0)
  1038. {
  1039. BF_ASSERT(!mPreprocessorNodeStack.empty());
  1040. int ignoreEnd = std::max(mPreprocessorIgnoredSectionNode->GetSrcStart(), mLineStart - 1);
  1041. if ((pragma == "endif") || (pragma == ">>>"))
  1042. {
  1043. mPreprocessorIgnoreDepth--;
  1044. if (mPreprocessorIgnoreDepth > 0)
  1045. return true;
  1046. mPreprocessorNodeStack.pop_back();
  1047. mPreprocessorIgnoredSectionNode->SetSrcEnd(ignoreEnd);
  1048. mPreprocessorIgnoredSectionNode = NULL;
  1049. triviaStart = ignoreEnd;
  1050. }
  1051. else if ((pragma == "if") ||
  1052. ((mCompatMode) && (pragma == "ifdef")) ||
  1053. ((mCompatMode) && (pragma == "ifndef")))
  1054. {
  1055. wantsSingleParam = false;
  1056. wantedParam = true;
  1057. mPreprocessorIgnoreDepth++;
  1058. }
  1059. else if (pragma == "else")
  1060. {
  1061. if (mCompatMode)
  1062. {
  1063. if (paramNode != NULL)
  1064. {
  1065. if (paramNode->ToString() == "if")
  1066. {
  1067. bool found = HandleProcessorCondition(paramNode) != MaybeBool_False;
  1068. if (found)
  1069. {
  1070. addToPreprocessorAccept = true;
  1071. mPreprocessorNodeStack.pop_back();
  1072. mPreprocessorIgnoreDepth = 0;
  1073. mPreprocessorIgnoredSectionNode->SetSrcEnd(ignoreEnd);
  1074. mPreprocessorIgnoredSectionNode = NULL;
  1075. triviaStart = ignoreEnd;
  1076. }
  1077. else
  1078. {
  1079. mPreprocessorIgnoredSectionStarts.insert(mSrcIdx);
  1080. }
  1081. return true;
  1082. }
  1083. }
  1084. }
  1085. if ((mPreprocessorIgnoreDepth == 1) && !mPreprocessorNodeStack.back().second)
  1086. {
  1087. addToPreprocessorAccept = true;
  1088. mPreprocessorNodeStack.pop_back();
  1089. mPreprocessorIgnoreDepth = 0;
  1090. mPreprocessorIgnoredSectionNode->SetSrcEnd(ignoreEnd);
  1091. mPreprocessorIgnoredSectionNode = NULL;
  1092. triviaStart = ignoreEnd;
  1093. }
  1094. }
  1095. else if (pragma == "elif")
  1096. {
  1097. wantsSingleParam = false;
  1098. if ((mPreprocessorIgnoreDepth == 1) && !mPreprocessorNodeStack.back().second)
  1099. {
  1100. wantedParam = true;
  1101. bool found = HandleProcessorCondition(paramNode) != MaybeBool_False;
  1102. if (found)
  1103. {
  1104. addToPreprocessorAccept = true;
  1105. mPreprocessorNodeStack.pop_back();
  1106. mPreprocessorIgnoreDepth = 0;
  1107. mPreprocessorIgnoredSectionNode->SetSrcEnd(ignoreEnd);
  1108. mPreprocessorIgnoredSectionNode = NULL;
  1109. triviaStart = ignoreEnd;
  1110. }
  1111. else
  1112. {
  1113. mPreprocessorIgnoredSectionStarts.insert(mSrcIdx);
  1114. }
  1115. }
  1116. }
  1117. if (mPreprocessorIgnoreDepth > 0)
  1118. return true;
  1119. }
  1120. else
  1121. {
  1122. if ((pragma == "if") || (pragma == "<<<") ||
  1123. ((mCompatMode) && (pragma == "ifdef")) ||
  1124. ((mCompatMode) && (pragma == "ifndef")))
  1125. {
  1126. wantsSingleParam = false;
  1127. wantedParam = true;
  1128. bool found = false;
  1129. if (pragma == "<<<")
  1130. {
  1131. mPassInstance->FailAt("Conflict marker found", mSourceData, startIdx, endIdx - startIdx + 1);
  1132. wantedParam = false;
  1133. found = true;
  1134. }
  1135. else if (!mQuickCompatMode)
  1136. {
  1137. if (pragma == "if")
  1138. found = HandleProcessorCondition(paramNode) != MaybeBool_False;
  1139. else if (pragma == "ifdef")
  1140. found = HandleIfDef(pragmaParam) != MaybeBool_False;
  1141. else if (pragma == "ifndef")
  1142. found = HandleIfDef(pragmaParam) != MaybeBool_True;
  1143. }
  1144. if (!found)
  1145. mPreprocessorIgnoredSectionStarts.insert(mSrcIdx);
  1146. addToPreprocessorAccept = true;
  1147. if ((!found) && (!mQuickCompatMode) && (!mCompleteParse))
  1148. {
  1149. addToPreprocessorAcceptResolved = false;
  1150. mPreprocessorIgnoreDepth = 1;
  1151. }
  1152. }
  1153. else if ((pragma == "else") || (pragma == "==="))
  1154. {
  1155. if (!mQuickCompatMode && !mCompleteParse)
  1156. {
  1157. if (mPreprocessorNodeStack.empty())
  1158. mPassInstance->FailAt("Unexpected #else", mSourceData, startIdx, mSrcIdx - startIdx);
  1159. else
  1160. {
  1161. BF_ASSERT(mPreprocessorNodeStack.back().second);
  1162. mPreprocessorIgnoreDepth = 1;
  1163. }
  1164. }
  1165. }
  1166. else if (pragma == "elif")
  1167. {
  1168. wantsSingleParam = false;
  1169. if (!mQuickCompatMode && !mCompleteParse)
  1170. {
  1171. if (mPreprocessorNodeStack.empty())
  1172. mPassInstance->FailAt("Unexpected #elif", mSourceData, startIdx, mSrcIdx - startIdx);
  1173. else
  1174. {
  1175. BF_ASSERT(mPreprocessorNodeStack.back().second);
  1176. mPreprocessorIgnoreDepth = 1;
  1177. }
  1178. }
  1179. wantedParam = true;
  1180. }
  1181. else if (pragma == "endif")
  1182. {
  1183. if (mPreprocessorNodeStack.empty())
  1184. mPassInstance->FailAt("Unexpected #endif", mSourceData, startIdx, mSrcIdx - startIdx);
  1185. else
  1186. mPreprocessorNodeStack.pop_back();
  1187. }
  1188. else if (pragma == "define")
  1189. {
  1190. if ((paramNode != NULL) && (!paramNode->mChildArr.IsEmpty()))
  1191. HandleDefine(paramNode->mChildArr[0]->ToString(), paramNode);
  1192. wantedParam = true;
  1193. }
  1194. else if (pragma == "undef")
  1195. {
  1196. if ((paramNode != NULL) && (!paramNode->mChildArr.IsEmpty()))
  1197. HandleUndefine(paramNode->mChildArr[0]->ToString());
  1198. wantedParam = true;
  1199. }
  1200. else if (pragma == "error")
  1201. {
  1202. wantsSingleParam = false;
  1203. mPassInstance->FailAt(pragmaParam, mSourceData, startIdx, mSrcIdx - startIdx);
  1204. wantedParam = true;
  1205. }
  1206. else if (pragma == "warning")
  1207. {
  1208. wantsSingleParam = false;
  1209. mPassInstance->WarnAt(BfWarning_CS1030_PragmaWarning, pragmaParam, mSourceData, startIdx, mSrcIdx - startIdx);
  1210. wantedParam = true;
  1211. }
  1212. else if (pragma == "region")
  1213. {
  1214. wantsSingleParam = false;
  1215. wantedParam = true;
  1216. }
  1217. else if (pragma == "endregion")
  1218. {
  1219. wantsSingleParam = false;
  1220. if (!pragmaParam.empty())
  1221. wantedParam = true;
  1222. }
  1223. else if (pragma == "pragma")
  1224. {
  1225. wantsSingleParam = false;
  1226. wantedParam = true;
  1227. if (paramNode != NULL)
  1228. HandlePragma(pragmaParam, paramNode);
  1229. }
  1230. else if (pragma == "unwarn")
  1231. {
  1232. mParserData->mUnwarns.insert(mSrcIdx);
  1233. }
  1234. else if ((mCompatMode) && (pragma == "include"))
  1235. {
  1236. HandleInclude(paramNode);
  1237. wantedParam = true;
  1238. }
  1239. else if ((mCompatMode) && (pragma == "include_next"))
  1240. {
  1241. HandleIncludeNext(paramNode);
  1242. wantedParam = true;
  1243. }
  1244. else
  1245. {
  1246. mPassInstance->FailAt("Unknown preprocessor directive", mSourceData, startIdx, mSrcIdx - startIdx);
  1247. }
  1248. }
  1249. if ((wantsSingleParam) && (paramNode != NULL) && (paramNode->mChildArr.size() > 1))
  1250. {
  1251. mPassInstance->FailAt("Only one parameter expected", mSourceData, paramNode->GetSrcStart(), paramNode->GetSrcLength());
  1252. }
  1253. if ((wantedParam) && (paramNode == NULL))
  1254. {
  1255. mPassInstance->FailAt("Expected parameter", mSourceData, startIdx, mSrcIdx - startIdx);
  1256. }
  1257. else if ((!wantedParam) && (paramNode != NULL))
  1258. {
  1259. mPassInstance->FailAt("Parameter not expected", mSourceData, startIdx, mSrcIdx - startIdx);
  1260. }
  1261. mTokenStart = charIdx;
  1262. mTokenEnd = charIdx + (int)pragma.length();
  1263. mTriviaStart = -1;
  1264. auto bfPreprocessorCmdNode = mAlloc->Alloc<BfIdentifierNode>();
  1265. bfPreprocessorCmdNode->Init(this);
  1266. mTriviaStart = triviaStart;
  1267. auto bfPreprocessorNode = mAlloc->Alloc<BfPreprocessorNode>();
  1268. mTokenStart = startIdx;
  1269. mTokenEnd = mSrcIdx;
  1270. bfPreprocessorNode->Init(this);
  1271. bfPreprocessorNode->Add(bfPreprocessorCmdNode);
  1272. bfPreprocessorNode->mCommand = bfPreprocessorCmdNode;
  1273. if (paramNode != NULL)
  1274. {
  1275. int curIdx = 0;
  1276. bfPreprocessorNode->mArgument = paramNode;
  1277. }
  1278. mPendingSideNodes.push_back(bfPreprocessorNode);
  1279. mTokenStart = mSrcIdx;
  1280. mTriviaStart = mSrcIdx;
  1281. triviaStart = mSrcIdx;
  1282. if (addToPreprocessorAccept)
  1283. mPreprocessorNodeStack.push_back(std::pair<BfAstNode*, bool>(bfPreprocessorNode, addToPreprocessorAcceptResolved));
  1284. if (mPreprocessorIgnoreDepth > 0)
  1285. {
  1286. mPreprocessorIgnoredSectionNode = mAlloc->Alloc<BfPreprocesorIgnoredSectionNode>();
  1287. mPreprocessorIgnoredSectionNode->Init(this);
  1288. mSidechannelRootNode->Add(mPreprocessorIgnoredSectionNode);
  1289. mPendingSideNodes.push_back(mPreprocessorIgnoredSectionNode);
  1290. }
  1291. return true;
  1292. }
  1293. static int ValSign(int64 val)
  1294. {
  1295. if (val < 0)
  1296. return -1;
  1297. if (val > 0)
  1298. return 1;
  1299. return 0;
  1300. }
  1301. template <int Len>
  1302. struct StrHashT
  1303. {
  1304. const static int HASH = 0;
  1305. };
  1306. template <>
  1307. struct StrHashT<4>
  1308. {
  1309. template <const char* Str>
  1310. struct DoHash
  1311. {
  1312. const static int HASH = (StrHashT<3>::HASH) ^ Str[4];
  1313. };
  1314. };
  1315. // This is little endian only
  1316. #define TOKEN_HASH(a, b, c, d) ((int)a << 0) | ((int)b << 8) | ((int)c << 16) | ((int)d << 24)
  1317. const int text_const = (1 << 2);
  1318. const int gClassConst = 0;
  1319. uint32 BfParser::GetTokenHash()
  1320. {
  1321. char hashChars[4] = { 0 };
  1322. int idx = 0;
  1323. uint32 tokenHash = 0;
  1324. int checkIdx = mSrcIdx - 1;
  1325. while ((!IsWhitespaceOrPunctuation(mSrc[checkIdx])) && (idx < 4))
  1326. {
  1327. hashChars[idx++] = mSrc[checkIdx];
  1328. checkIdx++;
  1329. }
  1330. return *((uint32*)hashChars);
  1331. }
  1332. double BfParser::ParseLiteralDouble()
  1333. {
  1334. char buf[256];
  1335. int len = std::min(mTokenEnd - mTokenStart, 255);
  1336. int outLen = 0;
  1337. for (int i = 0; i < len; i++)
  1338. {
  1339. char c = mSrc[mTokenStart + i];
  1340. if (c != '\'')
  1341. buf[outLen++] = c;
  1342. }
  1343. char c = buf[outLen - 1];
  1344. if ((c == 'd') || (c == 'D') || (c == 'f') || (c == 'F'))
  1345. buf[outLen - 1] = '\0';
  1346. else
  1347. buf[outLen] = '\0';
  1348. return strtod(buf, NULL);
  1349. }
  1350. void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePreprocessor)
  1351. {
  1352. auto prevToken = mToken;
  1353. mToken = BfToken_None;
  1354. if (mSyntaxToken == BfSyntaxToken_EOF)
  1355. Fail("Unexpected end of file");
  1356. mTriviaStart = mSrcIdx;
  1357. bool isLineStart = true;
  1358. bool isVerbatim = false;
  1359. int interpolateSetting = 0;
  1360. int stringStart = -1;
  1361. while (true)
  1362. {
  1363. bool setVerbatim = false;
  1364. bool setInterpolate = false;
  1365. uint32 checkTokenHash = 0;
  1366. if ((endIdx != -1) && (mSrcIdx >= endIdx))
  1367. {
  1368. mSyntaxToken = BfSyntaxToken_HIT_END_IDX;
  1369. return;
  1370. }
  1371. mTokenStart = mSrcIdx;
  1372. mTokenEnd = mSrcIdx + 1;
  1373. char c = mSrc[mSrcIdx++];
  1374. if (outerIsInterpolate)
  1375. {
  1376. if (c == '"')
  1377. {
  1378. mSyntaxToken = BfSyntaxToken_StringQuote;
  1379. return;
  1380. }
  1381. }
  1382. if ((mPreprocessorIgnoreDepth > 0) && (endIdx == -1))
  1383. {
  1384. if (c == 0)
  1385. {
  1386. mSyntaxToken = BfSyntaxToken_EOF;
  1387. mSrcIdx--;
  1388. break;
  1389. }
  1390. if ((c == '>') && (mSrc[mSrcIdx] == '>') && (mSrc[mSrcIdx + 1] == '>'))
  1391. {
  1392. // Allow through
  1393. }
  1394. else if ((c != '#') || (!isLineStart))
  1395. {
  1396. if (c == '\n')
  1397. {
  1398. NewLine();
  1399. isLineStart = true;
  1400. continue;
  1401. }
  1402. if (IsWhitespace(c))
  1403. continue;
  1404. isLineStart = false;
  1405. continue;
  1406. }
  1407. }
  1408. switch (c)
  1409. {
  1410. case '!':
  1411. if (mSrc[mSrcIdx] == '=')
  1412. {
  1413. if (mSrc[mSrcIdx + 1] == '=')
  1414. {
  1415. mToken = BfToken_CompareStrictNotEquals;
  1416. ++mSrcIdx;
  1417. mTokenEnd = ++mSrcIdx;
  1418. }
  1419. else
  1420. {
  1421. mToken = BfToken_CompareNotEquals;
  1422. mTokenEnd = ++mSrcIdx;
  1423. }
  1424. }
  1425. else
  1426. mToken = BfToken_Bang;
  1427. mSyntaxToken = BfSyntaxToken_Token;
  1428. return;
  1429. case '=':
  1430. if (mSrc[mSrcIdx] == '=')
  1431. {
  1432. if (mSrc[mSrcIdx + 1] == '=')
  1433. {
  1434. if (mSrc[mSrcIdx + 2] == '=')
  1435. {
  1436. if (HandlePreprocessor())
  1437. {
  1438. // Conflict split
  1439. break;
  1440. }
  1441. else
  1442. {
  1443. mToken = BfToken_CompareStrictEquals;
  1444. ++mSrcIdx;
  1445. mTokenEnd = ++mSrcIdx;
  1446. }
  1447. }
  1448. else
  1449. {
  1450. mToken = BfToken_CompareStrictEquals;
  1451. ++mSrcIdx;
  1452. mTokenEnd = ++mSrcIdx;
  1453. }
  1454. }
  1455. else
  1456. {
  1457. mToken = BfToken_CompareEquals;
  1458. mTokenEnd = ++mSrcIdx;
  1459. }
  1460. }
  1461. else if (mSrc[mSrcIdx] == '>')
  1462. {
  1463. mToken = BfToken_FatArrow;
  1464. mTokenEnd = ++mSrcIdx;
  1465. }
  1466. else
  1467. mToken = BfToken_AssignEquals;
  1468. mSyntaxToken = BfSyntaxToken_Token;
  1469. return;
  1470. case '+':
  1471. if (mSrc[mSrcIdx] == '+')
  1472. {
  1473. mToken = BfToken_DblPlus;
  1474. mTokenEnd = ++mSrcIdx;
  1475. }
  1476. else if (mSrc[mSrcIdx] == '=')
  1477. {
  1478. mToken = BfToken_PlusEquals;
  1479. mTokenEnd = ++mSrcIdx;
  1480. }
  1481. else
  1482. mToken = BfToken_Plus;
  1483. mSyntaxToken = BfSyntaxToken_Token;
  1484. return;
  1485. case '^':
  1486. if (mSrc[mSrcIdx] == '=')
  1487. {
  1488. mToken = BfToken_XorEquals;
  1489. mTokenEnd = ++mSrcIdx;
  1490. }
  1491. else
  1492. mToken = BfToken_Carat;
  1493. mSyntaxToken = BfSyntaxToken_Token;
  1494. return;
  1495. case '~':
  1496. mToken = BfToken_Tilde;
  1497. mSyntaxToken = BfSyntaxToken_Token;
  1498. return;
  1499. case '%':
  1500. if (mSrc[mSrcIdx] == '=')
  1501. {
  1502. mToken = BfToken_ModulusEquals;
  1503. mTokenEnd = ++mSrcIdx;
  1504. }
  1505. else
  1506. mToken = BfToken_Modulus;
  1507. mSyntaxToken = BfSyntaxToken_Token;
  1508. return;
  1509. case '&':
  1510. if (mSrc[mSrcIdx] == '&')
  1511. {
  1512. mToken = BfToken_DblAmpersand;
  1513. mTokenEnd = ++mSrcIdx;
  1514. }
  1515. else if (mSrc[mSrcIdx] == '=')
  1516. {
  1517. mToken = BfToken_AndEquals;
  1518. mTokenEnd = ++mSrcIdx;
  1519. }
  1520. else if (mSrc[mSrcIdx] == '+')
  1521. {
  1522. if (mSrc[mSrcIdx + 1] == '=')
  1523. {
  1524. mToken = BfToken_AndPlusEquals;
  1525. ++mSrcIdx;
  1526. }
  1527. else
  1528. mToken = BfToken_AndPlus;
  1529. mTokenEnd = ++mSrcIdx;
  1530. }
  1531. else if (mSrc[mSrcIdx] == '-')
  1532. {
  1533. if (mSrc[mSrcIdx + 1] == '=')
  1534. {
  1535. mToken = BfToken_AndMinusEquals;
  1536. ++mSrcIdx;
  1537. }
  1538. else
  1539. mToken = BfToken_AndMinus;
  1540. mTokenEnd = ++mSrcIdx;
  1541. }
  1542. else if (mSrc[mSrcIdx] == '*')
  1543. {
  1544. if (mSrc[mSrcIdx + 1] == '=')
  1545. {
  1546. mToken = BfToken_AndStarEquals;
  1547. ++mSrcIdx;
  1548. }
  1549. else
  1550. mToken = BfToken_AndStar;
  1551. mTokenEnd = ++mSrcIdx;
  1552. }
  1553. else
  1554. mToken = BfToken_Ampersand;
  1555. mSyntaxToken = BfSyntaxToken_Token;
  1556. return;
  1557. case '|':
  1558. if (mSrc[mSrcIdx] == '|')
  1559. {
  1560. mToken = BfToken_DblBar;
  1561. mTokenEnd = ++mSrcIdx;
  1562. }
  1563. else if (mSrc[mSrcIdx] == '=')
  1564. {
  1565. mToken = BfToken_OrEquals;
  1566. mTokenEnd = ++mSrcIdx;
  1567. }
  1568. else
  1569. mToken = BfToken_Bar;
  1570. mSyntaxToken = BfSyntaxToken_Token;
  1571. return;
  1572. case '*':
  1573. if (mSrc[mSrcIdx] == '=')
  1574. {
  1575. mToken = BfToken_MultiplyEquals;
  1576. mTokenEnd = ++mSrcIdx;
  1577. }
  1578. else
  1579. mToken = BfToken_Star;
  1580. mSyntaxToken = BfSyntaxToken_Token;
  1581. return;
  1582. case '?':
  1583. if (mSrc[mSrcIdx] == '?')
  1584. {
  1585. mTokenEnd = ++mSrcIdx;
  1586. if (mSrc[mSrcIdx] == '=')
  1587. {
  1588. mToken = BfToken_NullCoalsceEquals;
  1589. mTokenEnd = ++mSrcIdx;
  1590. }
  1591. else
  1592. mToken = BfToken_DblQuestion;
  1593. }
  1594. else if (mSrc[mSrcIdx] == '.')
  1595. {
  1596. mToken = BfToken_QuestionDot;
  1597. mTokenEnd = ++mSrcIdx;
  1598. }
  1599. else if (mSrc[mSrcIdx] == '[')
  1600. {
  1601. mToken = BfToken_QuestionLBracket;
  1602. mTokenEnd = ++mSrcIdx;
  1603. }
  1604. else
  1605. mToken = BfToken_Question;
  1606. mSyntaxToken = BfSyntaxToken_Token;
  1607. return;
  1608. case '<':
  1609. if (mSrc[mSrcIdx] == '<')
  1610. {
  1611. mTokenEnd = ++mSrcIdx;
  1612. if (mSrc[mSrcIdx] == '=')
  1613. {
  1614. mToken = BfToken_ShiftLeftEquals;
  1615. mTokenEnd = ++mSrcIdx;
  1616. }
  1617. else if (mSrc[mSrcIdx] == '<')
  1618. {
  1619. mSrcIdx--;
  1620. if (HandlePreprocessor())
  1621. {
  1622. // Conflict end
  1623. break;
  1624. }
  1625. else
  1626. {
  1627. mSrcIdx++;
  1628. mToken = BfToken_LDblChevron;
  1629. }
  1630. }
  1631. else
  1632. mToken = BfToken_LDblChevron;
  1633. }
  1634. else if (mSrc[mSrcIdx] == '=')
  1635. {
  1636. if (mSrc[mSrcIdx + 1] == '>')
  1637. {
  1638. mToken = BfToken_Spaceship;
  1639. mSrcIdx += 2;
  1640. mTokenEnd = mSrcIdx;
  1641. }
  1642. else
  1643. {
  1644. mToken = BfToken_LessEquals;
  1645. mTokenEnd = ++mSrcIdx;
  1646. }
  1647. }
  1648. else
  1649. mToken = BfToken_LChevron;
  1650. mSyntaxToken = BfSyntaxToken_Token;
  1651. return;
  1652. case '>':
  1653. if (mSrc[mSrcIdx] == '>')
  1654. {
  1655. mTokenEnd = ++mSrcIdx;
  1656. if (mSrc[mSrcIdx] == '=')
  1657. {
  1658. mToken = BfToken_ShiftRightEquals;
  1659. mTokenEnd = ++mSrcIdx;
  1660. }
  1661. else if (mSrc[mSrcIdx] == '>')
  1662. {
  1663. mSrcIdx--;
  1664. if (HandlePreprocessor())
  1665. {
  1666. // Conflict start
  1667. break;
  1668. }
  1669. else
  1670. {
  1671. mSrcIdx++;
  1672. mToken = BfToken_RDblChevron;
  1673. }
  1674. }
  1675. else
  1676. mToken = BfToken_RDblChevron;
  1677. }
  1678. else if (mSrc[mSrcIdx] == '=')
  1679. {
  1680. mToken = BfToken_GreaterEquals;
  1681. mTokenEnd = ++mSrcIdx;
  1682. }
  1683. else
  1684. mToken = BfToken_RChevron;
  1685. mSyntaxToken = BfSyntaxToken_Token;
  1686. return;
  1687. case '@':
  1688. setVerbatim = true;
  1689. c = mSrc[mSrcIdx];
  1690. if ((c == '\"') || (c == '$'))
  1691. {
  1692. setVerbatim = true;
  1693. }
  1694. else if (((c >= 'A') && (c <= 'a')) || ((c >= 'a') && (c <= 'z')) || (c == '_') || (c == '@'))
  1695. {
  1696. setVerbatim = true;
  1697. }
  1698. else
  1699. {
  1700. mSyntaxToken = BfSyntaxToken_Identifier;
  1701. return;
  1702. }
  1703. break;
  1704. case '$':
  1705. c = mSrc[mSrcIdx];
  1706. if ((c == '\"') || (c == '@') || (c == '$'))
  1707. {
  1708. setInterpolate = true;
  1709. }
  1710. else if (!mCompatMode)
  1711. Fail("Expected to precede string");
  1712. break;
  1713. case '"':
  1714. case '\'':
  1715. {
  1716. SizedArray<BfUnscopedBlock*, 4> interpolateExpressions;
  1717. String lineHeader;
  1718. String strLiteral;
  1719. char startChar = c;
  1720. bool isMultiline = false;
  1721. int triviaStart = mTriviaStart;
  1722. if ((mSrc[mSrcIdx] == '"') && (mSrc[mSrcIdx + 1] == '"'))
  1723. {
  1724. isMultiline = true;
  1725. mSrcIdx += 2;
  1726. }
  1727. int contentErrorStart = -1;
  1728. int lineIdx = 0;
  1729. int lineIndentIdx = -1;
  1730. if (isMultiline)
  1731. {
  1732. int checkIdx = mSrcIdx;
  1733. int lineStartIdx = checkIdx;
  1734. while (true)
  1735. {
  1736. char c = mSrc[checkIdx++];
  1737. if ((c == '"') && (mSrc[checkIdx] == '"') && (mSrc[checkIdx + 1] == '"'))
  1738. {
  1739. lineIndentIdx = lineStartIdx;
  1740. for (int i = lineStartIdx; i < checkIdx - 1; i++)
  1741. {
  1742. char c = mSrc[i];
  1743. if ((c != '\t') && (c != ' '))
  1744. {
  1745. mPassInstance->FailAt("Multi-line string literal closing delimiter must begin on a new line", mSourceData, i, checkIdx - i + 3);
  1746. break;
  1747. }
  1748. lineHeader.Append(c);
  1749. }
  1750. break;
  1751. }
  1752. else if (c == '\n')
  1753. {
  1754. if (contentErrorStart != -1)
  1755. {
  1756. mPassInstance->FailAt("Multi-line string literal content must begin on a new line", mSourceData, contentErrorStart, checkIdx - contentErrorStart - 1);
  1757. contentErrorStart = -1;
  1758. }
  1759. lineStartIdx = checkIdx;
  1760. lineIdx++;
  1761. }
  1762. else if (c == '\0')
  1763. break; // Will throw an error in next pass
  1764. else if ((c == ' ') || (c == '\t') || (c == '\r'))
  1765. {
  1766. // Allow
  1767. }
  1768. else if (lineIdx == 0)
  1769. {
  1770. if (contentErrorStart == -1)
  1771. contentErrorStart = checkIdx - 1;
  1772. }
  1773. }
  1774. }
  1775. int lineCount = lineIdx + 1;
  1776. lineIdx = 0;
  1777. int lineStart = mSrcIdx;
  1778. while (true)
  1779. {
  1780. char c = mSrc[mSrcIdx++];
  1781. if (c == '\0')
  1782. {
  1783. // Invalid file end
  1784. mPassInstance->FailAt("String not terminated", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  1785. mSrcIdx--;
  1786. break;
  1787. }
  1788. else if (c == '\n')
  1789. {
  1790. if (isMultiline)
  1791. {
  1792. lineIdx++;
  1793. if ((lineIdx > 1) && (lineIdx < lineCount - 1))
  1794. {
  1795. strLiteral += "\n";
  1796. }
  1797. lineStart = mSrcIdx;
  1798. for (int i = 0; i < lineHeader.GetLength(); i++)
  1799. {
  1800. char wantC = lineHeader[i];
  1801. char c = mSrc[mSrcIdx];
  1802. if (c == '\r')
  1803. continue;
  1804. if (c == '\n')
  1805. break;
  1806. if (wantC == c)
  1807. {
  1808. mSrcIdx++;
  1809. }
  1810. else
  1811. {
  1812. BfError* error = NULL;
  1813. if (c == ' ')
  1814. {
  1815. error = mPassInstance->FailAt("Unexpected space in indentation of line in multi-line string literal", mSourceData, mSrcIdx, 1, BfFailFlag_ShowSpaceChars);
  1816. }
  1817. else if (c == '\t')
  1818. {
  1819. error = mPassInstance->FailAt("Unexpected tab in indentation of line in multi-line string literal", mSourceData, mSrcIdx, 1, BfFailFlag_ShowSpaceChars);
  1820. }
  1821. else
  1822. {
  1823. error = mPassInstance->FailAt("Insufficient indentation of line in multi-line string literal", mSourceData, lineStart, mSrcIdx - lineStart + 1, BfFailFlag_ShowSpaceChars);
  1824. }
  1825. if (error != NULL)
  1826. {
  1827. mPassInstance->MoreInfoAt("Change indentation of this line to match closing delimiter", mSourceData, lineIndentIdx, lineHeader.GetLength(), BfFailFlag_ShowSpaceChars);
  1828. }
  1829. break;
  1830. }
  1831. }
  1832. NewLine();
  1833. }
  1834. else
  1835. {
  1836. mSrcIdx--;
  1837. int errorIdx = mSrcIdx - 1;
  1838. while ((errorIdx > 0) && (IsWhitespace(mSrc[errorIdx])))
  1839. errorIdx--;
  1840. mPassInstance->FailAfterAt("Newline not allowed in string", mSourceData, errorIdx);
  1841. break;
  1842. }
  1843. }
  1844. else if ((c == '"') && (c == startChar))
  1845. {
  1846. if (isMultiline)
  1847. {
  1848. if ((mSrc[mSrcIdx] == '"') && (mSrc[mSrcIdx + 1] == '"')) // Triple quote
  1849. {
  1850. // Done
  1851. mSrcIdx += 2;
  1852. break;
  1853. }
  1854. strLiteral += '"';
  1855. }
  1856. else
  1857. {
  1858. if (mSrc[mSrcIdx] == '"') // Double quote
  1859. {
  1860. strLiteral += '"';
  1861. mSrcIdx++;
  1862. }
  1863. else
  1864. break;
  1865. }
  1866. }
  1867. else if ((c == '\'') && (c == startChar))
  1868. {
  1869. break;
  1870. }
  1871. else if ((c == '\\') && (!isVerbatim))
  1872. {
  1873. char c = mSrc[mSrcIdx++];
  1874. switch (c)
  1875. {
  1876. case '0':
  1877. strLiteral += '\0';
  1878. break;
  1879. case 'a':
  1880. strLiteral += '\a';
  1881. break;
  1882. case 'b':
  1883. strLiteral += '\b';
  1884. break;
  1885. case 'f':
  1886. strLiteral += '\f';
  1887. break;
  1888. case 'n':
  1889. strLiteral += '\n';
  1890. break;
  1891. case 'r':
  1892. strLiteral += '\r';
  1893. break;
  1894. case 't':
  1895. strLiteral += '\t';
  1896. break;
  1897. case 'v':
  1898. strLiteral += '\v';
  1899. break;
  1900. case '\\':
  1901. case '"':
  1902. case '\'':
  1903. strLiteral += c;
  1904. break;
  1905. case '{':
  1906. case '}':
  1907. strLiteral += c;
  1908. if (interpolateSetting > 0)
  1909. strLiteral += c;
  1910. else
  1911. Fail("Invalid escape sequence");
  1912. break;
  1913. case 'x':
  1914. {
  1915. int wantHexChars = 2;
  1916. int hexVal = 0;
  1917. int numHexChars = 0;
  1918. while (true)
  1919. {
  1920. char c = mSrc[mSrcIdx];
  1921. int hexChar = 0;
  1922. if ((c >= '0') && (c <= '9'))
  1923. hexChar = c - '0';
  1924. else if ((c >= 'a') && (c <= 'f'))
  1925. hexChar = c - 'a' + 0xa;
  1926. else if ((c >= 'A') && (c <= 'F'))
  1927. hexChar = c - 'A' + 0xA;
  1928. else
  1929. {
  1930. Fail("Expected two hex characters");
  1931. break;
  1932. }
  1933. mSrcIdx++;
  1934. numHexChars++;
  1935. hexVal = (hexVal * 0x10) + hexChar;
  1936. if (numHexChars == wantHexChars)
  1937. break;
  1938. }
  1939. strLiteral += (char)hexVal;
  1940. }
  1941. break;
  1942. case 'u':
  1943. {
  1944. if (mSrc[mSrcIdx] != '{')
  1945. {
  1946. Fail("Expected hexadecimal code in braces after unicode escape");
  1947. break;
  1948. }
  1949. mSrcIdx++;
  1950. int hexStart = mSrcIdx;
  1951. int hexVal = 0;
  1952. int numHexChars = 0;
  1953. while (true)
  1954. {
  1955. char c = mSrc[mSrcIdx];
  1956. int hexChar = 0;
  1957. if (c == '}')
  1958. {
  1959. if (numHexChars == 0)
  1960. Fail("Unicode escape sequence expects hex digits");
  1961. mSrcIdx++;
  1962. break;
  1963. }
  1964. if ((c >= '0') && (c <= '9'))
  1965. hexChar = c - '0';
  1966. else if ((c >= 'a') && (c <= 'f'))
  1967. hexChar = c - 'a' + 0xa;
  1968. else if ((c >= 'A') && (c <= 'F'))
  1969. hexChar = c - 'A' + 0xA;
  1970. else
  1971. {
  1972. Fail("Hex encoding error");
  1973. break;
  1974. }
  1975. mSrcIdx++;
  1976. numHexChars++;
  1977. if (numHexChars > 8)
  1978. {
  1979. Fail("Too many hex digits for an unicode scalar");
  1980. }
  1981. hexVal = (hexVal * 0x10) + hexChar;
  1982. }
  1983. char outStrUTF8[8];
  1984. int size = u8_toutf8(outStrUTF8, 8, (uint32)hexVal);
  1985. if (size == 0)
  1986. {
  1987. mPassInstance->FailAt("Invalid unicode scalar", mSourceData, hexStart, mSrcIdx - hexStart - 1);
  1988. }
  1989. strLiteral += outStrUTF8;
  1990. }
  1991. break;
  1992. default:
  1993. Fail("Unrecognized escape sequence");
  1994. strLiteral += c;
  1995. }
  1996. }
  1997. else
  1998. {
  1999. strLiteral += c;
  2000. if (interpolateSetting > 0)
  2001. {
  2002. if (c == '{')
  2003. {
  2004. int braceCount = 1;
  2005. while (mSrc[mSrcIdx] == '{')
  2006. {
  2007. braceCount++;
  2008. mSrcIdx++;
  2009. }
  2010. int literalBraces = braceCount;
  2011. if (((interpolateSetting == 1) && (braceCount % 2 == 1)) ||
  2012. ((interpolateSetting > 1) && (braceCount >= interpolateSetting)))
  2013. {
  2014. BfUnscopedBlock* newBlock = mAlloc->Alloc<BfUnscopedBlock>();
  2015. mTokenStart = mSrcIdx - interpolateSetting;
  2016. mTriviaStart = mTokenStart;
  2017. mTokenEnd = mTokenStart + 1;
  2018. mToken = BfToken_LBrace;
  2019. newBlock->mOpenBrace = (BfTokenNode*)CreateNode();
  2020. newBlock->Init(this);
  2021. ParseBlock(newBlock, 1, true);
  2022. if (mToken == BfToken_RBrace)
  2023. {
  2024. newBlock->mCloseBrace = (BfTokenNode*)CreateNode();
  2025. newBlock->SetSrcEnd(mSrcIdx);
  2026. mSrcIdx--;
  2027. }
  2028. else if (mSyntaxToken == BfSyntaxToken_StringQuote)
  2029. {
  2030. mSrcIdx--;
  2031. mPassInstance->FailAfterAt("Expected '}'", mSourceData, newBlock->GetSrcEnd() - 1);
  2032. }
  2033. mInAsmBlock = false;
  2034. interpolateExpressions.Add(newBlock);
  2035. }
  2036. if (interpolateSetting == 1)
  2037. {
  2038. for (int i = 0; i < braceCount - 1; i++)
  2039. strLiteral += '{';
  2040. }
  2041. else
  2042. {
  2043. if (braceCount >= interpolateSetting)
  2044. {
  2045. for (int i = 0; i < (braceCount - interpolateSetting) * 2; i++)
  2046. strLiteral += '{';
  2047. }
  2048. else
  2049. {
  2050. for (int i = 0; i < braceCount * 2 - 1; i++)
  2051. strLiteral += '{';
  2052. }
  2053. }
  2054. }
  2055. else if (c == '}')
  2056. {
  2057. int braceCount = 1;
  2058. while (mSrc[mSrcIdx] == '}')
  2059. {
  2060. braceCount++;
  2061. mSrcIdx++;
  2062. }
  2063. bool isClosingBrace = false;
  2064. if (!interpolateExpressions.IsEmpty())
  2065. {
  2066. auto block = interpolateExpressions.back();
  2067. if (block->mCloseBrace == NULL)
  2068. {
  2069. mTokenStart = mSrcIdx - 1;
  2070. mTriviaStart = mTokenStart;
  2071. mTokenEnd = mTokenStart + 1;
  2072. mToken = BfToken_RBrace;
  2073. block->mCloseBrace = (BfTokenNode*)CreateNode();
  2074. block->SetSrcEnd(mSrcIdx);
  2075. isClosingBrace = true;
  2076. }
  2077. else if (block->mCloseBrace->mSrcStart == mSrcIdx - braceCount)
  2078. {
  2079. block->mCloseBrace->mSrcEnd = mSrcIdx - braceCount + interpolateSetting;
  2080. isClosingBrace = true;
  2081. }
  2082. }
  2083. if (interpolateSetting == 1)
  2084. {
  2085. for (int i = 0; i < braceCount - 1; i++)
  2086. strLiteral += '}';
  2087. }
  2088. else
  2089. {
  2090. if (isClosingBrace)
  2091. {
  2092. if (braceCount < interpolateSetting)
  2093. Fail("Mismatched closing brace set");
  2094. for (int i = 0; i < (braceCount - interpolateSetting) * 2; i++)
  2095. strLiteral += '}';
  2096. }
  2097. else
  2098. {
  2099. for (int i = 0; i < braceCount * 2 - 1; i++)
  2100. strLiteral += '}';
  2101. }
  2102. }
  2103. }
  2104. }
  2105. }
  2106. }
  2107. if (stringStart != -1)
  2108. {
  2109. mTokenStart = stringStart;
  2110. stringStart = -1;
  2111. }
  2112. mTriviaStart = triviaStart;
  2113. mTokenEnd = mSrcIdx;
  2114. mSyntaxToken = BfSyntaxToken_Literal;
  2115. if (startChar == '\'')
  2116. {
  2117. mLiteral.mTypeCode = BfTypeCode_Char8;
  2118. if (strLiteral.length() == 0)
  2119. {
  2120. if (mPreprocessorIgnoredSectionNode == NULL)
  2121. mPassInstance->FailAt("Empty char literal", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2122. }
  2123. else if (strLiteral.length() > 1)
  2124. {
  2125. int utf8Len = u8_seqlen((char*)strLiteral.c_str());
  2126. if (utf8Len == (int)strLiteral.length())
  2127. {
  2128. mLiteral.mUInt64 = u8_toucs((char*)strLiteral.c_str(), (int)strLiteral.length());
  2129. }
  2130. else if (mPreprocessorIgnoredSectionNode == NULL)
  2131. {
  2132. bool isGraphemeCluster = false;
  2133. // There's no explicit unicode limit to how many diacriticals a grapheme cluster can contain,
  2134. // but we apply a limit for sanity for the purpose of this error
  2135. if (strLiteral.length() < 64)
  2136. {
  2137. int numCodePoints;
  2138. int numCombiningMarks;
  2139. UTF8Categorize(strLiteral.c_str(), (int)strLiteral.length(), numCodePoints, numCombiningMarks);
  2140. isGraphemeCluster = numCodePoints - numCombiningMarks <= 1;
  2141. }
  2142. if (isGraphemeCluster)
  2143. mPassInstance->FailAt("Grapheme clusters cannot be used as character literals", mSourceData, mTokenStart + 1, mSrcIdx - mTokenStart - 2);
  2144. else
  2145. mPassInstance->FailAt("Too many characters in character literal", mSourceData, mTokenStart + 1, mSrcIdx - mTokenStart - 2);
  2146. }
  2147. }
  2148. else
  2149. {
  2150. mLiteral.mInt64 = (uint8)strLiteral[0];
  2151. }
  2152. if (mLiteral.mInt64 >= 0x8000) // Use 0x8000 to remain UTF16-compatible
  2153. mLiteral.mTypeCode = BfTypeCode_Char32;
  2154. else if (mLiteral.mInt64 >= 0x80) // Use 0x80 to remain UTF8-compatible
  2155. mLiteral.mTypeCode = BfTypeCode_Char16;
  2156. }
  2157. else
  2158. {
  2159. auto* strLiteralPtr = new String(std::move(strLiteral));
  2160. mParserData->mStringLiterals.push_back(strLiteralPtr);
  2161. mLiteral.mTypeCode = BfTypeCode_CharPtr;
  2162. mLiteral.mString = strLiteralPtr;
  2163. }
  2164. if (interpolateSetting > 0)
  2165. {
  2166. if (mLiteral.mTypeCode == BfTypeCode_CharPtr)
  2167. {
  2168. auto interpolateExpr = mAlloc->Alloc<BfStringInterpolationExpression>();
  2169. interpolateExpr->mString = mLiteral.mString;
  2170. interpolateExpr->mTriviaStart = mTriviaStart;
  2171. interpolateExpr->mSrcStart = mTokenStart;
  2172. interpolateExpr->mSrcEnd = mSrcIdx;
  2173. BfSizedArrayInitIndirect(interpolateExpr->mExpressions, interpolateExpressions, mAlloc);
  2174. mGeneratedNode = interpolateExpr;
  2175. mSyntaxToken = BfSyntaxToken_GeneratedNode;
  2176. mToken = BfToken_None;
  2177. }
  2178. }
  2179. return;
  2180. }
  2181. break;
  2182. case '/':
  2183. if (mSrc[mSrcIdx] == '/')
  2184. {
  2185. // Comment line
  2186. while (true)
  2187. {
  2188. char c = mSrc[mSrcIdx++];
  2189. if ((c == '\n') || (c == '\0'))
  2190. {
  2191. mSrcIdx--;
  2192. break;
  2193. }
  2194. }
  2195. mTokenEnd = mSrcIdx;
  2196. if (mPreprocessorIgnoredSectionNode == NULL)
  2197. {
  2198. auto commentKind = GetCommentKind(mTokenStart);
  2199. bool handled = false;
  2200. if (!mPendingSideNodes.IsEmpty())
  2201. {
  2202. if (auto prevComment = BfNodeDynCast<BfCommentNode>(mPendingSideNodes.back()))
  2203. {
  2204. // This is required for folding '///' style multi-line documentation into a single node
  2205. if (prevComment->GetTriviaStart() == mTriviaStart)
  2206. {
  2207. auto prevCommentKind = GetCommentKind(prevComment->mSrcStart);
  2208. if ((!BfIsCommentBlock(commentKind)) && (commentKind == prevCommentKind))
  2209. {
  2210. prevComment->SetSrcEnd(mSrcIdx);
  2211. handled = true;
  2212. }
  2213. }
  2214. }
  2215. }
  2216. if ((!handled) && (!disablePreprocessor))
  2217. {
  2218. auto bfCommentNode = mAlloc->Alloc<BfCommentNode>();
  2219. bfCommentNode->Init(this);
  2220. bfCommentNode->mCommentKind = commentKind;
  2221. mSidechannelRootNode->Add(bfCommentNode);
  2222. mPendingSideNodes.push_back(bfCommentNode);
  2223. }
  2224. }
  2225. break;
  2226. }
  2227. else if (mSrc[mSrcIdx] == '=')
  2228. {
  2229. mToken = BfToken_DivideEquals;
  2230. mTokenEnd = ++mSrcIdx;
  2231. mSyntaxToken = BfSyntaxToken_Token;
  2232. return;
  2233. }
  2234. else if (mSrc[mSrcIdx] == '*')
  2235. {
  2236. // Comment block
  2237. int nestCount = 1;
  2238. mSrcIdx++;
  2239. while (true)
  2240. {
  2241. char c = mSrc[mSrcIdx++];
  2242. if (c == '\n')
  2243. {
  2244. NewLine();
  2245. }
  2246. else if ((c == '\0') || ((c == '*') && (mSrc[mSrcIdx] == '/')))
  2247. {
  2248. // Block ends
  2249. if (c == '\0')
  2250. {
  2251. nestCount = 0;
  2252. mSrcIdx--;
  2253. }
  2254. else
  2255. {
  2256. c = 0;
  2257. nestCount--;
  2258. mSrcIdx++;
  2259. }
  2260. if (nestCount == 0)
  2261. {
  2262. mTokenEnd = mSrcIdx;
  2263. if (mPreprocessorIgnoredSectionNode == NULL)
  2264. {
  2265. bool handled = false;
  2266. if (!mPendingSideNodes.IsEmpty())
  2267. {
  2268. if (auto prevComment = BfNodeDynCast<BfCommentNode>(mPendingSideNodes.back()))
  2269. {
  2270. // This is required for folding documentation into a single node
  2271. if (prevComment->GetTriviaStart() == mTriviaStart)
  2272. {
  2273. //TODO: Why did we allow merging BLOCKS of comments together? This messes up BfPrinter word wrapping on comments
  2274. // if (GetCommentKind(prevComment->mSrcStart) == GetCommentKind(mTokenStart))
  2275. // {
  2276. // prevComment->SetSrcEnd(mSrcIdx);
  2277. // handled = true;
  2278. // }
  2279. }
  2280. }
  2281. }
  2282. if (!handled)
  2283. {
  2284. auto bfCommentNode = mAlloc->Alloc<BfCommentNode>();
  2285. bfCommentNode->Init(this);
  2286. bfCommentNode->mCommentKind = GetCommentKind(mTokenStart);
  2287. mSidechannelRootNode->Add(bfCommentNode);
  2288. mPendingSideNodes.push_back(bfCommentNode);
  2289. }
  2290. }
  2291. break;
  2292. }
  2293. }
  2294. else if ((!mCompatMode) && ((c == '/') && (mSrc[mSrcIdx] == '*') && (mSrc[mSrcIdx - 2] != '/')))
  2295. {
  2296. nestCount++;
  2297. mSrcIdx++;
  2298. }
  2299. }
  2300. }
  2301. else
  2302. {
  2303. mToken = BfToken_ForwardSlash;
  2304. mSyntaxToken = BfSyntaxToken_Token;
  2305. return;
  2306. }
  2307. break;
  2308. case '#':
  2309. if (disablePreprocessor)
  2310. {
  2311. mTokenStart = mSrcIdx - 1;
  2312. UnexpectedCharacter();
  2313. continue;
  2314. }
  2315. else
  2316. HandlePreprocessor();
  2317. if (mSyntaxToken == BfSyntaxToken_EOF)
  2318. return;
  2319. break;
  2320. case '.':
  2321. if (mSrc[mSrcIdx] == '.')
  2322. {
  2323. if (mSrc[mSrcIdx + 1] == '.')
  2324. {
  2325. mSrcIdx += 2;
  2326. mTokenEnd = mSrcIdx;
  2327. mToken = BfToken_DotDotDot;
  2328. mSyntaxToken = BfSyntaxToken_Token;
  2329. }
  2330. else if (mSrc[mSrcIdx + 1] == '<')
  2331. {
  2332. mSrcIdx += 2;
  2333. mTokenEnd = mSrcIdx;
  2334. mToken = BfToken_DotDotLess;
  2335. mSyntaxToken = BfSyntaxToken_Token;
  2336. }
  2337. else
  2338. {
  2339. mSrcIdx++;
  2340. mTokenEnd = mSrcIdx;
  2341. mToken = BfToken_DotDot;
  2342. mSyntaxToken = BfSyntaxToken_Token;
  2343. }
  2344. }
  2345. else
  2346. {
  2347. mToken = BfToken_Dot;
  2348. mSyntaxToken = BfSyntaxToken_Token;
  2349. }
  2350. return;
  2351. case ',':
  2352. mToken = BfToken_Comma;
  2353. mSyntaxToken = BfSyntaxToken_Token;
  2354. return;
  2355. case ';':
  2356. if (mInAsmBlock)
  2357. {
  2358. mToken = BfToken_AsmNewline;
  2359. mSyntaxToken = BfSyntaxToken_Token;
  2360. }
  2361. else
  2362. {
  2363. mToken = BfToken_Semicolon;
  2364. mSyntaxToken = BfSyntaxToken_Token;
  2365. }
  2366. return;
  2367. case ':':
  2368. {
  2369. if ((mCompatMode) && (mSrc[mSrcIdx] == ':'))
  2370. {
  2371. mSrcIdx++;
  2372. mTokenEnd = mSrcIdx;
  2373. mToken = BfToken_Dot;
  2374. mSyntaxToken = BfSyntaxToken_Token;
  2375. }
  2376. else
  2377. {
  2378. mToken = BfToken_Colon;
  2379. mSyntaxToken = BfSyntaxToken_Token;
  2380. }
  2381. }
  2382. return;
  2383. case '(':
  2384. mToken = BfToken_LParen;
  2385. mSyntaxToken = BfSyntaxToken_Token;
  2386. return;
  2387. case ')':
  2388. mToken = BfToken_RParen;
  2389. mSyntaxToken = BfSyntaxToken_Token;
  2390. return;
  2391. case '{':
  2392. mToken = BfToken_LBrace;
  2393. mSyntaxToken = BfSyntaxToken_Token;
  2394. return;
  2395. case '}':
  2396. mToken = BfToken_RBrace;
  2397. mSyntaxToken = BfSyntaxToken_Token;
  2398. return;
  2399. case '[':
  2400. mToken = BfToken_LBracket;
  2401. mSyntaxToken = BfSyntaxToken_Token;
  2402. return;
  2403. case ']':
  2404. mToken = BfToken_RBracket;
  2405. mSyntaxToken = BfSyntaxToken_Token;
  2406. return;
  2407. case '\n':
  2408. NewLine();
  2409. if (!mInAsmBlock)
  2410. continue;
  2411. mToken = BfToken_AsmNewline;
  2412. mSyntaxToken = BfSyntaxToken_Token;
  2413. return;
  2414. case ' ':
  2415. case '\t':
  2416. case '\v':
  2417. case '\f':
  2418. case '\r':
  2419. continue; // Whitespace
  2420. case '\0':
  2421. mSrcIdx--; // Stay on EOF marker
  2422. mSyntaxToken = BfSyntaxToken_EOF;
  2423. return;
  2424. default:
  2425. if (((c >= '0') && (c <= '9')) || (c == '-'))
  2426. {
  2427. bool prevIsDot = prevToken == BfToken_Dot;
  2428. if (c == '-')
  2429. {
  2430. // Not a number!
  2431. if (mSrc[mSrcIdx] == '-')
  2432. {
  2433. mToken = BfToken_DblMinus;
  2434. mSrcIdx++;
  2435. }
  2436. else if (mSrc[mSrcIdx] == '=')
  2437. {
  2438. mToken = BfToken_MinusEquals;
  2439. mSrcIdx++;
  2440. }
  2441. else if (mSrc[mSrcIdx] == '>')
  2442. {
  2443. if (mCompatMode)
  2444. mToken = BfToken_Dot;
  2445. else
  2446. mToken = BfToken_Arrow;
  2447. mSrcIdx++;
  2448. }
  2449. else
  2450. mToken = BfToken_Minus;
  2451. mSyntaxToken = BfSyntaxToken_Token;
  2452. mTokenEnd = mSrcIdx;
  2453. return;
  2454. }
  2455. bool hadOverflow = false;
  2456. uint64 val = 0;
  2457. int numberBase = 10;
  2458. int expVal = 0;
  2459. int expSign = 0;
  2460. bool hasExp = false;
  2461. bool hadSeps = false;
  2462. bool hadLeadingHexSep = false;
  2463. int hexDigits = 0;
  2464. if (c == '-')
  2465. {
  2466. BF_FATAL("Parsing error");
  2467. }
  2468. val = c - '0';
  2469. if (c == '0')
  2470. {
  2471. switch (mSrc[mSrcIdx])
  2472. {
  2473. case 'b':
  2474. case 'B':
  2475. numberBase = 2;
  2476. mSrcIdx++;
  2477. break;
  2478. case 'o':
  2479. case 'O':
  2480. numberBase = 8;
  2481. mSrcIdx++;
  2482. break;
  2483. case 'x':
  2484. case 'X':
  2485. numberBase = 16;
  2486. mSrcIdx++;
  2487. break;
  2488. }
  2489. }
  2490. while (true)
  2491. {
  2492. char c = mSrc[mSrcIdx++];
  2493. if (c == '\'')
  2494. {
  2495. hadSeps = true;
  2496. if ((numberBase == 0x10) && (hexDigits == 0))
  2497. hadLeadingHexSep = true;
  2498. continue;
  2499. }
  2500. if ((numberBase == 10) && ((c == 'e') || (c == 'E')))
  2501. {
  2502. // Specifying exponent
  2503. while (true)
  2504. {
  2505. c = mSrc[mSrcIdx++];
  2506. if (c == '+')
  2507. {
  2508. if (expSign != 0)
  2509. TokenFail("Format error");
  2510. expSign = 1;
  2511. }
  2512. else if (c == '-')
  2513. {
  2514. if (expSign != 0)
  2515. TokenFail("Format error");
  2516. expSign = -1;
  2517. }
  2518. else if ((c >= '0') && (c <= '9'))
  2519. {
  2520. hasExp = true;
  2521. expVal *= 10;
  2522. expVal += c - '0';
  2523. }
  2524. else
  2525. {
  2526. if (expSign == -1)
  2527. expVal = -expVal;
  2528. mSrcIdx--;
  2529. break;
  2530. }
  2531. }
  2532. if (!hasExp)
  2533. {
  2534. TokenFail("Expected an exponent");
  2535. }
  2536. }
  2537. bool endNumber = false;
  2538. bool hasDot = c == '.';
  2539. if ((hasDot) && (mSrc[mSrcIdx] == '.'))
  2540. {
  2541. // Skip float parsing if we have a double-dot `1..` case
  2542. hasDot = false;
  2543. }
  2544. // The 'prevIsDot' helps tuple lookups like "tuple.0.0", interpreting those as two integers rather than a float
  2545. if (((hasDot) && (!prevIsDot)) || (hasExp))
  2546. {
  2547. // Switch to floating point mode
  2548. //double dVal = val;
  2549. //double dValScale = 0.1;
  2550. //if (hasExp)
  2551. //dVal *= pow(10, expVal);
  2552. while (true)
  2553. {
  2554. char c = mSrc[mSrcIdx++];
  2555. if (IsWhitespaceOrPunctuation(c))
  2556. {
  2557. mTokenEnd = mSrcIdx - 1;
  2558. mSrcIdx--;
  2559. mLiteral.mTypeCode = BfTypeCode_Double;
  2560. mLiteral.mDouble = ParseLiteralDouble();//dVal;
  2561. mSyntaxToken = BfSyntaxToken_Literal;
  2562. return;
  2563. }
  2564. if ((c == 'e') || (c == 'E'))
  2565. {
  2566. // Specifying exponent
  2567. if (hasExp)
  2568. TokenFail("Format error");
  2569. while (true)
  2570. {
  2571. c = mSrc[mSrcIdx++];
  2572. if (c == '+')
  2573. {
  2574. if (expSign != 0)
  2575. TokenFail("Format error");
  2576. expSign = 1;
  2577. }
  2578. else if (c == '-')
  2579. {
  2580. if (expSign != 0)
  2581. TokenFail("Format error");
  2582. expSign = -1;
  2583. }
  2584. else if ((c >= '0') && (c <= '9'))
  2585. {
  2586. hasExp = true;
  2587. expVal *= 10;
  2588. expVal += c - '0';
  2589. }
  2590. else
  2591. {
  2592. if (expSign == -1)
  2593. expVal = -expVal;
  2594. mSrcIdx--;
  2595. //dVal *= pow(10, expVal);
  2596. break;
  2597. }
  2598. }
  2599. if (!hasExp)
  2600. {
  2601. TokenFail("Expected an exponent");
  2602. }
  2603. continue;
  2604. }
  2605. if ((c == 'f') || (c == 'F'))
  2606. {
  2607. mTokenEnd = mSrcIdx;
  2608. mLiteral.mTypeCode = BfTypeCode_Float;
  2609. mLiteral.mSingle = (float)ParseLiteralDouble();//(float)dVal;
  2610. mSyntaxToken = BfSyntaxToken_Literal;
  2611. return;
  2612. }
  2613. else if ((c == 'd') || (c == 'D'))
  2614. {
  2615. mTokenEnd = mSrcIdx;
  2616. mLiteral.mTypeCode = BfTypeCode_Double;
  2617. mLiteral.mDouble = ParseLiteralDouble();//(double)dVal;
  2618. mSyntaxToken = BfSyntaxToken_Literal;
  2619. return;
  2620. }
  2621. else if ((c >= '0') && (c <= '9'))
  2622. {
  2623. //dVal += (c - '0') * dValScale;
  2624. //dValScale *= 0.1;
  2625. }
  2626. else if ((((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) &&
  2627. (mSrc[mSrcIdx - 2] == '.'))
  2628. {
  2629. // This is actually a integer followed by an Int32 call (like 123.ToString)
  2630. mSrcIdx -= 2;
  2631. mTokenEnd = mSrcIdx;
  2632. mLiteral.mUInt64 = val;
  2633. mLiteral.mTypeCode = BfTypeCode_IntUnknown;
  2634. mSyntaxToken = BfSyntaxToken_Literal;
  2635. return;
  2636. }
  2637. else
  2638. {
  2639. mSrcIdx--;
  2640. mTokenEnd = mSrcIdx;
  2641. mLiteral.mTypeCode = BfTypeCode_Double;
  2642. mLiteral.mDouble = ParseLiteralDouble();//(double)dVal;
  2643. mSyntaxToken = BfSyntaxToken_Literal;
  2644. TokenFail("Unexpected character while parsing number", 0);
  2645. return;
  2646. }
  2647. }
  2648. return;
  2649. }
  2650. else if (c == '.')
  2651. endNumber = true;
  2652. if (IsWhitespaceOrPunctuation(c))
  2653. endNumber = true;
  2654. if (endNumber)
  2655. {
  2656. mTokenEnd = mSrcIdx - 1;
  2657. mSrcIdx--;
  2658. if ((numberBase == 0x10) &&
  2659. ((hexDigits >= 16) || ((hadSeps) && (hexDigits > 8)) || ((hadLeadingHexSep) && (hexDigits == 8))))
  2660. {
  2661. if (hexDigits > 16)
  2662. mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2663. mLiteral.mUInt64 = val;
  2664. if (val >= 0x8000000000000000)
  2665. mLiteral.mTypeCode = BfTypeCode_UInt64;
  2666. else
  2667. mLiteral.mTypeCode = BfTypeCode_Int64;
  2668. }
  2669. else
  2670. {
  2671. mLiteral.mUInt64 = val;
  2672. mLiteral.mTypeCode = BfTypeCode_IntUnknown;
  2673. if ((numberBase == 0x10) && (hexDigits == 7))
  2674. mLiteral.mWarnType = BfWarning_BF4201_Only7Hex;
  2675. if ((numberBase == 0x10) && (hexDigits == 9))
  2676. mLiteral.mWarnType = BfWarning_BF4202_TooManyHexForInt;
  2677. if (hadOverflow)
  2678. {
  2679. mPassInstance->FailAt("Value doesn't fit into int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2680. mLiteral.mTypeCode = BfTypeCode_Int64;
  2681. }
  2682. //else if ((val < -0x80000000LL) || (val > 0xFFFFFFFFLL))
  2683. else if (val >= 0x8000000000000000)
  2684. {
  2685. mLiteral.mTypeCode = BfTypeCode_UInt64;
  2686. }
  2687. else if (val > 0xFFFFFFFFLL)
  2688. {
  2689. mLiteral.mTypeCode = BfTypeCode_Int64;
  2690. }
  2691. }
  2692. mSyntaxToken = BfSyntaxToken_Literal;
  2693. return;
  2694. }
  2695. uint64 prevVal = val;
  2696. if ((c >= '0') && (c <= '9') && (c < '0' + numberBase))
  2697. {
  2698. if (numberBase == 0x10)
  2699. hexDigits++;
  2700. val *= numberBase;
  2701. val += c - '0';
  2702. }
  2703. else if ((numberBase == 0x10) && (c >= 'A') && (c <= 'F'))
  2704. {
  2705. hexDigits++;
  2706. val *= numberBase;
  2707. val += c - 'A' + 0xA;
  2708. }
  2709. else if ((numberBase == 0x10) && (c >= 'a') && (c <= 'f'))
  2710. {
  2711. hexDigits++;
  2712. val *= numberBase;
  2713. val += c - 'a' + 0xa;
  2714. }
  2715. else if ((c == 'u') || (c == 'U'))
  2716. {
  2717. if ((mSrc[mSrcIdx] == 'l') || (mSrc[mSrcIdx] == 'L'))
  2718. {
  2719. if (mSrc[mSrcIdx] == 'l')
  2720. TokenFail("Uppercase 'L' required for int64");
  2721. mSrcIdx++;
  2722. mTokenEnd = mSrcIdx;
  2723. mLiteral.mTypeCode = BfTypeCode_UInt64;
  2724. mLiteral.mUInt64 = (uint64)val;
  2725. if (hexDigits > 16)
  2726. mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2727. else if (hadOverflow)
  2728. mPassInstance->FailAt("Value doesn't fit into uint64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2729. mSyntaxToken = BfSyntaxToken_Literal;
  2730. return;
  2731. }
  2732. mTokenEnd = mSrcIdx;
  2733. mLiteral.mTypeCode = BfTypeCode_UIntPtr;
  2734. mLiteral.mUInt32 = (uint32)val;
  2735. if ((hadOverflow) || ((uint64)val != (uint64)mLiteral.mUInt32))
  2736. mPassInstance->FailAt("Value doesn't fit into uint32", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2737. mSyntaxToken = BfSyntaxToken_Literal;
  2738. return;
  2739. }
  2740. else if ((c == 'l') || (c == 'L'))
  2741. {
  2742. if (c == 'l')
  2743. TokenFail("Uppercase 'L' required for int64");
  2744. if ((mSrc[mSrcIdx] == 'u') || (mSrc[mSrcIdx] == 'U'))
  2745. {
  2746. mSrcIdx++;
  2747. mTokenEnd = mSrcIdx;
  2748. mLiteral.mTypeCode = BfTypeCode_UInt64;
  2749. mLiteral.mUInt64 = (uint64)val;
  2750. if (hexDigits > 16)
  2751. mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2752. else if (hadOverflow)
  2753. mPassInstance->FailAt("Value doesn't fit into uint64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2754. mSyntaxToken = BfSyntaxToken_Literal;
  2755. return;
  2756. }
  2757. mTokenEnd = mSrcIdx;
  2758. mLiteral.mTypeCode = BfTypeCode_Int64;
  2759. mLiteral.mInt64 = (int64)val;
  2760. if (val == 0x8000000000000000)
  2761. mLiteral.mTypeCode = BfTypeCode_UInt64;
  2762. else if (val >= 0x8000000000000000)
  2763. hadOverflow = true;
  2764. if (numberBase == 0x10)
  2765. {
  2766. if (hexDigits > 16)
  2767. mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2768. }
  2769. else if (hadOverflow)
  2770. mPassInstance->FailAt("Value doesn't fit into int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2771. mSyntaxToken = BfSyntaxToken_Literal;
  2772. return;
  2773. }
  2774. else if ((c == 'f') || (c == 'F'))
  2775. {
  2776. mTokenEnd = mSrcIdx;
  2777. mLiteral.mTypeCode = BfTypeCode_Float;
  2778. mLiteral.mSingle = (float)ParseLiteralDouble();//(float)val;
  2779. mSyntaxToken = BfSyntaxToken_Literal;
  2780. return;
  2781. }
  2782. else if ((c == 'd') || (c == 'D'))
  2783. {
  2784. mTokenEnd = mSrcIdx;
  2785. mLiteral.mTypeCode = BfTypeCode_Double;
  2786. mLiteral.mDouble = ParseLiteralDouble();//(double)val;
  2787. mSyntaxToken = BfSyntaxToken_Literal;
  2788. return;
  2789. }
  2790. else
  2791. {
  2792. mTokenEnd = mSrcIdx - 1;
  2793. mSrcIdx--;
  2794. mLiteral.mUInt64 = val;
  2795. mLiteral.mTypeCode = BfTypeCode_IntUnknown;
  2796. mSyntaxToken = BfSyntaxToken_Literal;
  2797. TokenFail("Unexpected character while parsing number", 0);
  2798. return;
  2799. }
  2800. if ((uint64)prevVal > (uint64)val)
  2801. hadOverflow = true;
  2802. }
  2803. }
  2804. else
  2805. {
  2806. if ((mCompatMode) && (c == '\\'))
  2807. {
  2808. int checkIdx = mSrcIdx;
  2809. bool isAtLineEnd = true;
  2810. while (true)
  2811. {
  2812. char checkC = mSrc[checkIdx];
  2813. if ((checkC == '\r') || (checkC == '\n'))
  2814. break;
  2815. if ((checkC != ' ') && (checkC != '\t'))
  2816. {
  2817. isAtLineEnd = false;
  2818. break;
  2819. }
  2820. checkIdx++;
  2821. }
  2822. if (isAtLineEnd)
  2823. continue;
  2824. }
  2825. if (!isVerbatim)
  2826. {
  2827. switch (GetTokenHash())
  2828. {
  2829. case TOKEN_HASH('t', 'r', 'u', 'e'):
  2830. if (SrcPtrHasToken("true"))
  2831. {
  2832. mLiteral.mTypeCode = BfTypeCode_Boolean;
  2833. mLiteral.mInt64 = 1;
  2834. mSyntaxToken = BfSyntaxToken_Literal;
  2835. return;
  2836. }
  2837. break;
  2838. case TOKEN_HASH('f', 'a', 'l', 's'):
  2839. if (SrcPtrHasToken("false"))
  2840. {
  2841. mLiteral.mTypeCode = BfTypeCode_Boolean;
  2842. mLiteral.mInt64 = 0;
  2843. mSyntaxToken = BfSyntaxToken_Literal;
  2844. return;
  2845. }
  2846. break;
  2847. case TOKEN_HASH('a', 'b', 's', 't'):
  2848. if ((!mCompatMode) && (SrcPtrHasToken("abstract")))
  2849. mToken = BfToken_Abstract;
  2850. break;
  2851. case TOKEN_HASH('a', 'l', 'l', 'o'):
  2852. if (SrcPtrHasToken("alloctype"))
  2853. mToken = BfToken_AllocType;
  2854. break;
  2855. case TOKEN_HASH('a', 'l', 'i', 'g'):
  2856. if (SrcPtrHasToken("alignof"))
  2857. mToken = BfToken_AlignOf;
  2858. break;
  2859. case TOKEN_HASH('a', 'p', 'p', 'e'):
  2860. if ((!mCompatMode) && (SrcPtrHasToken("append")))
  2861. mToken = BfToken_Append;
  2862. break;
  2863. case TOKEN_HASH('a', 's', 0, 0):
  2864. if ((!mCompatMode) && (SrcPtrHasToken("as")))
  2865. mToken = BfToken_As;
  2866. break;
  2867. case TOKEN_HASH('a', 's', 'm', 0):
  2868. if (SrcPtrHasToken("asm"))
  2869. mToken = BfToken_Asm;
  2870. break;
  2871. case TOKEN_HASH('b', 'a', 's', 'e'):
  2872. if (SrcPtrHasToken("base"))
  2873. mToken = BfToken_Base;
  2874. break;
  2875. case TOKEN_HASH('b', 'o', 'x', 0):
  2876. if ((!mCompatMode) && (SrcPtrHasToken("box")))
  2877. mToken = BfToken_Box;
  2878. break;
  2879. case TOKEN_HASH('b', 'r', 'e', 'a'):
  2880. if (SrcPtrHasToken("break"))
  2881. mToken = BfToken_Break;
  2882. break;
  2883. case TOKEN_HASH('c', 'a', 's', 'e'):
  2884. if (SrcPtrHasToken("case"))
  2885. mToken = BfToken_Case;
  2886. break;
  2887. case TOKEN_HASH('c', 'a', 't', 'c'):
  2888. if (SrcPtrHasToken("catch"))
  2889. mToken = BfToken_Catch;
  2890. break;
  2891. case TOKEN_HASH('c', 'h', 'e', 'c'):
  2892. if ((!mCompatMode) && (SrcPtrHasToken("checked")))
  2893. mToken = BfToken_Checked;
  2894. break;
  2895. case TOKEN_HASH('c', 'l', 'a', 's'):
  2896. if (SrcPtrHasToken("class"))
  2897. mToken = BfToken_Class;
  2898. break;
  2899. case TOKEN_HASH('c', 'o', 'm', 'p'):
  2900. if ((!mCompatMode) && (SrcPtrHasToken("comptype")))
  2901. mToken = BfToken_Comptype;
  2902. break;
  2903. case TOKEN_HASH('c', 'o', 'n', 'c'):
  2904. if ((!mCompatMode) && (SrcPtrHasToken("concrete")))
  2905. mToken = BfToken_Concrete;
  2906. break;
  2907. case TOKEN_HASH('c', 'o', 'n', 's'):
  2908. if (SrcPtrHasToken("const"))
  2909. mToken = BfToken_Const;
  2910. break;
  2911. case TOKEN_HASH('c', 'o', 'n', 't'):
  2912. if (SrcPtrHasToken("continue"))
  2913. mToken = BfToken_Continue;
  2914. break;
  2915. case TOKEN_HASH('d', 'e', 'c', 'l'):
  2916. if (SrcPtrHasToken("decltype"))
  2917. mToken = BfToken_Decltype;
  2918. break;
  2919. case TOKEN_HASH('d', 'e', 'f', 'a'):
  2920. if (SrcPtrHasToken("default"))
  2921. mToken = BfToken_Default;
  2922. break;
  2923. case TOKEN_HASH('d', 'e', 'f', 'e'):
  2924. if ((!mCompatMode) && (SrcPtrHasToken("defer")))
  2925. mToken = BfToken_Defer;
  2926. break;
  2927. case TOKEN_HASH('d', 'e', 'l', 'e'):
  2928. if ((!mCompatMode) && (SrcPtrHasToken("delegate")))
  2929. mToken = BfToken_Delegate;
  2930. else if (SrcPtrHasToken("delete"))
  2931. mToken = BfToken_Delete;
  2932. break;
  2933. case TOKEN_HASH('d', 'o', 0, 0):
  2934. if (SrcPtrHasToken("do"))
  2935. mToken = BfToken_Do;
  2936. break;
  2937. break;
  2938. case TOKEN_HASH('e', 'l', 's', 'e'):
  2939. if (SrcPtrHasToken("else"))
  2940. mToken = BfToken_Else;
  2941. break;
  2942. case TOKEN_HASH('e', 'n', 'u', 'm'):
  2943. if (SrcPtrHasToken("enum"))
  2944. mToken = BfToken_Enum;
  2945. break;
  2946. case TOKEN_HASH('e', 'x', 'p', 'l'):
  2947. if ((!mCompatMode) && (SrcPtrHasToken("explicit")))
  2948. mToken = BfToken_Explicit;
  2949. break;
  2950. case TOKEN_HASH('e', 'x', 't', 'e'):
  2951. if (SrcPtrHasToken("extern"))
  2952. mToken = BfToken_Extern;
  2953. else if ((!mCompatMode) && (SrcPtrHasToken("extension")))
  2954. mToken = BfToken_Extension;
  2955. break;
  2956. case TOKEN_HASH('f', 'a', 'l', 'l'):
  2957. if ((!mCompatMode) && (SrcPtrHasToken("fallthrough")))
  2958. mToken = BfToken_Fallthrough;
  2959. break;
  2960. case TOKEN_HASH('f', 'i', 'n', 'a'):
  2961. if (SrcPtrHasToken("finally"))
  2962. mToken = BfToken_Finally;
  2963. break;
  2964. case TOKEN_HASH('f', 'i', 'x', 'e'):
  2965. if (SrcPtrHasToken("fixed"))
  2966. mToken = BfToken_Fixed;
  2967. break;
  2968. case TOKEN_HASH('f', 'o', 'r', 0):
  2969. if (SrcPtrHasToken("for"))
  2970. mToken = BfToken_For;
  2971. break;
  2972. case TOKEN_HASH('f', 'o', 'r', 'e'):
  2973. if ((!mCompatMode) && (SrcPtrHasToken("foreach")))
  2974. {
  2975. mToken = BfToken_For;
  2976. mPassInstance->WarnAt(0, "'foreach' should be renamed to 'for'", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
  2977. }
  2978. break;
  2979. case TOKEN_HASH('f', 'u', 'n', 'c'):
  2980. if ((!mCompatMode) && (SrcPtrHasToken("function")))
  2981. mToken = BfToken_Function;
  2982. break;
  2983. case TOKEN_HASH('g', 'o', 't', 'o'):
  2984. if (SrcPtrHasToken("goto"))
  2985. mToken = BfToken_Goto;
  2986. break;
  2987. case TOKEN_HASH('i', 'f', 0, 0):
  2988. if (SrcPtrHasToken("if"))
  2989. mToken = BfToken_If;
  2990. break;
  2991. case TOKEN_HASH('i', 'm', 'p', 'l'):
  2992. if ((!mCompatMode) && (SrcPtrHasToken("implicit")))
  2993. mToken = BfToken_Implicit;
  2994. break;
  2995. case TOKEN_HASH('i', 'n', 0, 0):
  2996. if ((!mCompatMode) && (SrcPtrHasToken("in")))
  2997. mToken = BfToken_In;
  2998. break;
  2999. case TOKEN_HASH('i', 'n', 'l', 'i'):
  3000. if ((!mCompatMode) && (SrcPtrHasToken("inline")))
  3001. mToken = BfToken_Inline;
  3002. break;
  3003. case TOKEN_HASH('i', 'n', 't', 'e'):
  3004. if ((!mCompatMode) && (SrcPtrHasToken("interface")))
  3005. mToken = BfToken_Interface;
  3006. else if ((!mCompatMode) && (SrcPtrHasToken("internal")))
  3007. mToken = BfToken_Internal;
  3008. break;
  3009. case TOKEN_HASH('i', 's', 0, 0):
  3010. if ((!mCompatMode) && (SrcPtrHasToken("is")))
  3011. mToken = BfToken_Is;
  3012. break;
  3013. case TOKEN_HASH('i', 's', 'c', 'o'):
  3014. if ((!mCompatMode) && (SrcPtrHasToken("isconst")))
  3015. mToken = BfToken_IsConst;
  3016. break;
  3017. case TOKEN_HASH('l', 'e', 't', 0):
  3018. if ((!mCompatMode) && (SrcPtrHasToken("let")))
  3019. mToken = BfToken_Let;
  3020. break;
  3021. case TOKEN_HASH('m', 'i', 'x', 'i'):
  3022. if ((!mCompatMode) && (SrcPtrHasToken("mixin")))
  3023. mToken = BfToken_Mixin;
  3024. break;
  3025. case TOKEN_HASH('m', 'u', 't', 0):
  3026. if ((!mCompatMode) && (SrcPtrHasToken("mut")))
  3027. mToken = BfToken_Mut;
  3028. break;
  3029. case TOKEN_HASH('n', 'a', 'm', 'e'):
  3030. if (SrcPtrHasToken("namespace"))
  3031. mToken = BfToken_Namespace;
  3032. else if (SrcPtrHasToken("nameof"))
  3033. mToken = BfToken_NameOf;
  3034. break;
  3035. case TOKEN_HASH('n', 'e', 'w', 0):
  3036. if (SrcPtrHasToken("new"))
  3037. mToken = BfToken_New;
  3038. break;
  3039. case TOKEN_HASH('n', 'u', 'l', 'l'):
  3040. if (SrcPtrHasToken("null"))
  3041. mToken = BfToken_Null;
  3042. else if (SrcPtrHasToken("nullable"))
  3043. mToken = BfToken_Nullable;
  3044. break;
  3045. case TOKEN_HASH('o', 'f', 'f', 's'):
  3046. if (SrcPtrHasToken("offsetof"))
  3047. mToken = BfToken_OffsetOf;
  3048. break;
  3049. case TOKEN_HASH('o', 'p', 'e', 'r'):
  3050. if (SrcPtrHasToken("operator"))
  3051. mToken = BfToken_Operator;
  3052. break;
  3053. case TOKEN_HASH('o', 'u', 't', 0):
  3054. if ((!mCompatMode) && (SrcPtrHasToken("out")))
  3055. mToken = BfToken_Out;
  3056. break;
  3057. case TOKEN_HASH('o', 'v', 'e', 'r'):
  3058. if (SrcPtrHasToken("override"))
  3059. mToken = BfToken_Override;
  3060. break;
  3061. case TOKEN_HASH('p', 'a', 'r', 'a'):
  3062. if ((!mCompatMode) && (SrcPtrHasToken("params")))
  3063. mToken = BfToken_Params;
  3064. break;
  3065. case TOKEN_HASH('p', 'r', 'i', 'v'):
  3066. if (SrcPtrHasToken("private"))
  3067. mToken = BfToken_Private;
  3068. break;
  3069. case TOKEN_HASH('p', 'r', 'o', 't'):
  3070. if (SrcPtrHasToken("protected"))
  3071. mToken = BfToken_Protected;
  3072. break;
  3073. case TOKEN_HASH('p', 'u', 'b', 'l'):
  3074. if (SrcPtrHasToken("public"))
  3075. mToken = BfToken_Public;
  3076. break;
  3077. case TOKEN_HASH('r', 'e', 'a', 'd'):
  3078. if ((!mCompatMode) && (SrcPtrHasToken("readonly")))
  3079. mToken = BfToken_ReadOnly;
  3080. break;
  3081. case TOKEN_HASH('r', 'e', 'f', 0):
  3082. if ((!mCompatMode) && (SrcPtrHasToken("ref")))
  3083. mToken = BfToken_Ref;
  3084. break;
  3085. case TOKEN_HASH('r', 'e', 'p', 'e'):
  3086. if ((!mCompatMode) && (SrcPtrHasToken("repeat")))
  3087. mToken = BfToken_Repeat;
  3088. break;
  3089. case TOKEN_HASH('r', 'e', 't', 't'):
  3090. if ((!mCompatMode) && (SrcPtrHasToken("rettype")))
  3091. mToken = BfToken_RetType;
  3092. break;
  3093. case TOKEN_HASH('r', 'e', 't', 'u'):
  3094. if (SrcPtrHasToken("return"))
  3095. mToken = BfToken_Return;
  3096. break;
  3097. case TOKEN_HASH('s', 'c', 'o', 'p'):
  3098. if ((!mCompatMode) && (SrcPtrHasToken("scope")))
  3099. mToken = BfToken_Scope;
  3100. break;
  3101. case TOKEN_HASH('s', 'e', 'a', 'l'):
  3102. if ((!mCompatMode) && (SrcPtrHasToken("sealed")))
  3103. mToken = BfToken_Sealed;
  3104. break;
  3105. case TOKEN_HASH('s', 'i', 'z', 'e'):
  3106. if (SrcPtrHasToken("sizeof"))
  3107. mToken = BfToken_SizeOf;
  3108. break;
  3109. case TOKEN_HASH('s', 't', 'a', 't'):
  3110. if (SrcPtrHasToken("static"))
  3111. mToken = BfToken_Static;
  3112. break;
  3113. case TOKEN_HASH('s', 't', 'r', 'i'):
  3114. if (SrcPtrHasToken("strideof"))
  3115. mToken = BfToken_StrideOf;
  3116. break;
  3117. case TOKEN_HASH('s', 't', 'r', 'u'):
  3118. if (SrcPtrHasToken("struct"))
  3119. mToken = BfToken_Struct;
  3120. break;
  3121. case TOKEN_HASH('s', 'w', 'i', 't'):
  3122. if (SrcPtrHasToken("switch"))
  3123. mToken = BfToken_Switch;
  3124. break;
  3125. case TOKEN_HASH('t', 'h', 'i', 's'):
  3126. if (SrcPtrHasToken("this"))
  3127. mToken = BfToken_This;
  3128. break;
  3129. case TOKEN_HASH('t', 'h', 'r', 'o'):
  3130. if (SrcPtrHasToken("throw"))
  3131. mToken = BfToken_Throw;
  3132. break;
  3133. case TOKEN_HASH('t', 'r', 'y', 0):
  3134. if (SrcPtrHasToken("try"))
  3135. mToken = BfToken_Try;
  3136. break;
  3137. case TOKEN_HASH('t', 'y', 'p', 'e'):
  3138. if (SrcPtrHasToken("typeof"))
  3139. mToken = BfToken_TypeOf;
  3140. else if (SrcPtrHasToken("typealias"))
  3141. mToken = BfToken_TypeAlias;
  3142. break;
  3143. case TOKEN_HASH('u', 'n', 'c', 'h'):
  3144. if (SrcPtrHasToken("unchecked"))
  3145. mToken = BfToken_Unchecked;
  3146. break;
  3147. case TOKEN_HASH('u', 'n', 's', 'i'):
  3148. if (mCompatMode)
  3149. {
  3150. if (SrcPtrHasToken("unsigned"))
  3151. mToken = BfToken_Unsigned;
  3152. }
  3153. break;
  3154. case TOKEN_HASH('u', 's', 'i', 'n'):
  3155. if (SrcPtrHasToken("using"))
  3156. mToken = BfToken_Using;
  3157. break;
  3158. case TOKEN_HASH('v', 'a', 'r', 0):
  3159. if ((!mCompatMode) && (SrcPtrHasToken("var")))
  3160. mToken = BfToken_Var;
  3161. break;
  3162. case TOKEN_HASH('v', 'i', 'r', 't'):
  3163. if (SrcPtrHasToken("virtual"))
  3164. mToken = BfToken_Virtual;
  3165. break;
  3166. case TOKEN_HASH('v', 'o', 'l', 'a'):
  3167. if (SrcPtrHasToken("volatile"))
  3168. mToken = BfToken_Volatile;
  3169. break;
  3170. case TOKEN_HASH('w', 'h', 'e', 'n'):
  3171. if (SrcPtrHasToken("when"))
  3172. mToken = BfToken_When;
  3173. break;
  3174. case TOKEN_HASH('w', 'h', 'e', 'r'):
  3175. if (SrcPtrHasToken("where"))
  3176. mToken = BfToken_Where;
  3177. break;
  3178. case TOKEN_HASH('w', 'h', 'i', 'l'):
  3179. if (SrcPtrHasToken("while"))
  3180. mToken = BfToken_While;
  3181. break;
  3182. case TOKEN_HASH('y', 'i', 'e', 'l'):
  3183. if ((!mCompatMode) && (SrcPtrHasToken("yield")))
  3184. mToken = BfToken_Yield;
  3185. break;
  3186. }
  3187. }
  3188. if (mToken != BfToken_None)
  3189. {
  3190. mSyntaxToken = BfSyntaxToken_Token;
  3191. return;
  3192. }
  3193. bool allowChar = false;
  3194. if (mCompatMode)
  3195. allowChar = (c == '$') || (c == '`');
  3196. if ((uint8)c >= 0xC0)
  3197. {
  3198. int cLen = 0;
  3199. mSrcIdx--;
  3200. uint32 c32 = u8_toucs(mSrc + mSrcIdx, mOrigSrcLength - mSrcIdx, &cLen);
  3201. mSrcIdx += cLen;
  3202. utf8proc_category_t cat = utf8proc_category(c32);
  3203. switch (cat)
  3204. {
  3205. case UTF8PROC_CATEGORY_LU:
  3206. case UTF8PROC_CATEGORY_LL:
  3207. case UTF8PROC_CATEGORY_LT:
  3208. case UTF8PROC_CATEGORY_LM:
  3209. case UTF8PROC_CATEGORY_LO:
  3210. case UTF8PROC_CATEGORY_NL:
  3211. case UTF8PROC_CATEGORY_SM:
  3212. case UTF8PROC_CATEGORY_SC:
  3213. case UTF8PROC_CATEGORY_SK:
  3214. case UTF8PROC_CATEGORY_SO:
  3215. allowChar = true;
  3216. default: break;
  3217. }
  3218. }
  3219. if ((allowChar) ||
  3220. ((c >= 'A') && (c <= 'Z')) ||
  3221. ((c >= 'a') && (c <= 'z')) ||
  3222. (c == '_'))
  3223. {
  3224. if (stringStart != -1)
  3225. {
  3226. mTokenStart = stringStart;
  3227. stringStart = -1;
  3228. }
  3229. while (true)
  3230. {
  3231. int curSrcIdx = mSrcIdx;
  3232. char c = mSrc[mSrcIdx++];
  3233. bool isValidChar =
  3234. (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || (c == '_') || ((c >= '0') && (c <= '9')));
  3235. if (mCompatMode)
  3236. isValidChar |= (c == '$') || (c == '`') || (c == '\'');
  3237. if ((uint8)c >= 0xC0)
  3238. {
  3239. int cLen = 0;
  3240. mSrcIdx--;
  3241. uint32 c32 = u8_toucs(mSrc + mSrcIdx, mOrigSrcLength - mSrcIdx, &cLen);
  3242. mSrcIdx += cLen;
  3243. utf8proc_category_t cat = utf8proc_category(c32);
  3244. switch (cat)
  3245. {
  3246. case UTF8PROC_CATEGORY_LU:
  3247. case UTF8PROC_CATEGORY_LL:
  3248. case UTF8PROC_CATEGORY_LT:
  3249. case UTF8PROC_CATEGORY_LM:
  3250. case UTF8PROC_CATEGORY_LO:
  3251. case UTF8PROC_CATEGORY_NL:
  3252. case UTF8PROC_CATEGORY_SM:
  3253. case UTF8PROC_CATEGORY_SC:
  3254. case UTF8PROC_CATEGORY_SK:
  3255. case UTF8PROC_CATEGORY_SO:
  3256. case UTF8PROC_CATEGORY_MN:
  3257. case UTF8PROC_CATEGORY_MC:
  3258. case UTF8PROC_CATEGORY_ND:
  3259. case UTF8PROC_CATEGORY_PC:
  3260. case UTF8PROC_CATEGORY_CF:
  3261. isValidChar = true;
  3262. default: break;
  3263. }
  3264. }
  3265. if (!isValidChar)
  3266. {
  3267. mTokenEnd = curSrcIdx;
  3268. mSrcIdx = curSrcIdx;
  3269. mSyntaxToken = BfSyntaxToken_Identifier;
  3270. return;
  3271. }
  3272. }
  3273. mSyntaxToken = BfSyntaxToken_Identifier;
  3274. return;
  3275. }
  3276. else
  3277. {
  3278. AddErrorNode(mTokenStart, mSrcIdx);
  3279. mTriviaStart = mSrcIdx;
  3280. UnexpectedCharacter();
  3281. continue;
  3282. }
  3283. }
  3284. return;
  3285. }
  3286. if ((setVerbatim) && (!isVerbatim))
  3287. {
  3288. isVerbatim = true;
  3289. stringStart = mTokenStart;
  3290. }
  3291. if (setInterpolate)
  3292. {
  3293. if (interpolateSetting == 0)
  3294. stringStart = mTokenStart;
  3295. interpolateSetting++;
  3296. }
  3297. }
  3298. }
  3299. static int gParseBlockIdx = 0;
  3300. static int gParseMemberIdx = 0;
  3301. void BfParser::ParseBlock(BfBlock* astNode, int depth, bool isInterpolate)
  3302. {
  3303. gParseBlockIdx++;
  3304. int startParseBlockIdx = gParseBlockIdx;
  3305. bool isAsmBlock = false;
  3306. bool isTernary = false;
  3307. bool forceAllowNext = false;
  3308. SizedArray<BfAstNode*, 32> childArr;
  3309. int parenDepth = 0;
  3310. while (true)
  3311. {
  3312. if ((mSyntaxToken == BfSyntaxToken_Token) && (mToken == BfToken_Asm))
  3313. {
  3314. if (isAsmBlock || mInAsmBlock)
  3315. mPassInstance->Fail("Already inside an 'asm' block", astNode);
  3316. else
  3317. isAsmBlock = true;
  3318. }
  3319. NextToken(-1, isInterpolate && (parenDepth == 0) && (!forceAllowNext));
  3320. forceAllowNext = false;
  3321. if (mPreprocessorIgnoredSectionNode != NULL)
  3322. {
  3323. if (mSyntaxToken != BfSyntaxToken_EOF)
  3324. continue;
  3325. mPreprocessorIgnoredSectionNode->SetSrcEnd(mSrcIdx);
  3326. }
  3327. if (mScanOnly)
  3328. {
  3329. if (mSyntaxToken == BfSyntaxToken_EOF)
  3330. break;
  3331. continue;
  3332. }
  3333. gParseMemberIdx++;
  3334. int memberIdx = gParseMemberIdx;
  3335. auto childNode = CreateNode();
  3336. if (childNode == NULL)
  3337. break;
  3338. if (mSyntaxToken == BfSyntaxToken_EOF)
  3339. {
  3340. if (astNode != 0)
  3341. Fail("Unexpected end of file");
  3342. break;
  3343. }
  3344. if (mToken == BfToken_LBrace)
  3345. {
  3346. BfBlock* newBlock;
  3347. BfInlineAsmStatement* asmBlock = nullptr;
  3348. BfBlock* genBlock = nullptr;
  3349. /*if (isAsmBlock)
  3350. {
  3351. asmBlock = mAlloc->Alloc<BfInlineAsmStatement>();
  3352. asmBlock->mOpenBrace = (BfTokenNode*)CreateNode();
  3353. newBlock = asmBlock;
  3354. mInAsmBlock = true;
  3355. isAsmBlock = false;
  3356. }
  3357. else*/
  3358. {
  3359. genBlock = mAlloc->Alloc<BfBlock>();
  3360. genBlock->mOpenBrace = (BfTokenNode*)CreateNode();
  3361. newBlock = genBlock;
  3362. }
  3363. newBlock->Init(this);
  3364. ParseBlock(newBlock, depth + 1);
  3365. if (mToken == BfToken_RBrace)
  3366. {
  3367. if (genBlock)
  3368. genBlock->mCloseBrace = (BfTokenNode*)CreateNode();
  3369. else if (asmBlock)
  3370. asmBlock->mCloseBrace = (BfTokenNode*)CreateNode();
  3371. newBlock->SetSrcEnd(mSrcIdx);
  3372. }
  3373. else
  3374. {
  3375. if (mSyntaxToken == BfSyntaxToken_EOF)
  3376. mPassInstance->FailAfterAt("Expected '}'", mSourceData, newBlock->GetSrcEnd() - 1);
  3377. }
  3378. mInAsmBlock = false;
  3379. astNode->Add(newBlock);
  3380. childArr.push_back(newBlock);
  3381. }
  3382. else if (mToken == BfToken_RBrace)
  3383. {
  3384. if (depth == 0)
  3385. Fail("Unexpected ending brace");
  3386. break;
  3387. }
  3388. else
  3389. {
  3390. if (mToken == BfToken_LParen)
  3391. parenDepth++;
  3392. else if (mToken == BfToken_RParen)
  3393. parenDepth--;
  3394. if ((isInterpolate) && (parenDepth == 0))
  3395. {
  3396. if (mToken == BfToken_Question)
  3397. {
  3398. isTernary = true;
  3399. forceAllowNext = true;
  3400. }
  3401. bool endNow = false;
  3402. if (mToken == BfToken_Colon)
  3403. {
  3404. endNow = true;
  3405. if (!childArr.IsEmpty())
  3406. {
  3407. if (auto prevToken = BfNodeDynCast<BfTokenNode>(childArr.back()))
  3408. {
  3409. if ((prevToken->mToken == BfToken_Scope) || (prevToken->mToken == BfToken_New) || (prevToken->mToken == BfToken_Bang) ||
  3410. (prevToken->mToken == BfToken_Colon))
  3411. endNow = false;
  3412. }
  3413. }
  3414. if ((endNow) && (isTernary))
  3415. {
  3416. forceAllowNext = true;
  3417. isTernary = false;
  3418. endNow = false;
  3419. }
  3420. }
  3421. if (mToken == BfToken_Comma)
  3422. endNow = true;
  3423. if (endNow)
  3424. {
  3425. mSrcIdx = mTokenStart;
  3426. break;
  3427. }
  3428. }
  3429. astNode->Add(childNode);
  3430. childArr.Add(childNode);
  3431. if ((mSyntaxToken == BfSyntaxToken_Token) && (mToken == BfToken_RBrace))
  3432. break;
  3433. }
  3434. }
  3435. astNode->Init(childArr, mAlloc);
  3436. }
  3437. const char* BfNodeToString(BfAstNode* node)
  3438. {
  3439. static char str[256] = { 0 };
  3440. strncpy(str, node->GetSourceData()->mSrc + node->GetSrcStart(), node->GetSrcLength());
  3441. return str;
  3442. }
  3443. BfAstNode* BfParser::CreateNode()
  3444. {
  3445. switch (mSyntaxToken)
  3446. {
  3447. case BfSyntaxToken_Token:
  3448. {
  3449. auto bfTokenNode = mAlloc->Alloc<BfTokenNode>();
  3450. bfTokenNode->Init(this);
  3451. bfTokenNode->SetToken(mToken);
  3452. return bfTokenNode;
  3453. }
  3454. case BfSyntaxToken_Identifier:
  3455. {
  3456. //auto bfIdentifierNode = new BfIdentifierNode();
  3457. auto bfIdentifierNode = mAlloc->Alloc<BfIdentifierNode>();
  3458. bfIdentifierNode->Init(this);
  3459. return bfIdentifierNode;
  3460. }
  3461. case BfSyntaxToken_Literal:
  3462. {
  3463. auto bfLiteralExpression = mAlloc->Alloc<BfLiteralExpression>();
  3464. bfLiteralExpression->Init(this);
  3465. bfLiteralExpression->mValue = mLiteral;
  3466. mLiteral.mTypeCode = BfTypeCode_None;
  3467. mLiteral.mWarnType = 0;
  3468. return bfLiteralExpression;
  3469. }
  3470. case BfSyntaxToken_GeneratedNode:
  3471. return mGeneratedNode;
  3472. default: break;
  3473. }
  3474. return NULL;
  3475. }
  3476. void BfParser::Parse(BfPassInstance* passInstance)
  3477. {
  3478. BP_ZONE_F("BfParser::Parse %s", mFileName.c_str());
  3479. mSyntaxToken = BfSyntaxToken_None;
  3480. mPassInstance = passInstance;
  3481. int startIdx = mSrcIdx;
  3482. if (mUsingCache)
  3483. {
  3484. mRootNode = mParserData->mRootNode;
  3485. mSidechannelRootNode = mParserData->mSidechannelRootNode;
  3486. mErrorRootNode = mParserData->mErrorRootNode;
  3487. return;
  3488. }
  3489. mRootNode = mAlloc->Alloc<BfRootNode>();
  3490. mRootNode->Init(this);
  3491. mParserData->mRootNode = mRootNode;
  3492. mSidechannelRootNode = mAlloc->Alloc<BfRootNode>();
  3493. mSidechannelRootNode->Init(this);
  3494. mParserData->mSidechannelRootNode = mSidechannelRootNode;
  3495. mErrorRootNode = mAlloc->Alloc<BfRootNode>();
  3496. mErrorRootNode->Init(this);
  3497. mParserData->mErrorRootNode = mErrorRootNode;
  3498. ParseBlock(mRootNode, 0);
  3499. if (mPreprocessorNodeStack.size() > 0)
  3500. {
  3501. mPassInstance->Warn(0, "No matching #endif found", mPreprocessorNodeStack.back().first);
  3502. }
  3503. if (mJumpTable != NULL)
  3504. {
  3505. for (int i = (startIdx / PARSER_JUMPTABLE_DIVIDE) + 1; i < mJumpTableSize; i++)
  3506. if (mJumpTable[i].mCharIdx == 0)
  3507. mJumpTable[i] = mJumpTable[i - 1];
  3508. }
  3509. if (mPassInstance->HasFailed())
  3510. mParsingFailed = true;
  3511. if ((mPassInstance->HasMessages()) || (mParsingFailed))
  3512. {
  3513. mParserData->mFailed = true; // Don't reuse cache if there were errors or warnings
  3514. }
  3515. mPassInstance = NULL;
  3516. }
  3517. int BfParser::GetCharIdAtIndex(int findIndex)
  3518. {
  3519. return mParserData->GetCharIdAtIndex(findIndex);
  3520. }
  3521. void BfParser::Close()
  3522. {
  3523. BfSource::Close();
  3524. BfLogSys(mSystem, "Parser %p closing. RefCount:%d Failed:%d\n", this, mParserData->mRefCount, mParserData->mFailed);
  3525. if ((mParserData->mRefCount == 0) && (!mParserData->mFailed))
  3526. {
  3527. BF_ASSERT(mParserData->mDidReduce);
  3528. AutoCrit autoCrit(gBfParserCache->mCritSect);
  3529. BfParserCache::DataEntry dataEntry;
  3530. dataEntry.mParserData = mParserData;
  3531. if (gBfParserCache->mEntries.Add(dataEntry))
  3532. {
  3533. BfLogSys(mSystem, "Parser %p added to cache\n", this);
  3534. mParserData->mRefCount++;
  3535. }
  3536. else
  3537. {
  3538. // It's possible two of the same entries were being parsed at the same time on different threads.
  3539. // Just let the loser be deleted in the dtor
  3540. BfLogSys(mSystem, "Duplicate parser %p not added to cache\n", this);
  3541. }
  3542. }
  3543. }
  3544. void BfParser::HadSrcRealloc()
  3545. {
  3546. int jumpTableSize = ((mSrcAllocSize + 1) + PARSER_JUMPTABLE_DIVIDE - 1) / PARSER_JUMPTABLE_DIVIDE;
  3547. if (jumpTableSize > mJumpTableSize)
  3548. {
  3549. auto jumpTable = new BfLineStartEntry[jumpTableSize];
  3550. memset(jumpTable, 0, jumpTableSize * sizeof(BfLineStartEntry));
  3551. memcpy(jumpTable, mJumpTable, mJumpTableSize * sizeof(BfLineStartEntry));
  3552. delete [] mJumpTable;
  3553. mJumpTable = jumpTable;
  3554. mJumpTableSize = jumpTableSize;
  3555. mParserData->mJumpTable = mJumpTable;
  3556. mParserData->mJumpTableSize = mJumpTableSize;
  3557. }
  3558. }
  3559. void BfParser::GenerateAutoCompleteFrom(int srcPosition)
  3560. {
  3561. BfSourcePositionFinder posFinder(this, srcPosition);
  3562. posFinder.Visit(mRootNode);
  3563. if (posFinder.mClosestElement != NULL)
  3564. {
  3565. }
  3566. }
  3567. void BfParser::ReportMemory(MemReporter* memReporter)
  3568. {
  3569. //memReporter->Add("SmallAstAlloc", (int)mAlloc->mPages.size() * BfAstAllocManager::PAGE_SIZE);
  3570. //memReporter->Add("LargeAstAlloc", mAlloc->mLargeAllocSizes);
  3571. // if (!mUsingCache)
  3572. // memReporter->AddBumpAlloc("AstAlloc", *mAlloc);
  3573. //
  3574. // memReporter->Add("JumpTable", mJumpTableSize * sizeof(BfLineStartEntry));
  3575. memReporter->Add(sizeof(BfParser));
  3576. if (mParserData->mRefCount <= 0)
  3577. mParserData->ReportMemory(memReporter);
  3578. // if (mSrcAllocSize > 0)
  3579. // memReporter->Add("Source", mSrcAllocSize);
  3580. }
  3581. class BfInnermostFinder : public BfElementVisitor
  3582. {
  3583. public:
  3584. int mCursorIdx;
  3585. BfAstNode* mFoundNode;
  3586. BfInnermostFinder(int cursorIdx)
  3587. {
  3588. mFoundNode = NULL;
  3589. mCursorIdx = cursorIdx;
  3590. }
  3591. virtual void Visit(BfAstNode* node) override
  3592. {
  3593. if ((node->Contains(mCursorIdx)) && (!node->IsA<BfBlock>()))
  3594. {
  3595. if ((mFoundNode == NULL) || ((node->GetSrcLength()) <= (mFoundNode->GetSrcLength())))
  3596. mFoundNode = node;
  3597. }
  3598. }
  3599. virtual void Visit(BfMemberReferenceExpression* memberRefExpr) override
  3600. {
  3601. BfElementVisitor::Visit(memberRefExpr);
  3602. if (mFoundNode == memberRefExpr->mMemberName)
  3603. {
  3604. mFoundNode = memberRefExpr;
  3605. }
  3606. }
  3607. virtual void Visit(BfAttributedIdentifierNode* identifierNode) override
  3608. {
  3609. BfElementVisitor::Visit(identifierNode);
  3610. if (mFoundNode == identifierNode->mIdentifier)
  3611. {
  3612. mFoundNode = identifierNode;
  3613. }
  3614. }
  3615. virtual void Visit(BfQualifiedNameNode* qualifiedNameNode) override
  3616. {
  3617. BfElementVisitor::Visit(qualifiedNameNode);
  3618. if (mFoundNode == qualifiedNameNode->mRight)
  3619. {
  3620. mFoundNode = qualifiedNameNode;
  3621. }
  3622. }
  3623. virtual void Visit(BfBinaryOperatorExpression* binaryOpExpr) override
  3624. {
  3625. BfElementVisitor::Visit(binaryOpExpr);
  3626. if (mFoundNode == binaryOpExpr->mOpToken)
  3627. {
  3628. mFoundNode = binaryOpExpr;
  3629. }
  3630. }
  3631. virtual void Visit(BfPreprocessorNode* preprocNode) override
  3632. {
  3633. if (preprocNode->mArgument != NULL)
  3634. {
  3635. for (auto arg : preprocNode->mArgument->mChildArr)
  3636. {
  3637. Visit((BfAstNode*)arg);
  3638. if (mFoundNode == arg)
  3639. {
  3640. mFoundNode = preprocNode;
  3641. }
  3642. }
  3643. }
  3644. }
  3645. };
  3646. static BfAstNode* FindDebugExpressionNode(BfAstNode* checkNode, int cursorIdx)
  3647. {
  3648. BfInnermostFinder innermostFinder(cursorIdx);
  3649. innermostFinder.VisitChild(checkNode);
  3650. BfAstNode* exprNode = innermostFinder.mFoundNode;
  3651. return exprNode;
  3652. }
  3653. //////////////////////////////////////////////////////////////////////////
  3654. BF_EXPORT void BF_CALLTYPE BfParser_SetSource(BfParser* bfParser, const char* data, int length, const char* fileName, int textVersion)
  3655. {
  3656. bfParser->mFileName = fileName;
  3657. bfParser->mTextVersion = textVersion;
  3658. bfParser->SetSource(data, length);
  3659. }
  3660. BF_EXPORT void BF_CALLTYPE BfParser_SetCharIdData(BfParser* bfParser, uint8* data, int length)
  3661. {
  3662. delete bfParser->mParserData->mCharIdData;
  3663. bfParser->mParserData->mCharIdData = new uint8[length];
  3664. memcpy(bfParser->mParserData->mCharIdData, data, length);
  3665. }
  3666. BF_EXPORT void BF_CALLTYPE BfParser_SetHashMD5(BfParser* bfParser, Val128* md5Hash)
  3667. {
  3668. if (md5Hash != NULL)
  3669. bfParser->mParserData->mMD5Hash = *md5Hash;
  3670. }
  3671. BF_EXPORT void BF_CALLTYPE BfParser_Delete(BfParser* bfParser)
  3672. {
  3673. if (bfParser->mNextRevision != NULL)
  3674. bfParser->mNextRevision->mPrevRevision = NULL;
  3675. auto itr = std::find(bfParser->mSystem->mParsers.begin(), bfParser->mSystem->mParsers.end(), bfParser);
  3676. bfParser->mSystem->mParsers.erase(itr);
  3677. delete bfParser;
  3678. }
  3679. BF_EXPORT void BF_CALLTYPE BfParser_SetNextRevision(BfParser* bfParser, BfParser* nextRevision)
  3680. {
  3681. BF_ASSERT(bfParser->mNextRevision == NULL);
  3682. BF_ASSERT(nextRevision->mPrevRevision == NULL);
  3683. bfParser->mNextRevision = nextRevision;
  3684. nextRevision->mPrevRevision = bfParser;
  3685. nextRevision->mDataId = bfParser->mDataId;
  3686. }
  3687. BF_EXPORT void BF_CALLTYPE BfParser_SetCursorIdx(BfParser* bfParser, int cursorIdx)
  3688. {
  3689. bfParser->SetCursorIdx(cursorIdx);
  3690. }
  3691. BF_EXPORT void BF_CALLTYPE BfParser_SetIsClassifying(BfParser* bfParser)
  3692. {
  3693. bfParser->mParserFlags = (BfParserFlag)(bfParser->mParserFlags | ParserFlag_Classifying);
  3694. }
  3695. BF_EXPORT void BF_CALLTYPE BfParser_SetEmbedKind(BfParser* bfParser, BfSourceEmbedKind embedKind)
  3696. {
  3697. bfParser->mEmbedKind = embedKind;
  3698. }
  3699. BF_EXPORT void BF_CALLTYPE BfParser_SetAutocomplete(BfParser* bfParser, int cursorIdx)
  3700. {
  3701. BF_ASSERT(bfParser->mParserData->mRefCount == -1);
  3702. bfParser->SetCursorIdx(cursorIdx);
  3703. bfParser->mParserFlags = (BfParserFlag)(bfParser->mParserFlags | ParserFlag_Autocomplete | ParserFlag_Classifying);
  3704. }
  3705. PerfManager* BfGetPerfManager(BfParser* bfParser)
  3706. {
  3707. if (bfParser == NULL)
  3708. return NULL;
  3709. if (bfParser->mCursorIdx != -1)
  3710. return gPerfManager;
  3711. return NULL;
  3712. }
  3713. BF_EXPORT bool BF_CALLTYPE BfParser_Parse(BfParser* bfParser, BfPassInstance* bfPassInstance, bool compatMode)
  3714. {
  3715. BP_ZONE("BfParser_Parse");
  3716. int startFailIdx = bfPassInstance->mFailedIdx;
  3717. bfParser->mCompatMode = compatMode;
  3718. bfParser->mQuickCompatMode = compatMode;
  3719. bfParser->Parse(bfPassInstance);
  3720. return startFailIdx == bfPassInstance->mFailedIdx;
  3721. }
  3722. BF_EXPORT bool BF_CALLTYPE BfParser_Reduce(BfParser* bfParser, BfPassInstance* bfPassInstance)
  3723. {
  3724. BP_ZONE("BfParser_Reduce");
  3725. if (bfParser->mUsingCache)
  3726. return true; // Already reduced
  3727. bfParser->FinishSideNodes();
  3728. int startFailIdx = bfPassInstance->mFailedIdx;
  3729. int startWarningCount = bfPassInstance->mWarningCount;
  3730. BfReducer bfReducer;
  3731. bfReducer.mSource = bfParser;
  3732. bfReducer.mCompatMode = bfParser->mCompatMode;
  3733. bfReducer.mPassInstance = bfPassInstance;
  3734. bfReducer.HandleRoot(bfParser->mRootNode);
  3735. if ((startFailIdx != bfPassInstance->mFailedIdx) ||
  3736. (startWarningCount != bfPassInstance->mWarningCount))
  3737. bfParser->mParserData->mFailed = true;
  3738. bfParser->mParserData->mDidReduce = true;
  3739. bfParser->Close();
  3740. return startFailIdx == bfPassInstance->mFailedIdx;
  3741. }
  3742. static Array<int> gCharMapping;
  3743. BF_EXPORT const char* BF_CALLTYPE BfParser_Format(BfParser* bfParser, int formatStart, int formatEnd, int** outCharMapping, int maxCol, int tabSize, bool wantsTabsAsSpaces,
  3744. bool indentCaseLabels)
  3745. {
  3746. BP_ZONE("BfParser_Reduce");
  3747. String& outString = *gTLStrReturn.Get();
  3748. outString.clear();
  3749. gCharMapping.Clear();
  3750. BfPrinter bfPrinter(bfParser->mRootNode, bfParser->mSidechannelRootNode, bfParser->mErrorRootNode);
  3751. bfPrinter.mMaxCol = maxCol;
  3752. bfPrinter.mTabSize = tabSize;
  3753. bfPrinter.mWantsTabsAsSpaces = wantsTabsAsSpaces;
  3754. bfPrinter.mIndentCaseLabels = indentCaseLabels;
  3755. bfPrinter.mFormatStart = formatStart;
  3756. bfPrinter.mFormatEnd = formatEnd;
  3757. bfPrinter.mCharMapping = &gCharMapping;
  3758. bfPrinter.Visit(bfParser->mRootNode);
  3759. outString = bfPrinter.mOutString;
  3760. *outCharMapping = &gCharMapping[0];
  3761. return outString.c_str();
  3762. }
  3763. BF_EXPORT const char* BF_CALLTYPE BfParser_DocPrep(BfParser* bfParser)
  3764. {
  3765. BP_ZONE("BfParser_Reduce");
  3766. String& outString = *gTLStrReturn.Get();
  3767. outString.clear();
  3768. gCharMapping.Clear();
  3769. BfPrinter bfPrinter(bfParser->mRootNode, bfParser->mSidechannelRootNode, bfParser->mErrorRootNode);
  3770. bfPrinter.mFormatStart = -1;
  3771. bfPrinter.mFormatEnd = -1;
  3772. bfPrinter.mCharMapping = &gCharMapping;
  3773. bfPrinter.mDocPrep = true;
  3774. bfPrinter.Visit(bfParser->mRootNode);
  3775. outString = bfPrinter.mOutString;
  3776. return outString.c_str();
  3777. }
  3778. BF_EXPORT const char* BF_CALLTYPE BfParser_GetDebugExpressionAt(BfParser* bfParser, int cursorIdx)
  3779. {
  3780. BP_ZONE("BfParser_Reduce");
  3781. String& outString = *gTLStrReturn.Get();
  3782. outString.clear();
  3783. BfAstNode* exprNode = FindDebugExpressionNode(bfParser->mRootNode, cursorIdx);
  3784. if (exprNode == NULL)
  3785. exprNode = FindDebugExpressionNode(bfParser->mSidechannelRootNode, cursorIdx);
  3786. if (exprNode == NULL)
  3787. return NULL;
  3788. if ((exprNode->IsA<BfMethodDeclaration>()) ||
  3789. (exprNode->IsA<BfBlock>()) ||
  3790. (exprNode->IsA<BfStatement>()) ||
  3791. (exprNode->IsA<BfTokenNode>())
  3792. )
  3793. {
  3794. return NULL;
  3795. }
  3796. BfPrinter bfPrinter(bfParser->mRootNode, NULL, NULL);
  3797. bfPrinter.mReformatting = true;
  3798. bfPrinter.mIgnoreTrivia = true;
  3799. bfPrinter.VisitChild(exprNode);
  3800. outString = bfPrinter.mOutString;
  3801. if (auto preprocessorNode = BfNodeDynCast<BfPreprocessorNode>(exprNode))
  3802. {
  3803. auto firstStr = preprocessorNode->mArgument->mChildArr[0]->ToString();
  3804. if (firstStr == "warning")
  3805. {
  3806. String warningNumStr = preprocessorNode->mArgument->mChildArr.back()->ToString();
  3807. int warningNum = atoi(warningNumStr.c_str());
  3808. String warningStr;
  3809. switch (warningNum)
  3810. {
  3811. case BfWarning_CS0108_MemberHidesInherited:
  3812. warningStr = "CS0108: Derived member hides inherited member";
  3813. break;
  3814. case BfWarning_CS0114_MethodHidesInherited:
  3815. warningStr = "CS0114: Derived method hides inherited member";
  3816. break;
  3817. case BfWarning_CS0162_UnreachableCode:
  3818. warningStr = "CS0162: Unreachable code";
  3819. break;
  3820. case BfWarning_CS0168_VariableDeclaredButNeverUsed:
  3821. warningStr = "CS0168: Variable declared but never used";
  3822. break;
  3823. case BfWarning_CS0472_ValueTypeNullCompare:
  3824. warningStr = "CS0472: ValueType compared to null";
  3825. break;
  3826. case BfWarning_CS1030_PragmaWarning:
  3827. warningStr = "CS1030: Pragma warning";
  3828. break;
  3829. }
  3830. if (!warningStr.empty())
  3831. outString = "`" + warningStr;
  3832. }
  3833. }
  3834. return outString.c_str();
  3835. }
  3836. BF_EXPORT BfResolvePassData* BF_CALLTYPE BfParser_CreateResolvePassData(BfParser* bfParser, BfResolveType resolveType, bool doFuzzyAutoComplete)
  3837. {
  3838. auto bfResolvePassData = new BfResolvePassData();
  3839. bfResolvePassData->mResolveType = resolveType;
  3840. if (bfParser != NULL)
  3841. bfResolvePassData->mParsers.Add(bfParser);
  3842. if ((bfParser != NULL) && ((bfParser->mParserFlags & ParserFlag_Autocomplete) != 0))
  3843. bfResolvePassData->mAutoComplete = new BfAutoComplete(resolveType, doFuzzyAutoComplete);
  3844. return bfResolvePassData;
  3845. }
  3846. BF_EXPORT bool BF_CALLTYPE BfParser_BuildDefs(BfParser* bfParser, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData, bool fullRefresh)
  3847. {
  3848. if (bfParser->mCursorIdx != -1)
  3849. resolvePassData->mHasCursorIdx = true;
  3850. BP_ZONE("BfParser_BuildDefs");
  3851. int startFailIdx = bfPassInstance->mFailedIdx;
  3852. BfDefBuilder defBuilder(bfParser->mSystem);
  3853. defBuilder.mResolvePassData = resolvePassData;
  3854. defBuilder.Process(bfPassInstance, bfParser, fullRefresh);
  3855. return startFailIdx == bfPassInstance->mFailedIdx;;
  3856. }
  3857. BF_EXPORT void BF_CALLTYPE BfParser_RemoveDefs(BfParser* bfParser)
  3858. {
  3859. }
  3860. BF_EXPORT void BF_CALLTYPE BfParser_ClassifySource(BfParser* bfParser, BfSourceClassifier::CharData* charData, bool preserveFlags)
  3861. {
  3862. if (!bfParser->mIsClosed)
  3863. bfParser->Close();
  3864. BfSourceClassifier bfSourceClassifier(bfParser, charData);
  3865. bfSourceClassifier.mPreserveFlags = preserveFlags;
  3866. bfSourceClassifier.Visit(bfParser->mRootNode);
  3867. bfSourceClassifier.mIsSideChannel = false; //? false or true?
  3868. bfSourceClassifier.Visit(bfParser->mErrorRootNode);
  3869. bfSourceClassifier.mIsSideChannel = true;
  3870. bfSourceClassifier.Visit(bfParser->mSidechannelRootNode);
  3871. }
  3872. BF_EXPORT void BF_CALLTYPE BfParser_CreateClassifier(BfParser* bfParser, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData, BfSourceClassifier::CharData* charData)
  3873. {
  3874. resolvePassData->mIsClassifying = true;
  3875. bfParser->mSourceClassifier = new BfSourceClassifier(bfParser, charData);
  3876. bfParser->mSourceClassifier->mClassifierPassId = bfPassInstance->mClassifierPassId;
  3877. if ((resolvePassData->mParsers.IsEmpty()) || (bfParser != resolvePassData->mParsers[0]))
  3878. resolvePassData->mParsers.Add(bfParser);
  3879. bool doClassifyPass = (charData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri);
  3880. bfParser->mSourceClassifier->mEnabled = doClassifyPass;
  3881. bfParser->mSourceClassifier->mSkipMethodInternals = true;
  3882. bfParser->mSourceClassifier->mSkipTypeDeclarations = true;
  3883. if (charData != NULL)
  3884. {
  3885. if ((doClassifyPass) && (bfParser->mRootNode != NULL))
  3886. bfParser->mSourceClassifier->Visit(bfParser->mRootNode);
  3887. }
  3888. bfParser->mSourceClassifier->mSkipTypeDeclarations = false;
  3889. bfParser->mSourceClassifier->mSkipMethodInternals = false;
  3890. }
  3891. BF_EXPORT void BF_CALLTYPE BfParser_FinishClassifier(BfParser* bfParser, BfResolvePassData* resolvePassData)
  3892. {
  3893. if (bfParser->mSourceClassifier == NULL)
  3894. return;
  3895. bool doClassifyPass = (bfParser->mSourceClassifier->mCharData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri);
  3896. if (doClassifyPass)
  3897. {
  3898. bfParser->mSourceClassifier->mIsSideChannel = false;
  3899. if (bfParser->mErrorRootNode != NULL)
  3900. bfParser->mSourceClassifier->Visit(bfParser->mErrorRootNode);
  3901. bfParser->mSourceClassifier->mIsSideChannel = true;
  3902. if (bfParser->mSidechannelRootNode != NULL)
  3903. bfParser->mSourceClassifier->Visit(bfParser->mSidechannelRootNode);
  3904. }
  3905. delete bfParser->mSourceClassifier;
  3906. bfParser->mSourceClassifier = NULL;
  3907. }
  3908. BF_EXPORT void BF_CALLTYPE BfParser_GenerateAutoCompletionFrom(BfParser* bfParser, int srcPosition)
  3909. {
  3910. BP_ZONE("BfParser_GenerateAutoCompletionFrom");
  3911. bfParser->GenerateAutoCompleteFrom(srcPosition);
  3912. }
  3913. BF_EXPORT void BF_CALLTYPE BfParser_SetCompleteParse(BfParser* bfParser)
  3914. {
  3915. bfParser->mCompleteParse = true;
  3916. }
  3917. BF_EXPORT void BF_CALLTYPE BfParser_GetLineCharAtIdx(BfParser* bfParser, int idx, int* line, int* lineChar)
  3918. {
  3919. int _line, _lineChar;
  3920. bfParser->GetLineCharAtIdx(idx, _line, _lineChar);
  3921. *line = _line;
  3922. *lineChar = _lineChar;
  3923. }
  3924. BF_EXPORT int BF_CALLTYPE BfParser_GetIndexAtLine(BfParser* bfParser, int line)
  3925. {
  3926. return bfParser->GetIndexAtLine(line);
  3927. }