| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast;
- namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
- {
- class Demangler
- {
- private static readonly string Base36 = "0123456789abcdefghijklmnopqrstuvwxyz";
- private List<BaseNode> _substitutionList = new List<BaseNode>();
- private List<BaseNode> _templateParamList = new List<BaseNode>();
- private List<ForwardTemplateReference> _forwardTemplateReferenceList = new List<ForwardTemplateReference>();
- public string Mangled { get; private set; }
- private int _position;
- private 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)
- {
- string mangledPart = Mangled.Substring(_position);
- if (mangledPart.StartsWith(toConsume))
- {
- _position += toConsume.Length;
- return true;
- }
- return false;
- }
- private string PeekString(int offset = 0, int length = 1)
- {
- if (_position + offset >= length)
- {
- return null;
- }
- return Mangled.Substring(_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()
- {
- string part = Mangled.Substring(_position);
- int seqIdLen = 0;
- for (; seqIdLen < part.Length; seqIdLen++)
- {
- if (!char.IsLetterOrDigit(part[seqIdLen]))
- {
- break;
- }
- }
- _position += seqIdLen;
- return FromBase36(part.Substring(0, 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 List<BaseNode>();
- 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> Params = new List<BaseNode>();
- 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;
- }
- Params.Add(type);
- }
- return new FunctionType(returnType, new NodeArray(Params), 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
- if (context == null)
- {
- context = new NameParserContext();
- }
- BaseNode result = null;
- 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 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()
- {
- string part = Mangled.Substring(_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.Substring(0, numberLength));
- }
- private string ParseNumber(bool isSigned = false)
- {
- if (isSigned)
- {
- ConsumeIf("n");
- }
- if (Count() == 0 || !char.IsDigit(Mangled[_position]))
- {
- return null;
- }
- string part = Mangled.Substring(_position);
- int numberLength = 0;
- for (; numberLength < part.Length; numberLength++)
- {
- if (!char.IsDigit(part[numberLength]))
- {
- break;
- }
- }
- _position += numberLength;
- return part.Substring(0, 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)
- {
- ((SpecialSubstitution)prev).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 = null;
- 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)
- {
- BaseNode temp = expression;
- expression = initializer;
- initializer = temp;
- }
- 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 List<BaseNode>();
- 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>();
- List<BaseNode> initializers = new List<BaseNode>();
- 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 = null;
- 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 List<BaseNode>();
- 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 = null;
- BaseNode rightNode = null;
- 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 List<BaseNode>();
- 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 = null;
- 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 List<BaseNode>();
- 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 List<BaseNode>();
- 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("");
- 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 ForwardTemplateReference(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 List<BaseNode>();
- while (!ConsumeIf("E"))
- {
- if (hasContext)
- {
- List<BaseNode> templateParamListTemp = new List<BaseNode>(_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 List<BaseNode>();
- 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> [tempate-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 CvType(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 NameParserContext();
- 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> Params = new List<BaseNode>();
- // 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;
- }
- Params.Add(param);
- }
- return new EncodedFunction(name, new NodeArray(Params), 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 Demangler(originalMangled);
- BaseNode resNode = instance.Parse();
- if (resNode != null)
- {
- StringWriter writer = new StringWriter();
- resNode.Print(writer);
- return writer.ToString();
- }
- return originalMangled;
- }
- }
- }
|