| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360 |
- using Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
- {
- class Demangler
- {
- private const string Base36 = "0123456789abcdefghijklmnopqrstuvwxyz";
- private readonly List<BaseNode> _substitutionList = new();
- private List<BaseNode> _templateParamList = new();
- private readonly List<ForwardTemplateReference> _forwardTemplateReferenceList = new();
- public string Mangled { get; private set; }
- private int _position;
- private readonly int _length;
- private bool _canForwardTemplateReference;
- private bool _canParseTemplateArgs;
- public Demangler(string mangled)
- {
- Mangled = mangled;
- _position = 0;
- _length = mangled.Length;
- _canParseTemplateArgs = true;
- }
- private bool ConsumeIf(string toConsume)
- {
- ReadOnlySpan<char> mangledPart = Mangled.AsSpan(_position);
- if (mangledPart.StartsWith(toConsume.AsSpan()))
- {
- _position += toConsume.Length;
- return true;
- }
- return false;
- }
- private ReadOnlySpan<char> PeekString(int offset = 0, int length = 1)
- {
- if (_position + offset >= length)
- {
- return null;
- }
- return Mangled.AsSpan(_position + offset, length);
- }
- private char Peek(int offset = 0)
- {
- if (_position + offset >= _length)
- {
- return '\0';
- }
- return Mangled[_position + offset];
- }
- private char Consume()
- {
- if (_position < _length)
- {
- return Mangled[_position++];
- }
- return '\0';
- }
- private int Count()
- {
- return _length - _position;
- }
- private static int FromBase36(string encoded)
- {
- char[] reversedEncoded = encoded.ToLower().ToCharArray().Reverse().ToArray();
- int result = 0;
- for (int i = 0; i < reversedEncoded.Length; i++)
- {
- int value = Base36.IndexOf(reversedEncoded[i]);
- if (value == -1)
- {
- return -1;
- }
- result += value * (int)Math.Pow(36, i);
- }
- return result;
- }
- private int ParseSeqId()
- {
- ReadOnlySpan<char> part = Mangled.AsSpan(_position);
- int seqIdLen = 0;
- for (; seqIdLen < part.Length; seqIdLen++)
- {
- if (!char.IsLetterOrDigit(part[seqIdLen]))
- {
- break;
- }
- }
- _position += seqIdLen;
- return FromBase36(new string(part[..seqIdLen]));
- }
- // <substitution> ::= S <seq-id> _
- // ::= S_
- // ::= St # std::
- // ::= Sa # std::allocator
- // ::= Sb # std::basic_string
- // ::= Ss # std::basic_string<char, std::char_traits<char>, std::allocator<char> >
- // ::= Si # std::basic_istream<char, std::char_traits<char> >
- // ::= So # std::basic_ostream<char, std::char_traits<char> >
- // ::= Sd # std::basic_iostream<char, std::char_traits<char> >
- private BaseNode ParseSubstitution()
- {
- if (!ConsumeIf("S"))
- {
- return null;
- }
- char substitutionSecondChar = Peek();
- if (char.IsLower(substitutionSecondChar))
- {
- switch (substitutionSecondChar)
- {
- case 'a':
- _position++;
- return new SpecialSubstitution(SpecialSubstitution.SpecialType.Allocator);
- case 'b':
- _position++;
- return new SpecialSubstitution(SpecialSubstitution.SpecialType.BasicString);
- case 's':
- _position++;
- return new SpecialSubstitution(SpecialSubstitution.SpecialType.String);
- case 'i':
- _position++;
- return new SpecialSubstitution(SpecialSubstitution.SpecialType.IStream);
- case 'o':
- _position++;
- return new SpecialSubstitution(SpecialSubstitution.SpecialType.OStream);
- case 'd':
- _position++;
- return new SpecialSubstitution(SpecialSubstitution.SpecialType.IOStream);
- default:
- return null;
- }
- }
- // ::= S_
- if (ConsumeIf("_"))
- {
- if (_substitutionList.Count != 0)
- {
- return _substitutionList[0];
- }
- return null;
- }
- // ::= S <seq-id> _
- int seqId = ParseSeqId();
- if (seqId < 0)
- {
- return null;
- }
- seqId++;
- if (!ConsumeIf("_") || seqId >= _substitutionList.Count)
- {
- return null;
- }
- return _substitutionList[seqId];
- }
- // NOTE: thoses data aren't used in the output
- // <call-offset> ::= h <nv-offset> _
- // ::= v <v-offset> _
- // <nv-offset> ::= <offset number>
- // # non-virtual base override
- // <v-offset> ::= <offset number> _ <virtual offset number>
- // # virtual base override, with vcall offset
- private bool ParseCallOffset()
- {
- if (ConsumeIf("h"))
- {
- return ParseNumber(true).Length == 0 || !ConsumeIf("_");
- }
- else if (ConsumeIf("v"))
- {
- return ParseNumber(true).Length == 0 || !ConsumeIf("_") || ParseNumber(true).Length == 0 || !ConsumeIf("_");
- }
- return true;
- }
- // <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
- // ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
- // ::= Tu <name> # dependent elaborated type specifier using 'union'
- // ::= Te <name> # dependent elaborated type specifier using 'enum'
- private BaseNode ParseClassEnumType()
- {
- string elaboratedType = null;
- if (ConsumeIf("Ts"))
- {
- elaboratedType = "struct";
- }
- else if (ConsumeIf("Tu"))
- {
- elaboratedType = "union";
- }
- else if (ConsumeIf("Te"))
- {
- elaboratedType = "enum";
- }
- BaseNode name = ParseName();
- if (name == null)
- {
- return null;
- }
- if (elaboratedType == null)
- {
- return name;
- }
- return new ElaboratedType(elaboratedType, name);
- }
- // <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
- // <bare-function-type> ::= <signature type>+
- // # types are possible return type, then parameter types
- // <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
- // ::= DO <expression> E # computed (instantiation-dependent) noexcept
- // ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
- private BaseNode ParseFunctionType()
- {
- Cv cvQualifiers = ParseCvQualifiers();
- BaseNode exceptionSpec = null;
- if (ConsumeIf("Do"))
- {
- exceptionSpec = new NameType("noexcept");
- }
- else if (ConsumeIf("DO"))
- {
- BaseNode expression = ParseExpression();
- if (expression == null || !ConsumeIf("E"))
- {
- return null;
- }
- exceptionSpec = new NoexceptSpec(expression);
- }
- else if (ConsumeIf("Dw"))
- {
- List<BaseNode> types = new();
- while (!ConsumeIf("E"))
- {
- BaseNode type = ParseType();
- if (type == null)
- {
- return null;
- }
- types.Add(type);
- }
- exceptionSpec = new DynamicExceptionSpec(new NodeArray(types));
- }
- // We don't need the transaction
- ConsumeIf("Dx");
- if (!ConsumeIf("F"))
- {
- return null;
- }
- // extern "C"
- ConsumeIf("Y");
- BaseNode returnType = ParseType();
- if (returnType == null)
- {
- return null;
- }
- Reference referenceQualifier = Reference.None;
- List<BaseNode> paramsList = new();
- while (true)
- {
- if (ConsumeIf("E"))
- {
- break;
- }
- if (ConsumeIf("v"))
- {
- continue;
- }
- if (ConsumeIf("RE"))
- {
- referenceQualifier = Reference.LValue;
- break;
- }
- else if (ConsumeIf("OE"))
- {
- referenceQualifier = Reference.RValue;
- break;
- }
- BaseNode type = ParseType();
- if (type == null)
- {
- return null;
- }
- paramsList.Add(type);
- }
- return new FunctionType(returnType, new NodeArray(paramsList), new CvType(cvQualifiers, null), new SimpleReferenceType(referenceQualifier, null), exceptionSpec);
- }
- // <array-type> ::= A <positive dimension number> _ <element type>
- // ::= A [<dimension expression>] _ <element type>
- private BaseNode ParseArrayType()
- {
- if (!ConsumeIf("A"))
- {
- return null;
- }
- BaseNode elementType;
- if (char.IsDigit(Peek()))
- {
- string dimension = ParseNumber();
- if (dimension.Length == 0 || !ConsumeIf("_"))
- {
- return null;
- }
- elementType = ParseType();
- if (elementType == null)
- {
- return null;
- }
- return new ArrayType(elementType, dimension);
- }
- if (!ConsumeIf("_"))
- {
- BaseNode dimensionExpression = ParseExpression();
- if (dimensionExpression == null || !ConsumeIf("_"))
- {
- return null;
- }
- elementType = ParseType();
- if (elementType == null)
- {
- return null;
- }
- return new ArrayType(elementType, dimensionExpression);
- }
- elementType = ParseType();
- if (elementType == null)
- {
- return null;
- }
- return new ArrayType(elementType);
- }
- // <type> ::= <builtin-type>
- // ::= <qualified-type> (PARTIAL)
- // ::= <function-type>
- // ::= <class-enum-type>
- // ::= <array-type> (TODO)
- // ::= <pointer-to-member-type> (TODO)
- // ::= <template-param>
- // ::= <template-template-param> <template-args>
- // ::= <decltype>
- // ::= P <type> # pointer
- // ::= R <type> # l-value reference
- // ::= O <type> # r-value reference (C++11)
- // ::= C <type> # complex pair (C99)
- // ::= G <type> # imaginary (C99)
- // ::= <substitution> # See Compression below
- private BaseNode ParseType(NameParserContext context = null)
- {
- // Temporary context
- context ??= new NameParserContext();
- BaseNode result;
- switch (Peek())
- {
- case 'r':
- case 'V':
- case 'K':
- int typePos = 0;
- if (Peek(typePos) == 'r')
- {
- typePos++;
- }
- if (Peek(typePos) == 'V')
- {
- typePos++;
- }
- if (Peek(typePos) == 'K')
- {
- typePos++;
- }
- if (Peek(typePos) == 'F' || (Peek(typePos) == 'D' && (Peek(typePos + 1) == 'o' || Peek(typePos + 1) == 'O' || Peek(typePos + 1) == 'w' || Peek(typePos + 1) == 'x')))
- {
- result = ParseFunctionType();
- break;
- }
- Cv cv = ParseCvQualifiers();
- result = ParseType(context);
- if (result == null)
- {
- return null;
- }
- result = new CvType(cv, result);
- break;
- case 'U':
- // TODO: <extended-qualifier>
- return null;
- case 'v':
- _position++;
- return new NameType("void");
- case 'w':
- _position++;
- return new NameType("wchar_t");
- case 'b':
- _position++;
- return new NameType("bool");
- case 'c':
- _position++;
- return new NameType("char");
- case 'a':
- _position++;
- return new NameType("signed char");
- case 'h':
- _position++;
- return new NameType("unsigned char");
- case 's':
- _position++;
- return new NameType("short");
- case 't':
- _position++;
- return new NameType("unsigned short");
- case 'i':
- _position++;
- return new NameType("int");
- case 'j':
- _position++;
- return new NameType("unsigned int");
- case 'l':
- _position++;
- return new NameType("long");
- case 'm':
- _position++;
- return new NameType("unsigned long");
- case 'x':
- _position++;
- return new NameType("long long");
- case 'y':
- _position++;
- return new NameType("unsigned long long");
- case 'n':
- _position++;
- return new NameType("__int128");
- case 'o':
- _position++;
- return new NameType("unsigned __int128");
- case 'f':
- _position++;
- return new NameType("float");
- case 'd':
- _position++;
- return new NameType("double");
- case 'e':
- _position++;
- return new NameType("long double");
- case 'g':
- _position++;
- return new NameType("__float128");
- case 'z':
- _position++;
- return new NameType("...");
- case 'u':
- _position++;
- return ParseSourceName();
- case 'D':
- switch (Peek(1))
- {
- case 'd':
- _position += 2;
- return new NameType("decimal64");
- case 'e':
- _position += 2;
- return new NameType("decimal128");
- case 'f':
- _position += 2;
- return new NameType("decimal32");
- case 'h':
- _position += 2;
- // FIXME: GNU c++flit returns this but that is not what is supposed to be returned.
- return new NameType("half"); // return new NameType("decimal16");
- case 'i':
- _position += 2;
- return new NameType("char32_t");
- case 's':
- _position += 2;
- return new NameType("char16_t");
- case 'a':
- _position += 2;
- return new NameType("decltype(auto)");
- case 'n':
- _position += 2;
- // FIXME: GNU c++flit returns this but that is not what is supposed to be returned.
- return new NameType("decltype(nullptr)"); // return new NameType("std::nullptr_t");
- case 't':
- case 'T':
- _position += 2;
- result = ParseDecltype();
- break;
- case 'o':
- case 'O':
- case 'w':
- case 'x':
- result = ParseFunctionType();
- break;
- default:
- return null;
- }
- break;
- case 'F':
- result = ParseFunctionType();
- break;
- case 'A':
- return ParseArrayType();
- case 'M':
- // TODO: <pointer-to-member-type>
- _position++;
- return null;
- case 'T':
- // might just be a class enum type
- if (Peek(1) == 's' || Peek(1) == 'u' || Peek(1) == 'e')
- {
- result = ParseClassEnumType();
- break;
- }
- result = ParseTemplateParam();
- if (result == null)
- {
- return null;
- }
- if (_canParseTemplateArgs && Peek() == 'I')
- {
- BaseNode templateArguments = ParseTemplateArguments();
- if (templateArguments == null)
- {
- return null;
- }
- result = new NameTypeWithTemplateArguments(result, templateArguments);
- }
- break;
- case 'P':
- _position++;
- result = ParseType(context);
- if (result == null)
- {
- return null;
- }
- result = new PointerType(result);
- break;
- case 'R':
- _position++;
- result = ParseType(context);
- if (result == null)
- {
- return null;
- }
- result = new ReferenceType("&", result);
- break;
- case 'O':
- _position++;
- result = ParseType(context);
- if (result == null)
- {
- return null;
- }
- result = new ReferenceType("&&", result);
- break;
- case 'C':
- _position++;
- result = ParseType(context);
- if (result == null)
- {
- return null;
- }
- result = new PostfixQualifiedType(" complex", result);
- break;
- case 'G':
- _position++;
- result = ParseType(context);
- if (result == null)
- {
- return null;
- }
- result = new PostfixQualifiedType(" imaginary", result);
- break;
- case 'S':
- if (Peek(1) != 't')
- {
- BaseNode substitution = ParseSubstitution();
- if (substitution == null)
- {
- return null;
- }
- if (_canParseTemplateArgs && Peek() == 'I')
- {
- BaseNode templateArgument = ParseTemplateArgument();
- if (templateArgument == null)
- {
- return null;
- }
- result = new NameTypeWithTemplateArguments(substitution, templateArgument);
- break;
- }
- return substitution;
- }
- else
- {
- result = ParseClassEnumType();
- break;
- }
- default:
- result = ParseClassEnumType();
- break;
- }
- if (result != null)
- {
- _substitutionList.Add(result);
- }
- return result;
- }
- // <special-name> ::= TV <type> # virtual table
- // ::= TT <type> # VTT structure (construction vtable index)
- // ::= TI <type> # typeinfo structure
- // ::= TS <type> # typeinfo name (null-terminated byte string)
- // ::= Tc <call-offset> <call-offset> <base encoding>
- // ::= TW <object name> # Thread-local wrapper
- // ::= TH <object name> # Thread-local initialization
- // ::= T <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- // ::= GV <object name> # Guard variable for one-time initialization
- private BaseNode ParseSpecialName(NameParserContext context = null)
- {
- if (Peek() != 'T')
- {
- if (ConsumeIf("GV"))
- {
- BaseNode name = ParseName();
- if (name == null)
- {
- return null;
- }
- return new SpecialName("guard variable for ", name);
- }
- return null;
- }
- BaseNode node;
- switch (Peek(1))
- {
- // ::= TV <type> # virtual table
- case 'V':
- _position += 2;
- node = ParseType(context);
- if (node == null)
- {
- return null;
- }
- return new SpecialName("vtable for ", node);
- // ::= TT <type> # VTT structure (construction vtable index)
- case 'T':
- _position += 2;
- node = ParseType(context);
- if (node == null)
- {
- return null;
- }
- return new SpecialName("VTT for ", node);
- // ::= TI <type> # typeinfo structure
- case 'I':
- _position += 2;
- node = ParseType(context);
- if (node == null)
- {
- return null;
- }
- return new SpecialName("typeinfo for ", node);
- // ::= TS <type> # typeinfo name (null-terminated byte string)
- case 'S':
- _position += 2;
- node = ParseType(context);
- if (node == null)
- {
- return null;
- }
- return new SpecialName("typeinfo name for ", node);
- // ::= Tc <call-offset> <call-offset> <base encoding>
- case 'c':
- _position += 2;
- if (ParseCallOffset() || ParseCallOffset())
- {
- return null;
- }
- node = ParseEncoding();
- if (node == null)
- {
- return null;
- }
- return new SpecialName("covariant return thunk to ", node);
- // extension ::= TC <first type> <number> _ <second type>
- case 'C':
- _position += 2;
- BaseNode firstType = ParseType();
- if (firstType == null || ParseNumber(true).Length == 0 || !ConsumeIf("_"))
- {
- return null;
- }
- BaseNode secondType = ParseType();
- return new CtorVtableSpecialName(secondType, firstType);
- // ::= TH <object name> # Thread-local initialization
- case 'H':
- _position += 2;
- node = ParseName();
- if (node == null)
- {
- return null;
- }
- return new SpecialName("thread-local initialization routine for ", node);
- // ::= TW <object name> # Thread-local wrapper
- case 'W':
- _position += 2;
- node = ParseName();
- if (node == null)
- {
- return null;
- }
- return new SpecialName("thread-local wrapper routine for ", node);
- default:
- _position++;
- bool isVirtual = Peek() == 'v';
- if (ParseCallOffset())
- {
- return null;
- }
- node = ParseEncoding();
- if (node == null)
- {
- return null;
- }
- if (isVirtual)
- {
- return new SpecialName("virtual thunk to ", node);
- }
- return new SpecialName("non-virtual thunk to ", node);
- }
- }
- // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
- private Cv ParseCvQualifiers()
- {
- Cv qualifiers = Cv.None;
- if (ConsumeIf("r"))
- {
- qualifiers |= Cv.Restricted;
- }
- if (ConsumeIf("V"))
- {
- qualifiers |= Cv.Volatile;
- }
- if (ConsumeIf("K"))
- {
- qualifiers |= Cv.Const;
- }
- return qualifiers;
- }
- // <ref-qualifier> ::= R # & ref-qualifier
- // <ref-qualifier> ::= O # && ref-qualifier
- private SimpleReferenceType ParseRefQualifiers()
- {
- Reference result = Reference.None;
- if (ConsumeIf("O"))
- {
- result = Reference.RValue;
- }
- else if (ConsumeIf("R"))
- {
- result = Reference.LValue;
- }
- return new SimpleReferenceType(result, null);
- }
- private static BaseNode CreateNameNode(BaseNode prev, BaseNode name, NameParserContext context)
- {
- BaseNode result = name;
- if (prev != null)
- {
- result = new NestedName(name, prev);
- }
- if (context != null)
- {
- context.FinishWithTemplateArguments = false;
- }
- return result;
- }
- private int ParsePositiveNumber()
- {
- ReadOnlySpan<char> part = Mangled.AsSpan(_position);
- int numberLength = 0;
- for (; numberLength < part.Length; numberLength++)
- {
- if (!char.IsDigit(part[numberLength]))
- {
- break;
- }
- }
- _position += numberLength;
- if (numberLength == 0)
- {
- return -1;
- }
- return int.Parse(part[..numberLength]);
- }
- private string ParseNumber(bool isSigned = false)
- {
- if (isSigned)
- {
- ConsumeIf("n");
- }
- if (Count() == 0 || !char.IsDigit(Mangled[_position]))
- {
- return null;
- }
- ReadOnlySpan<char> part = Mangled.AsSpan(_position);
- int numberLength = 0;
- for (; numberLength < part.Length; numberLength++)
- {
- if (!char.IsDigit(part[numberLength]))
- {
- break;
- }
- }
- _position += numberLength;
- return new string(part[..numberLength]);
- }
- // <source-name> ::= <positive length number> <identifier>
- private BaseNode ParseSourceName()
- {
- int length = ParsePositiveNumber();
- if (Count() < length || length <= 0)
- {
- return null;
- }
- string name = Mangled.Substring(_position, length);
- _position += length;
- if (name.StartsWith("_GLOBAL__N"))
- {
- return new NameType("(anonymous namespace)");
- }
- return new NameType(name);
- }
- // <operator-name> ::= nw # new
- // ::= na # new[]
- // ::= dl # delete
- // ::= da # delete[]
- // ::= ps # + (unary)
- // ::= ng # - (unary)
- // ::= ad # & (unary)
- // ::= de # * (unary)
- // ::= co # ~
- // ::= pl # +
- // ::= mi # -
- // ::= ml # *
- // ::= dv # /
- // ::= rm # %
- // ::= an # &
- // ::= or # |
- // ::= eo # ^
- // ::= aS # =
- // ::= pL # +=
- // ::= mI # -=
- // ::= mL # *=
- // ::= dV # /=
- // ::= rM # %=
- // ::= aN # &=
- // ::= oR # |=
- // ::= eO # ^=
- // ::= ls # <<
- // ::= rs # >>
- // ::= lS # <<=
- // ::= rS # >>=
- // ::= eq # ==
- // ::= ne # !=
- // ::= lt # <
- // ::= gt # >
- // ::= le # <=
- // ::= ge # >=
- // ::= ss # <=>
- // ::= nt # !
- // ::= aa # &&
- // ::= oo # ||
- // ::= pp # ++ (postfix in <expression> context)
- // ::= mm # -- (postfix in <expression> context)
- // ::= cm # ,
- // ::= pm # ->*
- // ::= pt # ->
- // ::= cl # ()
- // ::= ix # []
- // ::= qu # ?
- // ::= cv <type> # (cast) (TODO)
- // ::= li <source-name> # operator ""
- // ::= v <digit> <source-name> # vendor extended operator (TODO)
- private BaseNode ParseOperatorName(NameParserContext context)
- {
- switch (Peek())
- {
- case 'a':
- switch (Peek(1))
- {
- case 'a':
- _position += 2;
- return new NameType("operator&&");
- case 'd':
- case 'n':
- _position += 2;
- return new NameType("operator&");
- case 'N':
- _position += 2;
- return new NameType("operator&=");
- case 'S':
- _position += 2;
- return new NameType("operator=");
- default:
- return null;
- }
- case 'c':
- switch (Peek(1))
- {
- case 'l':
- _position += 2;
- return new NameType("operator()");
- case 'm':
- _position += 2;
- return new NameType("operator,");
- case 'o':
- _position += 2;
- return new NameType("operator~");
- case 'v':
- _position += 2;
- bool canParseTemplateArgsBackup = _canParseTemplateArgs;
- bool canForwardTemplateReferenceBackup = _canForwardTemplateReference;
- _canParseTemplateArgs = false;
- _canForwardTemplateReference = canForwardTemplateReferenceBackup || context != null;
- BaseNode type = ParseType();
- _canParseTemplateArgs = canParseTemplateArgsBackup;
- _canForwardTemplateReference = canForwardTemplateReferenceBackup;
- if (type == null)
- {
- return null;
- }
- if (context != null)
- {
- context.CtorDtorConversion = true;
- }
- return new ConversionOperatorType(type);
- default:
- return null;
- }
- case 'd':
- switch (Peek(1))
- {
- case 'a':
- _position += 2;
- return new NameType("operator delete[]");
- case 'e':
- _position += 2;
- return new NameType("operator*");
- case 'l':
- _position += 2;
- return new NameType("operator delete");
- case 'v':
- _position += 2;
- return new NameType("operator/");
- case 'V':
- _position += 2;
- return new NameType("operator/=");
- default:
- return null;
- }
- case 'e':
- switch (Peek(1))
- {
- case 'o':
- _position += 2;
- return new NameType("operator^");
- case 'O':
- _position += 2;
- return new NameType("operator^=");
- case 'q':
- _position += 2;
- return new NameType("operator==");
- default:
- return null;
- }
- case 'g':
- switch (Peek(1))
- {
- case 'e':
- _position += 2;
- return new NameType("operator>=");
- case 't':
- _position += 2;
- return new NameType("operator>");
- default:
- return null;
- }
- case 'i':
- if (Peek(1) == 'x')
- {
- _position += 2;
- return new NameType("operator[]");
- }
- return null;
- case 'l':
- switch (Peek(1))
- {
- case 'e':
- _position += 2;
- return new NameType("operator<=");
- case 'i':
- _position += 2;
- BaseNode sourceName = ParseSourceName();
- if (sourceName == null)
- {
- return null;
- }
- return new LiteralOperator(sourceName);
- case 's':
- _position += 2;
- return new NameType("operator<<");
- case 'S':
- _position += 2;
- return new NameType("operator<<=");
- case 't':
- _position += 2;
- return new NameType("operator<");
- default:
- return null;
- }
- case 'm':
- switch (Peek(1))
- {
- case 'i':
- _position += 2;
- return new NameType("operator-");
- case 'I':
- _position += 2;
- return new NameType("operator-=");
- case 'l':
- _position += 2;
- return new NameType("operator*");
- case 'L':
- _position += 2;
- return new NameType("operator*=");
- case 'm':
- _position += 2;
- return new NameType("operator--");
- default:
- return null;
- }
- case 'n':
- switch (Peek(1))
- {
- case 'a':
- _position += 2;
- return new NameType("operator new[]");
- case 'e':
- _position += 2;
- return new NameType("operator!=");
- case 'g':
- _position += 2;
- return new NameType("operator-");
- case 't':
- _position += 2;
- return new NameType("operator!");
- case 'w':
- _position += 2;
- return new NameType("operator new");
- default:
- return null;
- }
- case 'o':
- switch (Peek(1))
- {
- case 'o':
- _position += 2;
- return new NameType("operator||");
- case 'r':
- _position += 2;
- return new NameType("operator|");
- case 'R':
- _position += 2;
- return new NameType("operator|=");
- default:
- return null;
- }
- case 'p':
- switch (Peek(1))
- {
- case 'm':
- _position += 2;
- return new NameType("operator->*");
- case 's':
- case 'l':
- _position += 2;
- return new NameType("operator+");
- case 'L':
- _position += 2;
- return new NameType("operator+=");
- case 'p':
- _position += 2;
- return new NameType("operator++");
- case 't':
- _position += 2;
- return new NameType("operator->");
- default:
- return null;
- }
- case 'q':
- if (Peek(1) == 'u')
- {
- _position += 2;
- return new NameType("operator?");
- }
- return null;
- case 'r':
- switch (Peek(1))
- {
- case 'm':
- _position += 2;
- return new NameType("operator%");
- case 'M':
- _position += 2;
- return new NameType("operator%=");
- case 's':
- _position += 2;
- return new NameType("operator>>");
- case 'S':
- _position += 2;
- return new NameType("operator>>=");
- default:
- return null;
- }
- case 's':
- if (Peek(1) == 's')
- {
- _position += 2;
- return new NameType("operator<=>");
- }
- return null;
- case 'v':
- // TODO: ::= v <digit> <source-name> # vendor extended operator
- return null;
- default:
- return null;
- }
- }
- // <unqualified-name> ::= <operator-name> [<abi-tags> (TODO)]
- // ::= <ctor-dtor-name> (TODO)
- // ::= <source-name>
- // ::= <unnamed-type-name> (TODO)
- // ::= DC <source-name>+ E # structured binding declaration (TODO)
- private BaseNode ParseUnqualifiedName(NameParserContext context)
- {
- BaseNode result = null;
- char c = Peek();
- if (c == 'U')
- {
- // TODO: Unnamed Type Name
- // throw new Exception("Unnamed Type Name not implemented");
- }
- else if (char.IsDigit(c))
- {
- result = ParseSourceName();
- }
- else if (ConsumeIf("DC"))
- {
- // TODO: Structured Binding Declaration
- // throw new Exception("Structured Binding Declaration not implemented");
- }
- else
- {
- result = ParseOperatorName(context);
- }
- if (result != null)
- {
- // TODO: ABI Tags
- // throw new Exception("ABI Tags not implemented");
- }
- return result;
- }
- // <ctor-dtor-name> ::= C1 # complete object constructor
- // ::= C2 # base object constructor
- // ::= C3 # complete object allocating constructor
- // ::= D0 # deleting destructor
- // ::= D1 # complete object destructor
- // ::= D2 # base object destructor
- private BaseNode ParseCtorDtorName(NameParserContext context, BaseNode prev)
- {
- if (prev.Type == NodeType.SpecialSubstitution && prev is SpecialSubstitution substitution)
- {
- substitution.SetExtended();
- }
- if (ConsumeIf("C"))
- {
- bool isInherited = ConsumeIf("I");
- char ctorDtorType = Peek();
- if (ctorDtorType != '1' && ctorDtorType != '2' && ctorDtorType != '3')
- {
- return null;
- }
- _position++;
- if (context != null)
- {
- context.CtorDtorConversion = true;
- }
- if (isInherited && ParseName(context) == null)
- {
- return null;
- }
- return new CtorDtorNameType(prev, false);
- }
- if (ConsumeIf("D"))
- {
- char c = Peek();
- if (c != '0' && c != '1' && c != '2')
- {
- return null;
- }
- _position++;
- if (context != null)
- {
- context.CtorDtorConversion = true;
- }
- return new CtorDtorNameType(prev, true);
- }
- return null;
- }
- // <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
- // ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
- // ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter
- // ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
- private BaseNode ParseFunctionParameter()
- {
- if (ConsumeIf("fp"))
- {
- // ignored
- ParseCvQualifiers();
- if (!ConsumeIf("_"))
- {
- return null;
- }
- return new FunctionParameter(ParseNumber());
- }
- else if (ConsumeIf("fL"))
- {
- string l1Number = ParseNumber();
- if (l1Number == null || l1Number.Length == 0)
- {
- return null;
- }
- if (!ConsumeIf("p"))
- {
- return null;
- }
- // ignored
- ParseCvQualifiers();
- if (!ConsumeIf("_"))
- {
- return null;
- }
- return new FunctionParameter(ParseNumber());
- }
- return null;
- }
- // <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
- // ::= fR <binary-operator-name> <expression> <expression>
- // ::= fl <binary-operator-name> <expression>
- // ::= fr <binary-operator-name> <expression>
- private BaseNode ParseFoldExpression()
- {
- if (!ConsumeIf("f"))
- {
- return null;
- }
- char foldKind = Peek();
- bool hasInitializer = foldKind == 'L' || foldKind == 'R';
- bool isLeftFold = foldKind == 'l' || foldKind == 'L';
- if (!isLeftFold && !(foldKind == 'r' || foldKind == 'R'))
- {
- return null;
- }
- _position++;
- string operatorName;
- switch (PeekString(0, 2))
- {
- case "aa":
- operatorName = "&&";
- break;
- case "an":
- operatorName = "&";
- break;
- case "aN":
- operatorName = "&=";
- break;
- case "aS":
- operatorName = "=";
- break;
- case "cm":
- operatorName = ",";
- break;
- case "ds":
- operatorName = ".*";
- break;
- case "dv":
- operatorName = "/";
- break;
- case "dV":
- operatorName = "/=";
- break;
- case "eo":
- operatorName = "^";
- break;
- case "eO":
- operatorName = "^=";
- break;
- case "eq":
- operatorName = "==";
- break;
- case "ge":
- operatorName = ">=";
- break;
- case "gt":
- operatorName = ">";
- break;
- case "le":
- operatorName = "<=";
- break;
- case "ls":
- operatorName = "<<";
- break;
- case "lS":
- operatorName = "<<=";
- break;
- case "lt":
- operatorName = "<";
- break;
- case "mi":
- operatorName = "-";
- break;
- case "mI":
- operatorName = "-=";
- break;
- case "ml":
- operatorName = "*";
- break;
- case "mL":
- operatorName = "*=";
- break;
- case "ne":
- operatorName = "!=";
- break;
- case "oo":
- operatorName = "||";
- break;
- case "or":
- operatorName = "|";
- break;
- case "oR":
- operatorName = "|=";
- break;
- case "pl":
- operatorName = "+";
- break;
- case "pL":
- operatorName = "+=";
- break;
- case "rm":
- operatorName = "%";
- break;
- case "rM":
- operatorName = "%=";
- break;
- case "rs":
- operatorName = ">>";
- break;
- case "rS":
- operatorName = ">>=";
- break;
- default:
- return null;
- }
- _position += 2;
- BaseNode expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- BaseNode initializer = null;
- if (hasInitializer)
- {
- initializer = ParseExpression();
- if (initializer == null)
- {
- return null;
- }
- }
- if (isLeftFold && initializer != null)
- {
- (initializer, expression) = (expression, initializer);
- }
- return new FoldExpression(isLeftFold, operatorName, new PackedTemplateParameterExpansion(expression), initializer);
- }
- // ::= cv <type> <expression> # type (expression), conversion with one argument
- // ::= cv <type> _ <expression>* E # type (expr-list), conversion with other than one argument
- private BaseNode ParseConversionExpression()
- {
- if (!ConsumeIf("cv"))
- {
- return null;
- }
- bool canParseTemplateArgsBackup = _canParseTemplateArgs;
- _canParseTemplateArgs = false;
- BaseNode type = ParseType();
- _canParseTemplateArgs = canParseTemplateArgsBackup;
- if (type == null)
- {
- return null;
- }
- List<BaseNode> expressions = new();
- if (ConsumeIf("_"))
- {
- while (!ConsumeIf("E"))
- {
- BaseNode expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- expressions.Add(expression);
- }
- }
- else
- {
- BaseNode expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- expressions.Add(expression);
- }
- return new ConversionExpression(type, new NodeArray(expressions));
- }
- private BaseNode ParseBinaryExpression(string name)
- {
- BaseNode leftPart = ParseExpression();
- if (leftPart == null)
- {
- return null;
- }
- BaseNode rightPart = ParseExpression();
- if (rightPart == null)
- {
- return null;
- }
- return new BinaryExpression(leftPart, name, rightPart);
- }
- private BaseNode ParsePrefixExpression(string name)
- {
- BaseNode expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new PrefixExpression(name, expression);
- }
- // <braced-expression> ::= <expression>
- // ::= di <field source-name> <braced-expression> # .name = expr
- // ::= dx <index expression> <braced-expression> # [expr] = expr
- // ::= dX <range begin expression> <range end expression> <braced-expression>
- // # [expr ... expr] = expr
- private BaseNode ParseBracedExpression()
- {
- if (Peek() == 'd')
- {
- BaseNode bracedExpressionNode;
- switch (Peek(1))
- {
- case 'i':
- _position += 2;
- BaseNode field = ParseSourceName();
- if (field == null)
- {
- return null;
- }
- bracedExpressionNode = ParseBracedExpression();
- if (bracedExpressionNode == null)
- {
- return null;
- }
- return new BracedExpression(field, bracedExpressionNode, false);
- case 'x':
- _position += 2;
- BaseNode index = ParseExpression();
- if (index == null)
- {
- return null;
- }
- bracedExpressionNode = ParseBracedExpression();
- if (bracedExpressionNode == null)
- {
- return null;
- }
- return new BracedExpression(index, bracedExpressionNode, true);
- case 'X':
- _position += 2;
- BaseNode rangeBeginExpression = ParseExpression();
- if (rangeBeginExpression == null)
- {
- return null;
- }
- BaseNode rangeEndExpression = ParseExpression();
- if (rangeEndExpression == null)
- {
- return null;
- }
- bracedExpressionNode = ParseBracedExpression();
- if (bracedExpressionNode == null)
- {
- return null;
- }
- return new BracedRangeExpression(rangeBeginExpression, rangeEndExpression, bracedExpressionNode);
- }
- }
- return ParseExpression();
- }
- // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
- // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
- // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
- // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
- //
- // <initializer> ::= pi <expression>* E # parenthesized initialization
- private BaseNode ParseNewExpression()
- {
- bool isGlobal = ConsumeIf("gs");
- bool isArray = Peek(1) == 'a';
- if (!ConsumeIf("nw") || !ConsumeIf("na"))
- {
- return null;
- }
- List<BaseNode> expressions = new();
- List<BaseNode> initializers = new();
- while (!ConsumeIf("_"))
- {
- BaseNode expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- expressions.Add(expression);
- }
- BaseNode typeNode = ParseType();
- if (typeNode == null)
- {
- return null;
- }
- if (ConsumeIf("pi"))
- {
- while (!ConsumeIf("E"))
- {
- BaseNode initializer = ParseExpression();
- if (initializer == null)
- {
- return null;
- }
- initializers.Add(initializer);
- }
- }
- else if (!ConsumeIf("E"))
- {
- return null;
- }
- return new NewExpression(new NodeArray(expressions), typeNode, new NodeArray(initializers), isGlobal, isArray);
- }
- // <expression> ::= <unary operator-name> <expression>
- // ::= <binary operator-name> <expression> <expression>
- // ::= <ternary operator-name> <expression> <expression> <expression>
- // ::= pp_ <expression> # prefix ++
- // ::= mm_ <expression> # prefix --
- // ::= cl <expression>+ E # expression (expr-list), call
- // ::= cv <type> <expression> # type (expression), conversion with one argument
- // ::= cv <type> _ <expression>* E # type (expr-list), conversion with other than one argument
- // ::= tl <type> <braced-expression>* E # type {expr-list}, conversion with braced-init-list argument
- // ::= il <braced-expression>* E # {expr-list}, braced-init-list in any other context
- // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
- // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
- // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
- // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
- // ::= [gs] dl <expression> # delete expression
- // ::= [gs] da <expression> # delete[] expression
- // ::= dc <type> <expression> # dynamic_cast<type> (expression)
- // ::= sc <type> <expression> # static_cast<type> (expression)
- // ::= cc <type> <expression> # const_cast<type> (expression)
- // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
- // ::= ti <type> # typeid (type)
- // ::= te <expression> # typeid (expression)
- // ::= st <type> # sizeof (type)
- // ::= sz <expression> # sizeof (expression)
- // ::= at <type> # alignof (type)
- // ::= az <expression> # alignof (expression)
- // ::= nx <expression> # noexcept (expression)
- // ::= <template-param>
- // ::= <function-param>
- // ::= dt <expression> <unresolved-name> # expr.name
- // ::= pt <expression> <unresolved-name> # expr->name
- // ::= ds <expression> <expression> # expr.*expr
- // ::= sZ <template-param> # sizeof...(T), size of a template parameter pack
- // ::= sZ <function-param> # sizeof...(parameter), size of a function parameter pack
- // ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
- // ::= sp <expression> # expression..., pack expansion
- // ::= tw <expression> # throw expression
- // ::= tr # throw with no operand (rethrow)
- // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
- // # freestanding dependent name (e.g., T::x),
- // # objectless nonstatic member reference
- // ::= <expr-primary>
- private BaseNode ParseExpression()
- {
- bool isGlobal = ConsumeIf("gs");
- BaseNode expression;
- if (Count() < 2)
- {
- return null;
- }
- switch (Peek())
- {
- case 'L':
- return ParseExpressionPrimary();
- case 'T':
- return ParseTemplateParam();
- case 'f':
- char c = Peek(1);
- if (c == 'p' || (c == 'L' && char.IsDigit(Peek(2))))
- {
- return ParseFunctionParameter();
- }
- return ParseFoldExpression();
- case 'a':
- switch (Peek(1))
- {
- case 'a':
- _position += 2;
- return ParseBinaryExpression("&&");
- case 'd':
- case 'n':
- _position += 2;
- return ParseBinaryExpression("&");
- case 'N':
- _position += 2;
- return ParseBinaryExpression("&=");
- case 'S':
- _position += 2;
- return ParseBinaryExpression("=");
- case 't':
- _position += 2;
- BaseNode type = ParseType();
- if (type == null)
- {
- return null;
- }
- return new EnclosedExpression("alignof (", type, ")");
- case 'z':
- _position += 2;
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new EnclosedExpression("alignof (", expression, ")");
- }
- return null;
- case 'c':
- switch (Peek(1))
- {
- case 'c':
- _position += 2;
- BaseNode to = ParseType();
- if (to == null)
- {
- return null;
- }
- BaseNode from = ParseExpression();
- if (from == null)
- {
- return null;
- }
- return new CastExpression("const_cast", to, from);
- case 'l':
- _position += 2;
- BaseNode callee = ParseExpression();
- if (callee == null)
- {
- return null;
- }
- List<BaseNode> names = new();
- while (!ConsumeIf("E"))
- {
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- names.Add(expression);
- }
- return new CallExpression(callee, names);
- case 'm':
- _position += 2;
- return ParseBinaryExpression(",");
- case 'o':
- _position += 2;
- return ParsePrefixExpression("~");
- case 'v':
- return ParseConversionExpression();
- }
- return null;
- case 'd':
- BaseNode leftNode;
- BaseNode rightNode;
- switch (Peek(1))
- {
- case 'a':
- _position += 2;
- expression = ParseExpression();
- if (expression == null)
- {
- return expression;
- }
- return new DeleteExpression(expression, isGlobal, true);
- case 'c':
- _position += 2;
- BaseNode type = ParseType();
- if (type == null)
- {
- return null;
- }
- expression = ParseExpression();
- if (expression == null)
- {
- return expression;
- }
- return new CastExpression("dynamic_cast", type, expression);
- case 'e':
- _position += 2;
- return ParsePrefixExpression("*");
- case 'l':
- _position += 2;
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new DeleteExpression(expression, isGlobal, false);
- case 'n':
- return ParseUnresolvedName();
- case 's':
- _position += 2;
- leftNode = ParseExpression();
- if (leftNode == null)
- {
- return null;
- }
- rightNode = ParseExpression();
- if (rightNode == null)
- {
- return null;
- }
- return new MemberExpression(leftNode, ".*", rightNode);
- case 't':
- _position += 2;
- leftNode = ParseExpression();
- if (leftNode == null)
- {
- return null;
- }
- rightNode = ParseExpression();
- if (rightNode == null)
- {
- return null;
- }
- return new MemberExpression(leftNode, ".", rightNode);
- case 'v':
- _position += 2;
- return ParseBinaryExpression("/");
- case 'V':
- _position += 2;
- return ParseBinaryExpression("/=");
- }
- return null;
- case 'e':
- switch (Peek(1))
- {
- case 'o':
- _position += 2;
- return ParseBinaryExpression("^");
- case 'O':
- _position += 2;
- return ParseBinaryExpression("^=");
- case 'q':
- _position += 2;
- return ParseBinaryExpression("==");
- }
- return null;
- case 'g':
- switch (Peek(1))
- {
- case 'e':
- _position += 2;
- return ParseBinaryExpression(">=");
- case 't':
- _position += 2;
- return ParseBinaryExpression(">");
- }
- return null;
- case 'i':
- switch (Peek(1))
- {
- case 'x':
- _position += 2;
- BaseNode Base = ParseExpression();
- if (Base == null)
- {
- return null;
- }
- BaseNode subscript = ParseExpression();
- if (Base == null)
- {
- return null;
- }
- return new ArraySubscriptingExpression(Base, subscript);
- case 'l':
- _position += 2;
- List<BaseNode> bracedExpressions = new();
- while (!ConsumeIf("E"))
- {
- expression = ParseBracedExpression();
- if (expression == null)
- {
- return null;
- }
- bracedExpressions.Add(expression);
- }
- return new InitListExpression(null, bracedExpressions);
- }
- return null;
- case 'l':
- switch (Peek(1))
- {
- case 'e':
- _position += 2;
- return ParseBinaryExpression("<=");
- case 's':
- _position += 2;
- return ParseBinaryExpression("<<");
- case 'S':
- _position += 2;
- return ParseBinaryExpression("<<=");
- case 't':
- _position += 2;
- return ParseBinaryExpression("<");
- }
- return null;
- case 'm':
- switch (Peek(1))
- {
- case 'i':
- _position += 2;
- return ParseBinaryExpression("-");
- case 'I':
- _position += 2;
- return ParseBinaryExpression("-=");
- case 'l':
- _position += 2;
- return ParseBinaryExpression("*");
- case 'L':
- _position += 2;
- return ParseBinaryExpression("*=");
- case 'm':
- _position += 2;
- if (ConsumeIf("_"))
- {
- return ParsePrefixExpression("--");
- }
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new PostfixExpression(expression, "--");
- }
- return null;
- case 'n':
- switch (Peek(1))
- {
- case 'a':
- case 'w':
- _position += 2;
- return ParseNewExpression();
- case 'e':
- _position += 2;
- return ParseBinaryExpression("!=");
- case 'g':
- _position += 2;
- return ParsePrefixExpression("-");
- case 't':
- _position += 2;
- return ParsePrefixExpression("!");
- case 'x':
- _position += 2;
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new EnclosedExpression("noexcept (", expression, ")");
- }
- return null;
- case 'o':
- switch (Peek(1))
- {
- case 'n':
- return ParseUnresolvedName();
- case 'o':
- _position += 2;
- return ParseBinaryExpression("||");
- case 'r':
- _position += 2;
- return ParseBinaryExpression("|");
- case 'R':
- _position += 2;
- return ParseBinaryExpression("|=");
- }
- return null;
- case 'p':
- switch (Peek(1))
- {
- case 'm':
- _position += 2;
- return ParseBinaryExpression("->*");
- case 'l':
- case 's':
- _position += 2;
- return ParseBinaryExpression("+");
- case 'L':
- _position += 2;
- return ParseBinaryExpression("+=");
- case 'p':
- _position += 2;
- if (ConsumeIf("_"))
- {
- return ParsePrefixExpression("++");
- }
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new PostfixExpression(expression, "++");
- case 't':
- _position += 2;
- leftNode = ParseExpression();
- if (leftNode == null)
- {
- return null;
- }
- rightNode = ParseExpression();
- if (rightNode == null)
- {
- return null;
- }
- return new MemberExpression(leftNode, "->", rightNode);
- }
- return null;
- case 'q':
- if (Peek(1) == 'u')
- {
- _position += 2;
- BaseNode condition = ParseExpression();
- if (condition == null)
- {
- return null;
- }
- leftNode = ParseExpression();
- if (leftNode == null)
- {
- return null;
- }
- rightNode = ParseExpression();
- if (rightNode == null)
- {
- return null;
- }
- return new ConditionalExpression(condition, leftNode, rightNode);
- }
- return null;
- case 'r':
- switch (Peek(1))
- {
- case 'c':
- _position += 2;
- BaseNode to = ParseType();
- if (to == null)
- {
- return null;
- }
- BaseNode from = ParseExpression();
- if (from == null)
- {
- return null;
- }
- return new CastExpression("reinterpret_cast", to, from);
- case 'm':
- _position += 2;
- return ParseBinaryExpression("%");
- case 'M':
- _position += 2;
- return ParseBinaryExpression("%");
- case 's':
- _position += 2;
- return ParseBinaryExpression(">>");
- case 'S':
- _position += 2;
- return ParseBinaryExpression(">>=");
- }
- return null;
- case 's':
- switch (Peek(1))
- {
- case 'c':
- _position += 2;
- BaseNode to = ParseType();
- if (to == null)
- {
- return null;
- }
- BaseNode from = ParseExpression();
- if (from == null)
- {
- return null;
- }
- return new CastExpression("static_cast", to, from);
- case 'p':
- _position += 2;
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new PackedTemplateParameterExpansion(expression);
- case 'r':
- return ParseUnresolvedName();
- case 't':
- _position += 2;
- BaseNode enclosedType = ParseType();
- if (enclosedType == null)
- {
- return null;
- }
- return new EnclosedExpression("sizeof (", enclosedType, ")");
- case 'z':
- _position += 2;
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new EnclosedExpression("sizeof (", expression, ")");
- case 'Z':
- _position += 2;
- BaseNode sizeofParamNode;
- switch (Peek())
- {
- case 'T':
- // FIXME: ??? Not entire sure if it's right
- sizeofParamNode = ParseFunctionParameter();
- if (sizeofParamNode == null)
- {
- return null;
- }
- return new EnclosedExpression("sizeof...(", new PackedTemplateParameterExpansion(sizeofParamNode), ")");
- case 'f':
- sizeofParamNode = ParseFunctionParameter();
- if (sizeofParamNode == null)
- {
- return null;
- }
- return new EnclosedExpression("sizeof...(", sizeofParamNode, ")");
- }
- return null;
- case 'P':
- _position += 2;
- List<BaseNode> arguments = new();
- while (!ConsumeIf("E"))
- {
- BaseNode argument = ParseTemplateArgument();
- if (argument == null)
- {
- return null;
- }
- arguments.Add(argument);
- }
- return new EnclosedExpression("sizeof...(", new NodeArray(arguments), ")");
- }
- return null;
- case 't':
- switch (Peek(1))
- {
- case 'e':
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new EnclosedExpression("typeid (", expression, ")");
- case 't':
- BaseNode enclosedType = ParseExpression();
- if (enclosedType == null)
- {
- return null;
- }
- return new EnclosedExpression("typeid (", enclosedType, ")");
- case 'l':
- _position += 2;
- BaseNode typeNode = ParseType();
- if (typeNode == null)
- {
- return null;
- }
- List<BaseNode> bracedExpressions = new();
- while (!ConsumeIf("E"))
- {
- expression = ParseBracedExpression();
- if (expression == null)
- {
- return null;
- }
- bracedExpressions.Add(expression);
- }
- return new InitListExpression(typeNode, bracedExpressions);
- case 'r':
- _position += 2;
- return new NameType("throw");
- case 'w':
- _position += 2;
- expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- return new ThrowExpression(expression);
- }
- return null;
- }
- if (char.IsDigit(Peek()))
- {
- return ParseUnresolvedName();
- }
- return null;
- }
- private BaseNode ParseIntegerLiteral(string literalName)
- {
- string number = ParseNumber(true);
- if (number == null || number.Length == 0 || !ConsumeIf("E"))
- {
- return null;
- }
- return new IntegerLiteral(literalName, number);
- }
- // <expr-primary> ::= L <type> <value number> E # integer literal
- // ::= L <type> <value float> E # floating literal (TODO)
- // ::= L <string type> E # string literal
- // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
- // ::= L <pointer type> 0 E # null pointer template argument
- // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
- // ::= L _Z <encoding> E # external name
- private BaseNode ParseExpressionPrimary()
- {
- if (!ConsumeIf("L"))
- {
- return null;
- }
- switch (Peek())
- {
- case 'w':
- _position++;
- return ParseIntegerLiteral("wchar_t");
- case 'b':
- if (ConsumeIf("b0E"))
- {
- return new NameType("false", NodeType.BooleanExpression);
- }
- if (ConsumeIf("b1E"))
- {
- return new NameType("true", NodeType.BooleanExpression);
- }
- return null;
- case 'c':
- _position++;
- return ParseIntegerLiteral("char");
- case 'a':
- _position++;
- return ParseIntegerLiteral("signed char");
- case 'h':
- _position++;
- return ParseIntegerLiteral("unsigned char");
- case 's':
- _position++;
- return ParseIntegerLiteral("short");
- case 't':
- _position++;
- return ParseIntegerLiteral("unsigned short");
- case 'i':
- _position++;
- return ParseIntegerLiteral(string.Empty);
- case 'j':
- _position++;
- return ParseIntegerLiteral("u");
- case 'l':
- _position++;
- return ParseIntegerLiteral("l");
- case 'm':
- _position++;
- return ParseIntegerLiteral("ul");
- case 'x':
- _position++;
- return ParseIntegerLiteral("ll");
- case 'y':
- _position++;
- return ParseIntegerLiteral("ull");
- case 'n':
- _position++;
- return ParseIntegerLiteral("__int128");
- case 'o':
- _position++;
- return ParseIntegerLiteral("unsigned __int128");
- case 'd':
- case 'e':
- case 'f':
- // TODO: floating literal
- return null;
- case '_':
- if (ConsumeIf("_Z"))
- {
- BaseNode encoding = ParseEncoding();
- if (encoding != null && ConsumeIf("E"))
- {
- return encoding;
- }
- }
- return null;
- case 'T':
- return null;
- default:
- BaseNode type = ParseType();
- if (type == null)
- {
- return null;
- }
- string number = ParseNumber();
- if (number == null || number.Length == 0 || !ConsumeIf("E"))
- {
- return null;
- }
- return new IntegerCastExpression(type, number);
- }
- }
- // <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
- // ::= DT <expression> E # decltype of an expression (C++0x)
- private BaseNode ParseDecltype()
- {
- if (!ConsumeIf("D") || (!ConsumeIf("t") && !ConsumeIf("T")))
- {
- return null;
- }
- BaseNode expression = ParseExpression();
- if (expression == null)
- {
- return null;
- }
- if (!ConsumeIf("E"))
- {
- return null;
- }
- return new EnclosedExpression("decltype(", expression, ")");
- }
- // <template-param> ::= T_ # first template parameter
- // ::= T <parameter-2 non-negative number> _
- // <template-template-param> ::= <template-param>
- // ::= <substitution>
- private BaseNode ParseTemplateParam()
- {
- if (!ConsumeIf("T"))
- {
- return null;
- }
- int index = 0;
- if (!ConsumeIf("_"))
- {
- index = ParsePositiveNumber();
- if (index < 0)
- {
- return null;
- }
- index++;
- if (!ConsumeIf("_"))
- {
- return null;
- }
- }
- // 5.1.8: TODO: lambda?
- // if (IsParsingLambdaParameters)
- // return new NameType("auto");
- if (_canForwardTemplateReference)
- {
- ForwardTemplateReference forwardTemplateReference = new(index);
- _forwardTemplateReferenceList.Add(forwardTemplateReference);
- return forwardTemplateReference;
- }
- if (index >= _templateParamList.Count)
- {
- return null;
- }
- return _templateParamList[index];
- }
- // <template-args> ::= I <template-arg>+ E
- private BaseNode ParseTemplateArguments(bool hasContext = false)
- {
- if (!ConsumeIf("I"))
- {
- return null;
- }
- if (hasContext)
- {
- _templateParamList.Clear();
- }
- List<BaseNode> args = new();
- while (!ConsumeIf("E"))
- {
- if (hasContext)
- {
- List<BaseNode> templateParamListTemp = new(_templateParamList);
- BaseNode templateArgument = ParseTemplateArgument();
- _templateParamList = templateParamListTemp;
- if (templateArgument == null)
- {
- return null;
- }
- args.Add(templateArgument);
- if (templateArgument.GetType().Equals(NodeType.PackedTemplateArgument))
- {
- templateArgument = new PackedTemplateParameter(((NodeArray)templateArgument).Nodes);
- }
- _templateParamList.Add(templateArgument);
- }
- else
- {
- BaseNode templateArgument = ParseTemplateArgument();
- if (templateArgument == null)
- {
- return null;
- }
- args.Add(templateArgument);
- }
- }
- return new TemplateArguments(args);
- }
- // <template-arg> ::= <type> # type or template
- // ::= X <expression> E # expression
- // ::= <expr-primary> # simple expressions
- // ::= J <template-arg>* E # argument pack
- private BaseNode ParseTemplateArgument()
- {
- switch (Peek())
- {
- // X <expression> E
- case 'X':
- _position++;
- BaseNode expression = ParseExpression();
- if (expression == null || !ConsumeIf("E"))
- {
- return null;
- }
- return expression;
- // <expr-primary>
- case 'L':
- return ParseExpressionPrimary();
- // J <template-arg>* E
- case 'J':
- _position++;
- List<BaseNode> templateArguments = new();
- while (!ConsumeIf("E"))
- {
- BaseNode templateArgument = ParseTemplateArgument();
- if (templateArgument == null)
- {
- return null;
- }
- templateArguments.Add(templateArgument);
- }
- return new NodeArray(templateArguments, NodeType.PackedTemplateArgument);
- // <type>
- default:
- return ParseType();
- }
- }
- class NameParserContext
- {
- public CvType Cv;
- public SimpleReferenceType Ref;
- public bool FinishWithTemplateArguments;
- public bool CtorDtorConversion;
- }
- // <unresolved-type> ::= <template-param> [ <template-args> ] # T:: or T<X,Y>::
- // ::= <decltype> # decltype(p)::
- // ::= <substitution>
- private BaseNode ParseUnresolvedType()
- {
- if (Peek() == 'T')
- {
- BaseNode templateParam = ParseTemplateParam();
- if (templateParam == null)
- {
- return null;
- }
- _substitutionList.Add(templateParam);
- return templateParam;
- }
- else if (Peek() == 'D')
- {
- BaseNode declType = ParseDecltype();
- if (declType == null)
- {
- return null;
- }
- _substitutionList.Add(declType);
- return declType;
- }
- return ParseSubstitution();
- }
- // <simple-id> ::= <source-name> [ <template-args> ]
- private BaseNode ParseSimpleId()
- {
- BaseNode sourceName = ParseSourceName();
- if (sourceName == null)
- {
- return null;
- }
- if (Peek() == 'I')
- {
- BaseNode templateArguments = ParseTemplateArguments();
- if (templateArguments == null)
- {
- return null;
- }
- return new NameTypeWithTemplateArguments(sourceName, templateArguments);
- }
- return sourceName;
- }
- // <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
- // ::= <simple-id> # e.g., ~A<2*N>
- private BaseNode ParseDestructorName()
- {
- BaseNode node;
- if (char.IsDigit(Peek()))
- {
- node = ParseSimpleId();
- }
- else
- {
- node = ParseUnresolvedType();
- }
- if (node == null)
- {
- return null;
- }
- return new DtorName(node);
- }
- // <base-unresolved-name> ::= <simple-id> # unresolved name
- // extension ::= <operator-name> # unresolved operator-function-id
- // extension ::= <operator-name> <template-args> # unresolved operator template-id
- // ::= on <operator-name> # unresolved operator-function-id
- // ::= on <operator-name> <template-args> # unresolved operator template-id
- // ::= dn <destructor-name> # destructor or pseudo-destructor;
- // # e.g. ~X or ~X<N-1>
- private BaseNode ParseBaseUnresolvedName()
- {
- if (char.IsDigit(Peek()))
- {
- return ParseSimpleId();
- }
- else if (ConsumeIf("dn"))
- {
- return ParseDestructorName();
- }
- ConsumeIf("on");
- BaseNode operatorName = ParseOperatorName(null);
- if (operatorName == null)
- {
- return null;
- }
- if (Peek() == 'I')
- {
- BaseNode templateArguments = ParseTemplateArguments();
- if (templateArguments == null)
- {
- return null;
- }
- return new NameTypeWithTemplateArguments(operatorName, templateArguments);
- }
- return operatorName;
- }
- // <unresolved-name> ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
- // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
- // ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
- // # T::N::x /decltype(p)::N::x
- // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
- // # A::x, N::y, A<T>::z; "gs" means leading "::"
- private BaseNode ParseUnresolvedName(NameParserContext context = null)
- {
- BaseNode result = null;
- if (ConsumeIf("srN"))
- {
- result = ParseUnresolvedType();
- if (result == null)
- {
- return null;
- }
- if (Peek() == 'I')
- {
- BaseNode templateArguments = ParseTemplateArguments();
- if (templateArguments == null)
- {
- return null;
- }
- result = new NameTypeWithTemplateArguments(result, templateArguments);
- if (result == null)
- {
- return null;
- }
- }
- while (!ConsumeIf("E"))
- {
- BaseNode simpleId = ParseSimpleId();
- if (simpleId == null)
- {
- return null;
- }
- result = new QualifiedName(result, simpleId);
- if (result == null)
- {
- return null;
- }
- }
- BaseNode baseName = ParseBaseUnresolvedName();
- if (baseName == null)
- {
- return null;
- }
- return new QualifiedName(result, baseName);
- }
- bool isGlobal = ConsumeIf("gs");
- // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
- if (!ConsumeIf("sr"))
- {
- result = ParseBaseUnresolvedName();
- if (result == null)
- {
- return null;
- }
- if (isGlobal)
- {
- result = new GlobalQualifiedName(result);
- }
- return result;
- }
- // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
- if (char.IsDigit(Peek()))
- {
- do
- {
- BaseNode qualifier = ParseSimpleId();
- if (qualifier == null)
- {
- return null;
- }
- if (result != null)
- {
- result = new QualifiedName(result, qualifier);
- }
- else if (isGlobal)
- {
- result = new GlobalQualifiedName(qualifier);
- }
- else
- {
- result = qualifier;
- }
- if (result == null)
- {
- return null;
- }
- } while (!ConsumeIf("E"));
- }
- // ::= sr <unresolved-type> [template-args] <base-unresolved-name> # T::x / decltype(p)::x
- else
- {
- result = ParseUnresolvedType();
- if (result == null)
- {
- return null;
- }
- if (Peek() == 'I')
- {
- BaseNode templateArguments = ParseTemplateArguments();
- if (templateArguments == null)
- {
- return null;
- }
- result = new NameTypeWithTemplateArguments(result, templateArguments);
- if (result == null)
- {
- return null;
- }
- }
- }
- if (result == null)
- {
- return null;
- }
- BaseNode baseUnresolvedName = ParseBaseUnresolvedName();
- if (baseUnresolvedName == null)
- {
- return null;
- }
- return new QualifiedName(result, baseUnresolvedName);
- }
- // <unscoped-name> ::= <unqualified-name>
- // ::= St <unqualified-name> # ::std::
- private BaseNode ParseUnscopedName(NameParserContext context)
- {
- if (ConsumeIf("St"))
- {
- BaseNode unresolvedName = ParseUnresolvedName(context);
- if (unresolvedName == null)
- {
- return null;
- }
- return new StdQualifiedName(unresolvedName);
- }
- return ParseUnresolvedName(context);
- }
- // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix (TODO)> <unqualified-name> E
- // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix (TODO)> <template-args (TODO)> E
- private BaseNode ParseNestedName(NameParserContext context)
- {
- // Impossible in theory
- if (Consume() != 'N')
- {
- return null;
- }
- BaseNode result = null;
- CvType cv = new(ParseCvQualifiers(), null);
- if (context != null)
- {
- context.Cv = cv;
- }
- SimpleReferenceType Ref = ParseRefQualifiers();
- if (context != null)
- {
- context.Ref = Ref;
- }
- if (ConsumeIf("St"))
- {
- result = new NameType("std");
- }
- while (!ConsumeIf("E"))
- {
- // <data-member-prefix> end
- if (ConsumeIf("M"))
- {
- if (result == null)
- {
- return null;
- }
- continue;
- }
- char c = Peek();
- // TODO: template args
- if (c == 'T')
- {
- BaseNode templateParam = ParseTemplateParam();
- if (templateParam == null)
- {
- return null;
- }
- result = CreateNameNode(result, templateParam, context);
- _substitutionList.Add(result);
- continue;
- }
- // <template-prefix> <template-args>
- if (c == 'I')
- {
- BaseNode templateArgument = ParseTemplateArguments(context != null);
- if (templateArgument == null || result == null)
- {
- return null;
- }
- result = new NameTypeWithTemplateArguments(result, templateArgument);
- if (context != null)
- {
- context.FinishWithTemplateArguments = true;
- }
- _substitutionList.Add(result);
- continue;
- }
- // <decltype>
- if (c == 'D' && (Peek(1) == 't' || Peek(1) == 'T'))
- {
- BaseNode decltype = ParseDecltype();
- if (decltype == null)
- {
- return null;
- }
- result = CreateNameNode(result, decltype, context);
- _substitutionList.Add(result);
- continue;
- }
- // <substitution>
- if (c == 'S' && Peek(1) != 't')
- {
- BaseNode substitution = ParseSubstitution();
- if (substitution == null)
- {
- return null;
- }
- result = CreateNameNode(result, substitution, context);
- if (result != substitution)
- {
- _substitutionList.Add(substitution);
- }
- continue;
- }
- // <ctor-dtor-name> of ParseUnqualifiedName
- if (c == 'C' || (c == 'D' && Peek(1) != 'C'))
- {
- // We cannot have nothing before this
- if (result == null)
- {
- return null;
- }
- BaseNode ctOrDtorName = ParseCtorDtorName(context, result);
- if (ctOrDtorName == null)
- {
- return null;
- }
- result = CreateNameNode(result, ctOrDtorName, context);
- // TODO: ABI Tags (before)
- if (result == null)
- {
- return null;
- }
- _substitutionList.Add(result);
- continue;
- }
- BaseNode unqualifiedName = ParseUnqualifiedName(context);
- if (unqualifiedName == null)
- {
- return null;
- }
- result = CreateNameNode(result, unqualifiedName, context);
- _substitutionList.Add(result);
- }
- if (result == null || _substitutionList.Count == 0)
- {
- return null;
- }
- _substitutionList.RemoveAt(_substitutionList.Count - 1);
- return result;
- }
- // <discriminator> ::= _ <non-negative number> # when number < 10
- // ::= __ <non-negative number> _ # when number >= 10
- private void ParseDiscriminator()
- {
- if (Count() == 0)
- {
- return;
- }
- // We ignore the discriminator, we don't need it.
- if (ConsumeIf("_"))
- {
- ConsumeIf("_");
- while (char.IsDigit(Peek()) && Count() != 0)
- {
- Consume();
- }
- ConsumeIf("_");
- }
- }
- // <local-name> ::= Z <function encoding> E <entity name> [<discriminator>]
- // ::= Z <function encoding> E s [<discriminator>]
- // ::= Z <function encoding> Ed [ <parameter number> ] _ <entity name>
- private BaseNode ParseLocalName(NameParserContext context)
- {
- if (!ConsumeIf("Z"))
- {
- return null;
- }
- BaseNode encoding = ParseEncoding();
- if (encoding == null || !ConsumeIf("E"))
- {
- return null;
- }
- BaseNode entityName;
- if (ConsumeIf("s"))
- {
- ParseDiscriminator();
- return new LocalName(encoding, new NameType("string literal"));
- }
- else if (ConsumeIf("d"))
- {
- ParseNumber(true);
- if (!ConsumeIf("_"))
- {
- return null;
- }
- entityName = ParseName(context);
- if (entityName == null)
- {
- return null;
- }
- return new LocalName(encoding, entityName);
- }
- entityName = ParseName(context);
- if (entityName == null)
- {
- return null;
- }
- ParseDiscriminator();
- return new LocalName(encoding, entityName);
- }
- // <name> ::= <nested-name>
- // ::= <unscoped-name>
- // ::= <unscoped-template-name> <template-args>
- // ::= <local-name> # See Scope Encoding below (TODO)
- private BaseNode ParseName(NameParserContext context = null)
- {
- ConsumeIf("L");
- if (Peek() == 'N')
- {
- return ParseNestedName(context);
- }
- if (Peek() == 'Z')
- {
- return ParseLocalName(context);
- }
- if (Peek() == 'S' && Peek(1) != 't')
- {
- BaseNode substitution = ParseSubstitution();
- if (substitution == null)
- {
- return null;
- }
- if (Peek() != 'I')
- {
- return null;
- }
- BaseNode templateArguments = ParseTemplateArguments(context != null);
- if (templateArguments == null)
- {
- return null;
- }
- if (context != null)
- {
- context.FinishWithTemplateArguments = true;
- }
- return new NameTypeWithTemplateArguments(substitution, templateArguments);
- }
- BaseNode result = ParseUnscopedName(context);
- if (result == null)
- {
- return null;
- }
- if (Peek() == 'I')
- {
- _substitutionList.Add(result);
- BaseNode templateArguments = ParseTemplateArguments(context != null);
- if (templateArguments == null)
- {
- return null;
- }
- if (context != null)
- {
- context.FinishWithTemplateArguments = true;
- }
- return new NameTypeWithTemplateArguments(result, templateArguments);
- }
- return result;
- }
- private bool IsEncodingEnd()
- {
- char c = Peek();
- return Count() == 0 || c == 'E' || c == '.' || c == '_';
- }
- // <encoding> ::= <function name> <bare-function-type>
- // ::= <data name>
- // ::= <special-name>
- private BaseNode ParseEncoding()
- {
- NameParserContext context = new();
- if (Peek() == 'T' || (Peek() == 'G' && Peek(1) == 'V'))
- {
- return ParseSpecialName(context);
- }
- BaseNode name = ParseName(context);
- if (name == null)
- {
- return null;
- }
- // TODO: compute template refs here
- if (IsEncodingEnd())
- {
- return name;
- }
- // TODO: Ua9enable_ifI
- BaseNode returnType = null;
- if (!context.CtorDtorConversion && context.FinishWithTemplateArguments)
- {
- returnType = ParseType();
- if (returnType == null)
- {
- return null;
- }
- }
- if (ConsumeIf("v"))
- {
- return new EncodedFunction(name, null, context.Cv, context.Ref, null, returnType);
- }
- List<BaseNode> paramsList = new();
- // backup because that can be destroyed by parseType
- CvType cv = context.Cv;
- SimpleReferenceType Ref = context.Ref;
- while (!IsEncodingEnd())
- {
- BaseNode param = ParseType();
- if (param == null)
- {
- return null;
- }
- paramsList.Add(param);
- }
- return new EncodedFunction(name, new NodeArray(paramsList), cv, Ref, null, returnType);
- }
- // <mangled-name> ::= _Z <encoding>
- // ::= <type>
- private BaseNode Parse()
- {
- if (ConsumeIf("_Z"))
- {
- BaseNode encoding = ParseEncoding();
- if (encoding != null && Count() == 0)
- {
- return encoding;
- }
- return null;
- }
- else
- {
- BaseNode type = ParseType();
- if (type != null && Count() == 0)
- {
- return type;
- }
- return null;
- }
- }
- public static string Parse(string originalMangled)
- {
- Demangler instance = new(originalMangled);
- BaseNode resNode = instance.Parse();
- if (resNode != null)
- {
- StringWriter writer = new();
- resNode.Print(writer);
- return writer.ToString();
- }
- return originalMangled;
- }
- }
- }
|