| 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 BASE_36 = "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)
- {
- this.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 = BASE_36.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;
- }
- }
- }
|